読書メモ:システム設計の面接試験②

この記事の続き

目次

6章:キーバリューストアの設計

正直かなり微妙な章でした。RedisやCassandraなどの内部設計が頭に入ってれば読みとばして良い気がしました。

  • 日本語訳が微妙
  • CAP定理などの微妙な定理をいまだに利用して分散システムを考える

前者は内容というより訳者の問題でしょうか。和訳だと「結果整合性」と訳すべきであろうところを「最終的な一貫性」と訳してる部分があって、一般的に利用されている訳語があるならそっちを使うべきかなと…

後半は内容的な話です。この本は分散システムに関しての書籍ではないので分散システムの解説に多くの書面を割く必要はないのだとは思いますが、やっぱこの紙面だと微妙な内容にならざるを得ないのかなと感じました。

出てくるトピック

  • CAP定理
  • クオラムの話
  • ハートビートの話
  • SSTable(ほぼ単語が出てくるだけ)

この辺の話は分散システムの非常に奥深い話が入ってくる部分で、真面目に勉強するならデータ指向アプリケーションデザインを読むのがよさそうだと感じました。

7章:分散システムにおけるユニークIDジェネレータの設計

DatabaseのPrimary Keyをどう作るのか?と読み替えてよさそうな章です。短い章。紹介されてるアプローチは以下の4つ。

  • マルチマスター
  • UUID
  • チケットサーバ
  • twittersnowflakeアプローチ

マルチマスタ

1点目に関して、なんかこれマルチマスターっていって紹介していいんだっけ?となりました…(実装によって違うという認識を自分は持っているので)この書籍の中で紹介されていたのは、offsetを利用するアプローチです。

  • nodeは2つ
  • node1が奇数番、node2が偶数番を採番する
    • 1, 3, 5, 7….
    • 2, 4, 6, 8…
  • (ここは書かれてないが)ラウンドロビンでリクエストがバランスされるので、ええ感じにrecordが生成されまっせ、というものかと

このアプローチ以外にも1 - 10000, 2 - 20000…といった具合にsegmentを分割してあげる、みたいなこともマルチマスターでは採用されてたりします。自分が調べた限りだと、PostgreSQL-BDRではこのアプローチを使ってマルチマスタでシーケンスを生成しています。

PostgreSQL BDR (Bi-Directional Replication) を使ってみた - Qiita

uuid

よくあるやつ。割愛。

チケットサーバ

中央サーバとして連番を返すやつを用意する。単一障害点になるのがneck。

twittersnowflakeアプローチ

初めて聞きました。timestampとノードのID、シーケンス番号を組み合わせて番号を生成するというものらしいです。

Snowflake ID

感想

平日で仕事があったのであんま読む時間を確保できず。今週中には読み終えたいです。

読書メモ:システム設計の面接試験①


先日購入した以下の書籍の読書メモです。アフィリンクとかじゃあないです。

https://amzn.asia/d/5AeSGTfamzn.asia

1章:ユーザー数0から数百万人へのスケールアップ

以下のような基本的な内容を扱っています。

  • 単一サーバーをホストした際のリクエストの流れ
  • データベース
  • 垂直スケール / 水平スケール
  • ロードバランサ
  • データベースのレプリケーション
  • キャッシュ
  • CDN
  • ステートレスとステートフル
  • データセンター
  • メッセージキュー
  • ログ
  • データベースのスケール
    • シャーディングの話とか

一番最初は非常にシンプルな構成で、Webアプリ、データベース、キャッシュなどの全てが単一のサーバーに置かれてる状況を想定して、どんどんリッチでスケーラビリティを持つ、今っぽい構成に変えていく…って流れで構成された章でした。バックエンドエンジニアなら基本的に抑えてるであろう内容だったりするので自分は流し読みしました。

一番最後にデータベースのシャーディングの話が出ているのですが、セレブ問題(特定のデータにやたらとIOが集中する問題でホットスポットキー問題などの名前がついてるらしい?)など、高度なトピックもちょろっと紹介されていたりしました。

2章:おおまかな見積もり

Googleの超天才エンジニア、ジェフ・ディーンの有名な図を引用しながら見積もりの話が導入されています。

ジェフ・ディーン

内容的には以下のサイトに載ってるもので、ざっくり各処理にどのくらいのレイテンシが期待されるかを示したものです。

Numbers Every Programmer Should Know By Year

プラスでSLO/SLAの考え方が紹介されてました。

3章:システム設計の面接時のフレームワーク

面接時の心構え的なものを説明しているのがこの章です。似たような内容の話をnoteだかMediumだったかで読んだ覚えがあります。面接官と一緒にディスカッションしながら進めようね、あとこういうふうにしちゃダメだよ、という実践的なことが書かれてる印象でした。

「言うは易し、行うは難し」という印象で、モブ面接的なことをやらないと多分自分は身につかない気がしたので転職する際にここで書かれていたことを気にしながら訓練しないとなぁと感じました。

4章:レートリミッターの設計

Ratelimitのアルゴリズムを紹介する章です。スライディングウィンドウは仕事でも利用したことのあるアルゴリズムだったので知ってましたが、rate limitにいろんなバリエーションがあるなんて知りませんでした。紹介されていたのは以下のアルゴリズムです。

  • トークバケット(Token Bucket
  • リーキーバケット(Leaky Bucket
  • 固定ウィンドウカウンタ(Fixed window counters)
  • スライディングウィンドウログ(Sliding window log)
  • スライディングウィンドウカウンタ(Sliding window counters)

それぞれ得手不得手があるのでユースケースによって使い分けることが重要。実務上ではAPI Gatewayなどの機能やプラグインとかで実現することが多い気がします。

5章:コンシステントハッシュの設計

この章に関して、自分は以前以下のブログを読んでたので頭に入ってきやすかったです。このブログを読めばこの章で書かれてることは大体理解できる気がします。

Consistent Hashing (コンシステントハッシュ法) - Carpe Diem

シャーディングやパーティショニングといったDatabaseのスケール戦略を考えるにあたり、単純にkeyをhash化したものをサーバーの台数で割ってあげて、どのサーバーに割り当てるのかを計算する、というのが素朴なシャーディングの発想です。以下の数式で表現されるもの。

 \displaystyle
serverIndex = hash(key) \hspace{2mm} \% \hspace{2mm} N

Nはサーバーの台数で、keyというのがDBに保存されるレコードのイメージです。一見よさそうに思えますが、サーバーをスケールさせたり、障害が発生して台数が減ったりした際、つまりNが変化した際にどのようなことが起こるのかを考えてみましょう。

大抵のkeyは別のサーバーに割り当てられることになります。この課題を解決するのがコンシステントハッシュと呼ばれるアルゴリズムです。

ハッシュ空間をリング上に捉え、ハッシュリング上にノードをプロットします。recordを保存するノードを選択する際に、keyをhash化し、このリング上でどこにプロットされるのかを考え、プロットされた点から時計回りに見て一番近いノードに保存する、みたいなことをやるアルゴリズムです。Wikipediaのイメージ図を拝借します。

Wikipediaより引用

ノードを追加する場合も削除する場合も、リバランスを考えなきゃならないobjectが少なく済むので楽でいいよねって発想です。

ただ2つ課題があって削除と追加を繰り返してると以下のような状況になり得ます。

これらの課題を解決する仮想ノードの紹介もされています。

1つのノードに対して、ハッシュリング上に複数のプロットを行うことで上記の課題を解決することができます。

感想

あまり「就活対策本」みたいな類の本は普段読まないし、就活をゲーム化する感覚が好きじゃあないので、感覚的には ウッとなるタイトルではあるのですが普通に勉強になるので買ってよかったです。今回読んだ前半部分に当たる章では基本的な考え方や普段利用しているComponentのアルゴリズムの紹介的な章がメインで、後半になるにつれてシステム設計っぽさが出てきます。Youtubeを設計するには?みたいな切り口で議論を展開する章とかもあるので読むのが楽しみです。

続き

JPAは組み込みDBを利用する際にテーブルを自動生成する

0. tl;dr

  • JPAは組み込みDBを利用している場合にEntityの情報などからDBとtableを自動で生成する
  • application.properties(application.yaml)のspring.jpa.hibernate.ddl-autoというプロパティで自動生成する / しないが制御される

1. はじめに / 背景

Spring Bootを利用したプロジェクトにおいて、Integration Testの実装の際にH2(組み込みのin-memory DB)とJPAを利用しているのですが、H2の初期化のために書いていたDDLスキーマと、JPA用のEntityのスキーマの整合性が取れていないにも関わらず、Testがpassしていてファ!?ってなりました。DatabaseのTableと、JPAのために記述しているEntityとの間で整合性が取れないとapplication contextの生成に失敗してしまうはずなのですが、application contextがうまく生成されるだけでなく、JPA経由でDBに値を入れたり、参照したり、というのが普通に動いてしまってました。

2. spring.jpa.hibernate.ddl-autoの設定について

結論としては、application.yamlで制御できるhibernateの設定で、自動でテーブルが生成される設定がonになっていたのが原因でした。(そんな設定があるの知らなかった)

以下、Documentより引用


By default, JPA databases are automatically created only if you use an embedded database (H2, HSQL, or Derby). You can explicitly configure JPA settings by using spring.jpa.* properties. For example, to create and drop tables you can add the following line to your application.properties:

spring.jpa.hibernate.ddl-auto=create-drop

(DeepL訳)デフォルトでは、JPAデータベースは、組み込みデータベース(H2、HSQL、Derby)を使用する場合にのみ自動的に作成されます。JPAの設定は、spring.jpa.*プロパティを使用して明示的に設定することができます。例えば、テーブルの作成と削除を行うには、application.propertiesに次の行を追加します。


JPAはH2などの組み込みデータベースを検出すると自動でデータベース(とテーブル)を生成してくれます。

以下はやや古い資料で正確性が怪しいですが、組み込みDBだとdefaultでcreate-dropが設定されているようです。create-dropではその名の通り、アプリケーション作成時にEntityに対応するテーブルがなければ作成し、セッション終了時にスキーマを削除します。

59. Database initialization

組み込みDBが検出されない場合はdefaultでnoneが設定されるので何もしません。

3. どう設定するか

下記のようにapplication.yamlでcreate teble文を記述したsqlへのパスを指定してtableを初期化するアプローチをいままではとっていました。

spring:
  sql:
    init:
      schema-locations: classpath:h2/schema.sql

DatabaseのDDLを管理しているリポジトリは別で存在し、schemaが更新される際にJPAのEntityも更新しますが、その際にH2の初期化用のDDLも更新する必要が出てきて、DDLの二重管理(場合によってはn重管理)みたくなってめんどくさい思いもあります。RepositoryのIntegration Testという文脈で捉えるなら初期化用のDDLを定義してもしなくても、依存はリポジトリの中に閉じていて本番のDBの状態からは切り離されてしまいます。

どうせ外部環境に繋がないなら自動生成をonにして、初期化用のddlなんて用意しなくて良いのでは?というお気持ちになりました(ライブラリの作者もそう思ったからdefault設定しているのでしょうし)

また、JPAの設定と実際のDBのスキーマの齟齬から疎通で失敗することの検証に関しては後続で結合試験を実施すれば検知できる課題だと思うので、個人的には自動生成に頼ってしまってDDLの管理はサボりたいなと感じました。

以上

4. Reference

spring.jpa.hibernate.ddl-auto に設定可能な値 - Qiita

Spring Boot Reference Documentation

59. Database initialization

ACIDに対する批判

はじめに

DBのDocumentを見ていると「ACID transactionをサポートしています」という説明を目にすることがあります。自分はこれを見て、「ちゃんとtransactionサポートしてんのかぁ」くらいの感想しか持ってなかったんですが、最近読んでるデータ指向アプリケーションデザインという書籍の中で、ACIDという用語はマーケティング用語だって批判をしていて軽く衝撃を受けました。データ指向アプリケーションデザインで綺麗にまとめられていた内容について備忘録的にまとめようと思います。

ACIDとは何であるか

トランザクションが保証する安全性として、Atomicity、Consistency、Isolation、Durabilityの4つがあり、これらの頭文字をとってACIDと呼ばれています。順に説明しながら批判を整理していきます。

Atomicity / 原子性

Computer Scineceの分野ではそれ以上分割できないものを指してAtomicな処理と表現されることは一般的だと自分は理解しています。並行処理、マルチスレッドプログラミングなどでも同様にatomicityは出てきますが、この文脈だと他のスレッドからatomicな操作処理の途中が見えないことを意味したりします。

一方でACIDのAtomicityは並行性と全く関係がないです。複数のプロセスがデータに同時にアクセスしようとした際に起こることを記述しているのは、I(Isolation)であってAtomicityではないです。

Atomicityが意味するところは、なんらかの原因(プロセスがクラッシュしたりNetwork障害で処理が途中で止まったり)で処理が止まった際、TransactionがCommitされなかったらAbort(中断)されることを保証することです。中途半端な状態でデータが変更されてた場合に、Transactionをリトライしちゃうと、同じ変更を2回行ってしまって意図しないデータ変更が生じるリスクがありますが、ACIDのAtomicityはこういうことがないことを保証してくれるので、アプリケーションロジックをシンプルに保つのに役立ちます。

データ指向アプリケーションデザインでは、AtomicityではなくAbortabilityを当てた方がよかっただろと批判していますが、よくよく考えると確かにそうだなあと感じました。自分は雰囲気で用語を理解してました。

Consistency / 一貫性

分散システムにおける一貫性が、文脈によって意味合いが異なることを本書では指摘しています。著者によると、少なくとも4種類はある、と…

  • レプリカ間のデータの一貫性。非同期にレプリケーションを行う場合、結果整合性は保証するがデータの”一貫性”がないタイミングというのが出てくる
  • コンシステントハッシュ法におけるコンシステント。パーティションの境界をリバランシグするための手法なのでACIDとは全く関係ない
    • 書籍ではコラムとして紹介されてますが、コラム読むだけだと何言ってるのか微妙にわかりませんでした
  • CAP定理の一貫性は線形化可能性の意味で使われる
  • ACIDの文脈における一貫性は、データベースが「良い状態」にあることを示すアプリケーション固有の概念を指す

一貫性という用語の一貫性がないですね。

ACIDの文脈でよく例に出されるのが口座の例ですね。データベースにはルールがあって、送金処理を行なったときに間違えて口座残高が負になっちゃってたりしたらダメだよね、みたいな説明が出てくるかと。Wikipediaもそんな感じの説明してます。

ACID (コンピュータ科学) - Wikipedia

これはアプリケーションの責務であってデータベースの責務ではないです。外部キー制約とかユニーク制約とかつけることで保証できるものももちろんありますが、全ては保証できません。データが適正かどうかはアプリケーションが決めることであってデータベースはデータを保存するだけ。

データベースで無理やり保証しようとすることもやりようによってはできるものもありますが、やめとけって話が書籍の中でされています。詳しくはP.271 衝突の実体化を参照してみてください。

DDLでデータに対する制約をつけられるようにする発展がDBの世界で行われたら、もしかするとDatabaseの責務として分離できることもあるのかもしれませんが、少なくとも2023年現在はアプリケーション側の責務であってデータベースの責務ではないですね。自分の知る限りは。

Isolation / 分離性

複数のプロセス、クライアントからアクセスされるケースでは並行処理における課題であるrace conditionが生じることがあります。ユーザー1とユーザー2が同時に同じrecordを更新しようとして、競合しちゃってどっちかの変更が失われたり…みたいなことですね。

Isolationはデータベースによって何をどこまで保証しているのかが異なる部分で、Read Committedやスナップショット分離(MVCC)、直列化可能性など、どういうアプローチを取っているのかでIsolationのレベルが変わってきます。

分離レベルが異なることに関しては、そうだねという感じですが、ACIDと一口にまとめるにはバラエティがありすぎじゃあないすかね…?

Durability / 永続性

この特性はデータが消えないよねってことを保証することです。Write-Ahead-Logとかで頑張るってやつですが、著者はハードウェアとバックアップが壊れちまったらデータベースに何かできるものでもないだろって批判をしてます。まあそうですね。

まとめ

ACIDトランザクションってやつがなんなのかを書籍の力を借りて備忘録的にまとめておきました。書籍の中では、トランザクションで気をかけるところは、AとIで、他はデータベースの責務じゃあないとまとめて、後続の説明に入っていきます。トランザクションの章は大変学びが多くてエキサイティングな章で面白く読んでよかったです。

2023年の目標

あけましておめでとうございます。目標をなんとなく設定しました。

目標

  • 論文を2週間に一本読む
  • エンジニアリングに関する本を月に一冊は読む
  • 英会話を始める
  • ジムに週2で通う

論文を2週間に一本読む

Computer Scienceの論文を2週に一本くらいのペースで読み続けたいなって思ってます。自分の仕事はWebアプリケーション開発なので仕事と直接は関係ないのですが、以下のような観点でやってみたいなって思ってます。

  • その分野のある程度深い知識を身につけないとそもそも読めないので、論文を読むために関連して色々な情報に触れることになる
  • 仕事の幅を広げるきっかけになる
  • 単純に楽しい

NetworkやDatabase、OS、Virtualization、etc…などの低レイヤー寄りのソフトウェアは仕事をする上で意識せずに当たり前のように使っていますが、裏側には当然アカデミックな取り組みがあります。

例えば近年だとDatabase関連のSoftwareはたくさんあって、古典的なRDBMSで言うとMySQLOracle、NoSQLだとCassandraやRedisなどがあります。また、MySQLと言っても構成の仕方にはバリエーションがあるはずで、設定によって挙動が変わってくる(と本で読みました。実際に設定したことはなし。)はずで、Replicaの戦略、リーダーは単一か、マルチリーダー構成か、トランザクションの扱いってどうなってるのか、read committedかスナップショット分離か、ダーティリードやダーティライトは起こるのか起こらないのか…とか、SQLのインターフェースだけ見てもわからないことというのはたくさんあります。

まあ業務でこの辺のチューニングをすると逆に痛い目に合うというか、結局デフォルトがええわってなる未来も見えるのですが、知った上でデフォルトを選ぶのと、知らずになんかDBをhostしてるのでは全く違います。あとたまにアプリケーション側でも知ってないとダメな知識というのはありますし…

業務を遂行する上で利用しているSoftwareを深く知っている、というのは重要なことで一流と二流の違いの一つはこういうところにあるのだと個人的には思ってます。こういう深いところに触れるきっかけとして論文を読んでみる、というのは良い試みだと個人的に思っています。大抵の場合すんなり読めないんですが、何でつまづいたのか、というのは重要なインサイトを与えてくれます。

例えば今ちょうど読んでる論文はGoogleのMegastoreと呼ばれるCloud Datastoreを支えるストレージシステムに関する論文です。

Megastore: Providing Scalable, Highly Available Storage for Interactive Services - Google Research

本当はGoogleのNewSQL、Spannerの論文を読もうとしたのですが、頻繁に利用されるMegastoreという単語が気になって、まずはそっち読むか…と横道にそれました。Megastoreを読んでいると分散合意に関する自分の知識が薄っぺらすぎて読めないことに気づきました。結果また横道にそれてPaxosについて今は勉強しています。

Paxos

とまあ基礎が疎かになってるので色んな知らないことが出てきて大変なんですが、知らないことがあることを知れた、というのは重要な気づきで、こういうのを丁寧に一つずつ潰していけば最終的には論文が読めるようになっているはずです。論文が読めるくらい知識がつけば、結果として当該分野の解像度が飛躍的に高まってるはず。

時間はかかりますが、別に趣味なので無限に時間かけていいし、勉強の一環として楽しみながら続けようと思ってます。

エンジニアリングに関する本を月に一冊は読む

こっちの目標は仕事で必要な知識のinputとして設定している方です。論文の方は比較的探索的な情報摂取ですが、こちらはOutput Drivenでの情報摂取です。最近はどちらかというと技術力で困ってるというより、仕事の進め方やチーム・組織として感じているペインにどう向き合うべきか、みたいなやや抽象度の高い課題に頭を悩ませている感じがしているので、DevOpsや組織論的な本をちょっと読んでみる年にしようかなと思っています。新規事業なので秒間10万requestを裁くプラットフォームの開発をしなければならない、みたいな技術的に難しい課題がポコポコ生えてくる感じではなく、できるだけ難しいやり方ではなくシンプルに、簡単に達成できる課題に仕事を落とし込む、というアプローチをとっている組織なだけに、抽象的なレイヤーで頭を使えないと正直微妙な評価を受けざるを得ないと感じているので。(自分が思ってるだけでテッキーな人も欲しいのかもしれませんが). 技術力も全然高いわけではないのでちょこちょこ読もうとは思っています。

英会話を始める

仕事の幅を広げる意味でやっぱ英語喋れないとなぁ…とは思ってます。未来永劫今の会社にいることはあり得ないことだと思うので、転職を考えた際、minimum requirementに「fluent English」みたいなのがあると「あ、お疲れっす。さいなら〜〜〜」ってなっちゃってアレなので…

いますぐ積極的に転職したいわけじゃないですが、やっぱその会社で働き続けることを前提としたスキルセットの組み方はロバストじゃないと思います。いつでも転職できる、が、今の環境で働くことを選んでいる状態というのが望ましいので。

ジムに週2で通う

ムキムキになるつもりはないですが健康は大事。

まとめ

「ぶっちゃけ論文が読みたい」というお気持ちが文章量に出ちゃってますが、全部ちゃんと達成できるように頑張りたいです。本年もよろしくお願いします。

入社して良かったことと悪かったこと②感想編

入社してどうだったか

前回の記事では、自分が今の会社に入社するまでの経緯をまとめてきました。こちらのPostでは、じゃあ実際入社してどうだったの?という話を書いていこうと思います。とはいえまだ一年も働いていないのでどうこう言えない部分も多いですが。

入社してからの時系列的なところはこちらでまとめてみました。

2022年の振り返り - 巨人の肩の上

記事でもちょろちょろ書いてますが、そこそこ失敗してるし、学びもあってそこそこ満足しています。研修は不満、OJTは大満足、今のお仕事も楽しい、みたいなのが率直な感想です。

大きい会社なので部署や上司に依存する話が殆どですが、以下のような感想を持ってます。

文化とか

  • 意外とやりたいことやらせてくれる雰囲気でGood。そこそこ上司依存。やりたいことを言語化しておかないと機会損失が頻繁に起こる。
  • 分業は進んでいるので事業の数字にどうcommitしたのか、成果を定量化するのは無理。エンジニアの評価は基本定性評価だと思う。
  • とにかくホワイト、ここよりホワイトな会社はない気がする。仕事したければ残れるし、今月の残業20分です、みたいな同期もごろごろいる。
    • ハードワークな文化で新卒を過ごすとそこが基準になるので、今のゆるふわでいいのかという疑問はなくはない
    • その他の文化に関してもそう、良くも悪くも仕事へのスタンスや価値観が弊社の色に染まることになる
  • 大手の新規事業はベンチャーの事業とで戦術は全く違う。主に資金と人の使い方
  • 必要なSaaSは大抵揃ってるので仕事進める上でのDX(developer experience)が悪い、みたいなことは今のところない
  • どこでも働けるのは最高
  • 上司との1 on 1を定期的に実施してくれるのでそこで色々お話を聞けて良い(他の会社でも流石にあると思いますが)
  • 必要なのはわかるが、全社対応とかは結構めんどくさい

Technicalな視点

  • Private Cloudは最低限クラウドと呼べる機能、Componentは揃ってるので割と悪くはない(とてもすごいことだと思います)
    • 中にエンジニアがいるのでお友達になって話聞けると色々面白い
    • IaaS使わずPaaS、CaaSで開発しているので運用業務はほぼないので快適
    • Public Cloudの方が流石に機能も多いので便利だし、会社に依存しないスキルセットとしてそっちの方が触りたくは正直ある
      • ただ裏にはOpenな技術(e.g. k8s)があるので抽象的には同じことをやってる
  • Java(spring)とVueを利用していて別にレガシー感はそんなない
    • Javaが嫌だって人がいると聞きますが、別にそこまでディスられるような言語なのかよくわかってないです。Springを利用した開発をする上ではクラス設計をやって親子関係がああでこうで、ぎゃー神クラスができちゃった、みたいなオブジェクト指向の負の側面が出てくることってなかなかなくないですか…?
    • とはいえ負債と呼べるものはそこそこあるので、こうしましょう、ああしましょう、という提案はちょこちょこやってます。あくまで自チーム内でクイックに意思決定できる部分だけですが
  • 全社で利用するプラットフォームに関してはDocumentがとてもよく纏まっていて体験が良い(先輩方ありがとうございます)
  • ネットワーク図とかは結構書いてる。マイクロサービス指向な感じで開発されてるのでComponent間の繋がりとかは定期的にドキュメント書いたり、新規に開発する機能で何がどう変わるのか、Componentとしてこういう関係性だよってのをある程度書いてレビューもらう文化に今のところなってる。
  • マイクロサービスにしすぎて辛いのである程度まとめる作業をしてたりもする。意思決定を横から見るだけ(+茶々入れ)で結構勉強になる。
  • クリーンアーキテクチャっぽい感じで開発しているが、自分はDDDやクリーンアーキをそこまで深く理解できていないので良し悪しの判断はできない。ややずれた話になる(?)が、ソフトウェアの構造で言うと依存性逆転の原則ぐらいは守れってのは色んなところで指摘が入るらしい。あとはそこまで方法論で揉めてるところは今のところ見たことがない。あまりにもってものは指摘が入るが。
  • 一応社内での推奨みたいなものが色々ひかれてるので基本則ってると揉めることが少なくて楽
    • なぜ推奨しているかを知らずに従うのは思考停止なので良くないが。

正しい選択をする努力と選択を正しくする努力

色々と書いてきましたが、良い点もあれば悪い点もぼちぼち目につきます。ひょっとするともっといい会社、自分に合った会社があったのかもしれません。正しい選択をする努力というのをもっとしておけば、不満が減って、良いなと思う点が増えていたかもしれないなぁ、より成長してバリバリ働けるようになってたのかもなって考えることもあったりなかったりといった感じです。

前のポストでも散々書きましたが、自分の中で何が正しいという絶対的な正解はなく、会社によって得られる経験も違うので、それぞれ良し悪しあって単純に比較するというのはとても難しいことだと思います。良い悪いというより様々なトレードオフの中からどのようなバランス感を選び取るか、という話に落ち着くというのが適切でしょうか。

会社選びというのはあくまでスタート地点を決める行為であって、働き始めてからの走り方も大事だと思います。走り始めてみないと見えない景色や観点というのは0にはできないので、正しい選択をしようとするだけでなく、選択を正しくする、というのもまた同じくらい重要なのかなぁ、と。

そういう意味で弊社は色々な人が働いていて、プラットフォーム開発からサービス開発まで多様なポジションがあって、融通の効きやすい職場なのかなと思います。もちろん実力が伴っていることが前提ですが、別のポジションに社内から異動希望を出すこともできます。やりたいこと、得たい経験というのを都度都度しっかり言語化しておき、身の振り方を考えながら仕事をする努力を継続して行えば、新卒で今の会社を選んだという事実を正解だったと言えるようにできる気がしています。まだまだ働き始めて一年も経っていない(本配属されてからは3ヶ月程度)ので、道半ば、といったところですが、今後も無理しすぎない程度に選択を正しくする努力を継続していきたいです。

入社して良かったことと悪かったこと①企業選びの観点


はじめに

自分は22新卒でYahoo! Japanに入社しています。さほど就活に時間をかけていたわけではないので、割と雑な理由で選んだ感じですが、会社を比較検討する上で考えてたこと、実態としてどうだったか、という話を書いておこうと思います。書いてたらクソ長くなったのでこのポストでは新卒の就活時にぼんやり考えていたことをまとめて、次回じゃあ実際Yahooどうなんすか?という話を書きます。就活体験記(自分語り)みたいでなんかヤですが、まあ年末で暇なんで手が滑って書いちゃいました。

前提

  • ソフトウェアエンジニアとして働きたい
  • Computer Scienceが好き
  • 人と喋るのは嫌いじゃないでの業務としてクライアントコミュニケーションは別にあっても良い

比較をする

学生時代は各業態で比較をしてました。

ベンチャー

ベンチャーは向き不向きが確実に存在する業態かなぁと思います。会社の状況次第でよかった環境が急に悪くなることもあるのでかなり気をつけて選択しないとダメだと思います。ベンチャーと言っても0→1なのか、1→10なのか、10→100なのかで働き方も働いてる人の雰囲気も全然違いますし、上場、Exit前後で全く別物になることもあるので不確実性が非常に高いです。特に新卒の場合は面倒を見てもらえないと思って入社しないとキツイ場合が多いかと。

甘ったれたことを言うな、みたいな反応されそうですが、やっぱある程度時間に余裕があって、多少の失敗は許容してくれながら、comfort zoneを少し出た程度のタスクをマネージャーが振ってくれて、できないこととか自分の能力に限界があるところに関しては適切にFBをくれたり、時にはサポートしてくれたりする環境の方が成長が期待できると思います。赤字をどうにか補填しないとダメでエンジニアもセールスもみんなhard workしている環境、所属してるprojectもtime sensitiveなので先輩を捕まえて色々聞くのも無理、作ってるプロダクトはまだまだ自動化できていないことが多いので、特に個人の成長につながらない単純作業があって、どうしようもないため新卒にそういう仕事が降りてきて業務時間の大半を雑務で過ごすことになる、加えて自分も残業がすごいので平日夜に勉強する時間とか作れなくてスキルセットの幅は広がっていかない…とかもなくはないと思います。バキバキに中途入社組と肩を並べてoutput出せます、なんなら俺の方が5年目のあいつより仕事できるっす、みたいな人なら自信を持って入社しても楽しい仕事をかっさらえていいのだろうな、と思いましたが、自分にはきつかったです。

ちょっとヤバ目のプロジェクトの場合を出しちゃいましたが、適切な環境を選べば大きく成長できる環境もあることは理解しています。大手と違ってリソースの制約があり、人も金もなかなかない状況下で、プロジェクトを前に進めるために多角的な視点から意思決定を行い、エンジニアという職域を超えた働きを通して事業を成長させていける人材になれるのであれば十分魅力的だと思います。分業が進んでしまった大手と比較すると経験の横幅、みたいなところは圧倒的に分があると感じました。

たまにベンチャー→大手は無理だが逆はできる、みたいな言説を目にしますが、エンジニアに関しては的をいてないと思うので、そこは別に気にしませんでした。あれはソフトスキルでしか評価できない職種(e.g. 営業)の話をしているのであって、ハードスキルで評価をされるエンジニアは全く話が別だと思ってました。が、結論として諸々不確実性が大きいのでベンチャーはやめとくか、となりました。新卒の場合は内定から入社まで1年程度のgapがあるのも意思決定を難しくした一因ではありました。ベンチャーの1年は事業と会社のconditionを変化させるのに十分な期間だと思います。

SIer

IT企業って括りにはなると思いますが、もはや別の世界なので見なかったことにしました。日本のSI論に関しては、以下の記事がよくまとまってるなぁと感じてます。

SIerとは何か、何であるべきか ― 偉大ならざるリスクテイカー|ミック|note

正直ソフトウェアエンジニアとして働きたいという前提に立つと、SIに就職するのは選択はあまり良いものとは思えなかったので選択肢には上がってませんでした。R&Dをやってる部隊とかならアリかもなぁと思いましたが、R&Dに力を入れてる会社というのは必然的に大企業となり、かなり古い会社も多く、良い噂と悪い噂の両方があって、決め手にかける、といった印象でした。

外資のソフトウェアエンジニア

外資SWE(SDE)と呼ばれるポジションは、自分が知る限り営業やサポートエンジニア、プリ/ポストセールスと比較して募集がそもそも多くなく、入社のハードル自体もかなり高いことが多い印象があります。当時の自分を振り返ってもまあ入社は厳しかった気がするのと、Leet Codeとか一生懸命といて、面接準備をして、なんとか入社したところで、実力に見合わず結構キツイ思いをしそうだなという印象を持っていたのでそもそも受けていません。身の丈にあったポジションでしっかり成長し、その上でやりたいことがありそうなら将来受けてみてもいいかな、くらいの認識でした。

また、実態として何をやっているのかの情報が見つかりづらいというのもあります。本社自体は米国やヨーロッパ圏にある場合、どういう意図で日本法人をもうけているのかをちゃんとリサーチした方が良い気がします。入社しても日本のお客さん向けに自社サービスのローカライゼーションやadd on開発だけしてて製品のcoreな開発はやっていない、みたいなケースも全然ありそうで、元々それを承知の上でやりたくて入社した場合は良いと思いますが、そもそもcoreな開発がやりたかったんだけど・・・みたいな人はミスマッチになったりする気がしますし。

まとめると以下の2点の不確実性が高く、リスク許容できなかったため選択から外しました。

  • requirementがキツいので、面接のための小手先テクニックでちょろまかして入社しても、入社後ちゃんとついていけるか不明
  • そもそも日本法人として何やってるか不明な会社が多い

外資のプリ/ポストセールス・サポートエンジニア

募集もそれなりにありますし、選択としてナシではなかったです。ただ専業のエンジニアと比較して、セールス・コンサルタント成分が含まれるためか給与が異常に高いです。儲かってる会社とかだと新卒から1000万前後稼ぐことも夢じゃないです。そういう人も見ました。

待遇面が魅力的なのですが、同時にそこがデメリットでもあり、Software Engineerに転職すると大抵の場合給与が下がる気がします。同じくらいの待遇をエンジニア職で保とうとすると、先述した外資SWEと日系のごく一部の企業(smart newsやメルカリ、ウーブン・プラネット)に転職するしかないんじゃないでしょうか。サンプル数は少ないですが、待遇保ったたままエンジニアに転職した事例を自分は知りません。探せばいると思いますが。

プリセールスやポストセールスも楽しい仕事だとは思うのですが、エンジニア → プリ/ポストセールスは待遇も上がるし現場で働いたことあってボチボチ喋れる人は需要が高いのでキャリアパスとしてはイケる気がします。しかし、逆は給与下がるし結構厳しいんじゃないかなという仮説がありました。人間は生活水準を上げると下げられない生き物ですし、年に700万とか1000万とか稼いじゃうと調子にのって結構お金使っちゃう気がしてたので、新卒ではやめとくか、ってなった次第です。ずっとITコンサルタントとして生きてくって意思決定が自分にできればそれでよかったんですけどね。何かを作りたいなという欲求は捨てられませんでした。

Web系企業(リクルート楽天Yahoo!クックパッド、メルカリなど)

最も現実的な選択肢でした。

  • 長期インターンでの経験や個人での開発経験、研究等でweb開発自体は経験がある領域だった
  • 各社情報発信に積極的でテックブログを見ると大体中で何やってるか想像がつく
  • 社内にポジション・プロジェクトもたくさんあるので転職せずとも色々経験できる(制度的に整ってる会社もある)
  • 給与は福利厚生を加味した可処分所得は大体ならすとどこも500万で一年目はさほど変わらない(メルカリ等、一部の企業は除く)
  • サポーターズの逆求人イベントでエンジニアとコンタクトを取れた会社が複数社あって、なんとなく雰囲気がわかった
  • 大体みんな幸せそう(一番重要)
  • ホワイトな会社多い

外資と比較すると待遇面は劣りますが、ハードスキルをしっかり伸ばせばどこで働いてても満足できるだけ貰えるようになると考えていた(無理そうなら転職ハックなりなんなりで給与なんぞどうとでもできる)ので大きなデメリットではないな、と感じたのでWeb系に就職するのが丸そうだな、と判断した次第です。結果としてYahoo! Japanに入社しました。

Yahoo!にした決め手はPrivate Cloudを自社で運用しているため基盤技術に非常に強いエンジニアがいることや、抱えているサービスが多くて得られる経験の幅が広そう、超絶ホワイトなので可処分時間が多い、みたいなところです。

仕事自体は好きだしhard workもやぶさかではないのですが、実際働いてみてなんか違う感を感じた時に、平日夜と休日の時間を投資して別のスキルセットを確立して逃亡できる選択肢がほしかったのでホワイトなところは外せませんでした。特に大手の新卒は中途と違ってポジションとのマッチングではなくトップダウンな戦略のもと人員配置が決定されることが多いので、入社後の配属が希望したポジションと違うじゃねぇか!!ってなることもあり得るな、と思ってたので…配属が大外れってことはない会社が多い気もしますが、心の底からやりたいって思えてない仕事でhard workするのは本当に辛いことは想像に難くなかったです。

まとめ

なんというか凄まじい分量になってしまいましたが、自分の当時な雑な意思決定としては上記のような感じでした。

入社してみての感想はこちらです。