4年目のソフトウェアエンジニアがSWE協会のコーディング練習会に参加して感じた変化
概要
4年目のソフトウェアエンジニアとして、一般社団法人 ソフトウェアエンジニア協会(以下SWE協会)のコーディング練習会に参加して感じた変化を共有します。
なお、Google を含む外資系ソフトウェアエンジニアのコーディングテストを準備なしで解ける方にとっては、本記事の内容は役に立たないかもしれません。
自己紹介と参加の背景
私は現在、主にマーケティングオートメーションツールを提供している会社で、ツール全体が使うデータパイプラインの構築や運用、機能開発に利用する共通基盤の開発等を行っています。
扱うトラフィックはそれなりに大きく、馴染みの薄いミドルウェアを学ぶ場面も多いのですが、学習が場当たり的になりがちで、技術間に渡る「共通項」が見えにくい感覚を抱いていました。
また、社内で尊敬するエンジニアの「判断基準」や「なぜその選択肢を採らないのか」という背後の思考まで追いきれないことが悩みでした。表に出たコードは読めても、その設計判断の根拠まで腹落ちしせず、自分が同じ感覚を持てていないというモヤモヤを抱えていました。
「常識」というキーワードとの出会い
偶然近くでやっていた、SWE協会の元/現 Google の方による「ソフトウェアエンジニアとは何か?」という説明・勉強会に参加しました。
そこで示されたのは、「ソフトウェアエンジニアは専門家集団であり、専門家には常識(知識だけでなく、反応・行動・感覚・判断)がある」という考えでした。
たとえば、あるコードを見て即座に「これは嫌だ」と感じる反応や、選択肢を自然にふるいにかける判断は、この常識に根ざします。もしこの常識が十分に身についていれば、面接対策として LeetCode を漬け込みでやる必要は本来ないはず。この話を聞いて、私は自分に欠けていたものが「常識」だと強く感じました。
その際に、SWE協会ではコンピュータサイエンスの勉強会をやっていることを知ったので参加してみることにしました。これはオンラインで約半年ほどでコンピューターサイエンスの基礎を学ぶというプログラムです。(参加者の声: CSZAPのご紹介)
その中でアルゴリズムの講義の後にコーディング面接対策のために解きたいLeetCode 60問(通称arai60)を解く課題を与えられました。
SWE協会ではarai60を使ったコーディング練習会もやっており、良い機会なのでそのプログラムにも参加することにしました。
コーディング練習会の目的
練習会では、コーディングを通してSWEとしての常識を身につけることを目的としています。
ソフトウェアエンジニアが常識だと感じることの8、9割を再現できればソフトウェアエンジニアとしての専門家の仲間として扱われるので、コードの読み書きに対してそれを行うのが良い学習方法だという考えが元になっています。その題材としてarai60というLeetCodeの問題が選ばれています。
身につける能力の例は以下となります。(SWE協会の「コーディング練習会参加マニュアル」から一部抜粋)
- 計算量のような雑な評価ではなくコードの優劣の評価をして適切なものを選択できる能力
- 言語のバージョン間の差異、言語仕様か環境依存かなどを含めて気が配れる能力
- 手作業でできることをコンピュータにお願いできる能力
- 大規模なコードを読解し理解する能力
他人が書いたコードを読んた時にソフトウェアエンジニアが持つであろう感覚や反応を身につけることも目的に含まれるので、積極的に他の人が書いたコードを読むことになります。
その際、他のソフトウェアエンジニアの方が書いたコメントがあるので自分の感覚とあっているか、ズレていれば、そのギャップをどう埋めるか(どういうマインドセットが不足しているか)を考えることになります。
問題の取り組み方
私は以下のようなやり方をしていました。
- 何も見ずに問題を解く
- 気になったライブラリの実装を確認したり、自分で再実装してみる
- 自分はRuby問題を解いていたので、問題を解いた時に使ったメソッドの内部が気になった時はCRubyの実装を読んだりしました
- 過去に同じ問題を解いている人の解答を読む
- この時、基本的に他の人の解答とそれに対して他のソフトウェアエンジニアの方がつけたコメントを見ることができるので、自分の反応が常識の範囲内かどうかのフィードバックを得ることができます
- 1で解けなかった場合や、考慮できなかった常識の範囲内の解き方があれば理解した上で読み書きができるようにしました
- なにも見ずに10分以内に間違えずに3回続けて書けるまで繰り返す
- 3回書くのは理解が整理されて思考が深まるのと、くり返し間違う場所があれば不自然さを反映していることが多いためです。
2に関しては最初はやっていなかったのですが問題に取り組むうちに自然と内部実装が気になるようになったのでステップに加えました。
取り組んだ感想
当初は「LeetCode が解ける=難しいアルゴリズムを理解している」というイメージでした。しかし実感としては、自然言語で説明できることを機械にやらせるに過ぎない、という感覚が強まりました。
進めるにつれてCRuby 実装を自発的に確認したくなるなど、専門家の「気持ち」に近づいた感覚もありました。
コードレビューでも変化がありました。以前は「書かれたコード」をそのまま理解しに行っていましたが、今は「どんな思考過程を経てこのコードに至ったのか」に焦点を当てるようになりました。
日本語の文章を読むときに「この主張があるなら次はこう展開されるはず」と文章を構造的に理解して当たりをつけられるように、コードの背後にある構造を意識して読めるようになった結果、読んだことのないライブラリのコードリーディングやバグの発見が明確に速くなりました。
また、自分はコードに落とす前段階でつまずいていたことに、取り組みの途中で気づきました。
本来、課題に対して「やりたいこと(目的・不変条件・達成条件)」があるはずで、これが明確であれば自然言語でもコードでも表現できます。
ところが私は、やりたいことを曖昧にしたまま書き始め、最後に「要するに何をしたかったのか」を言語化しようとして詰まっていました。本来やりたいことが明確に出来てさえいれば、コードに落とし込むのにさほど労力は要らないはずなのです。
これはコードを読む時にも重要で、「やりたいこと」がわかっていれば、それを表現する手段であるコードのバリエーションが多少違っていても容易に理解できます。また、「やりたいこと」に対してコードが乖離している不自然な箇所も、目に入りやすくなります。
例えば、二分探索の問題では left/right の置き方や middle の選び方にさまざまなパターンがあります。しかし結局は「何を探したいのか」「left が何を表すのか」「right が何を表すのか」を明確に定義し、人に説明できるのであれば、その定義の仕方が異なる他者のコードでも読み解くのに苦労しませんし、バグのあるコードで何度も修正して“ガチャを引く”ように解答に辿り着く必要もないでしょう。
ちなみに私は取り組み始めの頃、上で書いたことができていませんでした。二分探索の問題を解く時も、具体例の配列を挙げてホワイトボードに必死に書き、抜け漏れがないかを確認して……といったやり方をしていました。
コーディング練習会では「自然言語で考えられないのであればコードに落とし込めないよね」といった趣旨の書き込みが多く、しばらくは自然言語でどのように考えるべきかを意識して取り組んだ結果、自然と具体例に頼らず、さまざまなパターンを頭の中で扱えるようになりました。
arai60 にはさまざまな問題がありますが、個人的には全問題を通して「やりたいことを明確にする能力」が鍵だと感じます。この能力を養うには二分探索が有効だと感じているので、これから始める方は先に取り組んでみるのもよいでしょう。
最後に
SWE協会の練習会参加者の記事や、関連勉強会の資料も大いに参考になります。興味があればぜひ目を通してみてください。
- 一般社団法人 ソフトウェアエンジニア協会
- 「人生のチュートリアルを終わらせるたった一つの冴えたやりかた」
- コーディング練習会参加の感想
- ソフトウェアエンジニアリング協会でArai60を解き終えました
- コーディング練習会の感想@一般社団法人ソフトウェアエンジニアリング協会
- 他にも「ソフトウェアエンジニアリング協会 arai60」とかで検索すると色々出てくると思います
- CSZAP
Discussion