株式会社DIGITALIOでメディアの開発をしているぐりです。
タイトルの通りなんですが、「やる」という言葉にはいろいろな解釈があり、大事なのはわかっているけど自身の経験として実感しづらいなという思いがありました。
自分自身が「やる」についてどう考えているか、を整理するために、普段考えていること・やっていることやなぜそう考えるようになったのか?を棚卸ししておこうという思いから書いています。
やるとは何か
この記事の中では、「何かしら価値を提供するものを本番環境にリリースすること」と定義しています。
直接リリースに紐づかない価値ある仕事もたくさんあると思いますが、ここでは自分自身がより良いソフトウェアエンジニアになりたいと考えていること、そして良いソフトウェアエンジニアはコードを書くなどのアウトプットによって多くの価値を提供できる人だと考えているからです。
やることの質と量が自身の成長に繋がる
やることがなぜ大事かはこちらの記事にとてもよくまとまっています。
より大きな価値を提供するためにはたくさん学ぶ必要があり、たくさん学ぶためには問題をたくさん解きFBを得ることが必要だと考えています。
これは『エンジニアの知的生産術』を読んだ際に学びのサイクルは以下のように積み上がっていくものだと説明されており、これが自分としてはかなりしっくりきました。
やることで具体を積み上げていき、自分の中でパターン化して応用していくことで成長できるのではないかと考えています。
本番環境にリリースするために「やる」こと
人によって仕事の進め方は様々あると思いますが、自分は以下のように進めることが多いため、これをベースに考えていきます。
(既知の知識や経験) → 要求分析 → 調査 → 要件定義 → 設計 → 実装 → テスト → レビュー → リリース → (分析・運用)
実際の仕事の中では矢印を逆方向に戻ることも多々ありますが、「やる」とはこの一連の流れを行うこととして考えます。
既知の知識や経験や分析・運用は本番環境に価値を届ける前・後に必要なものなのでここでは「かっこ()」で表しています。
一つ一つ見ていきます。
要求分析
まず機能の提案などを元に解決する問題を見つけます。
やはり大事なのは「言われたものをそのまま作らず、本質を見極めて何を解決するか」を根気強く考えることだと思います。
CARTAのエンジニアはこの考え方が文化レベルで根付いているなぁと感じます(すごい)。
本質を見極めることに関しては、すずけんさんの問題を解くことを時々読み返しています。
間違った問題を解いているときは、本当に解かなければならない問題に使える時間を失ってしまっている。同じ時間をつかって、同じような大変さで問題を解いていても、成果が変わってしまう。成果の大きさは問題の解き方より、どんな問題を解いたかのほうが支配的なことが多いのである。
間違った問題を解くことがソフトウェアエンジニアにとってどれほど恐ろしいことかが生々しく伝わってきます。
やることから学びを得るには、仮説を立ててその検証により仮説からの差分によって何がうまくいくか、何がうまくいかないかを経験する必要があります。よって、良い仮説を立てることができればその後のサイクルが何倍にも良いものになると考えています。
調査
設定した問題を解くために調査を行います。
変更を加えそうな部分のコードをメモしながら読んだり、関連の資料があれば読み込んだりします。
自分がよくやるのは、まずは愚直に1行1行読み進めていくことが多いです。
読んでいって、何度も読み返さないとわからない部分が出てきたり、影響範囲が大きかったりした場合は一旦手を止めてどういう構造になっているか?を理解しにいきます。ツールはなんでも良いですが、最近はGitHubのMermaidがシュッと書けて楽なのでよく使っています。
構造を理解しにいく時は、クラス図等を書きながら「どうしてこういう設計や依存関係になっているんだろう?」を整理するように心掛けています。
注意深く読むと当時の事情だったり、歴史的経緯でそうなったことがぼんやり浮かんできたりするので、設計の参考になるようメモしておきます。
このように調査を進めるようになったのは、これもまた問題を解くことに書いてある以下から影響を受けています。
何かをしはじめるときには虫の目と鳥の目を使う。虫の目はごく繊細な様子を読み取る。そのプロダクトのコードのほころびから、過去になぜこういう設計になってしまったのかを想像していく。現状のつくりがやろうとしていることを深くまで読み解く。もしボトルネックがあるのなら、本当の原因を深掘っていく。細かい振る舞いを把握していく。これが虫の目だ。
鳥の目は鳥瞰の目のそれである。全体像を把握する。プロダクトがなぜこのような狙いに基づいて作られているのか。そもそもこの設計にした理由はなんだったのか。過去の資料をみつつ、想像を膨らませていく。ここで作ろうとした競合優位性はなんだったのか。あるいは、志半ばで途絶えている状態なのか。複数のコンポーネントが同じようにしているようにみえるが、どういう狙いがあるのか。抽象をたどって、理由を繋いでいく。街の作りを上からみるように、どうしてこの道はこの方向に引かれているのだろうというのを想像していく。こうして2つの目で紐解くということをする。
すずけんさんの言語化、最高です。
要件定義
調査を行った結果からざっくり作るものの振る舞いをまとめ「こういう仕組みを作ったら良さそうですかね?」と関係者とコミュニケーションを取っていきます。
作るものを擦り合わせるために、何度もコミュニケーションが発生することがあると思います。ここでは、完璧なものができるまでホールドすることはしない、コミュニケーションに使う用語をちゃんと統一できるようにすることを意識しています。
また、普段からIssueやBacklogに細かくコメントを残し、自分の状態をオープンにしておくことを意識しています。こうすることで、僕に対する「今あの案件どうなっていたっけ?」という追加のコミュニケーションが無くなったり、自分自身がどれくらいの仕事を持っているか?ということが明確になり頭の中の整理にも繋がります。これは、ひげぽんさんの「常にそこにいろ」に影響を受けています。
タスクやバグのトラッキングにJIRAのようなシステムを使っていることもあると思う。チケット上でも常にそこにいよう。チケット上での「常にそこにいる」とは、チケットの状態(進捗・詳細な情報)を常に最新に保つことだ。これもコミュニケーションだ。
設計
次はどう作るかを考えていきます。
どこまで設計するか?は僕も迷うことが多いのですが、最近は「手を動かさなくてもわかることがあるうちは手を動かさない」そして「不確実性の高い部分から着手する」方針で進めています。
手を動かさなくてもわかることがある状態で手を動かしてしまうと、実際にコードを書き始めた時に「どれが手を動かして初めてわかった部分だっけ?」が曖昧になるためです。
手を動かさなくてもわかることはあらかじめ設計として文書化しておくと、それ以外にわかった部分は手を動かさないとわからなかったことなんだ、と明確になるので、もし無駄な実装になったとしても仕事を前に進めたぞという気持ちになることができます。
また、もういつものパターンで実装方法も分かりきっている部分は後から問題になることはほとんどないと思うので本当にざっくり書くくらいで終わらせることも多いです。
実装・テスト
実際にコードを書いていく中でも「たくさんやるにはどうすればいいか?」を最近は考えています。
僕が参考にしているのはテスト駆動開発や単体テストの考え方/使い方といったテストのプラクティスやClean Architecture 達人に学ぶソフトウェアの構造と設計 に書いてある依存性についての考え方などです。
良いテストを書くプラクティスは、より詳細な設計に関するFBを高速に得るのにとても良いと考えています。
テストが書きづらい部分は大抵の場合、実現したいソフトウェアに対して仕事が分解できておらずファットになっていたり、依存関係が整理されていないことが多いなと思います。
先にテストを書くといった徹底的なテスト駆動をやっているわけではないですが、クラスやメソッド単位でインターフェースを確認する意味でも都度都度テストを書いて進めていくことが多いです。
また、良いテストをかけるようなコードになっていると本番に影響しないリリースを部分的に行うことができ、後々のレビューやリリースのサイクルを高速に回すことにも繋がっていきます。
レビュー
ryuくんのプルリクのレビューは即返すを実践しています。
PRを即返すには、即返せるPRになっている必要があります。
実装・テストで部分的に切り出してリリースできそうな部分はどんどん切り出してレビューを出すことを意識しています。
この辺りはryuくんの記事にも参照があるnekoyaさんのそのPull Requestデカすぎませんかがとても参考になります。
リリース
ここではリリースする価値について少し自分の考えを書こうと思います。
僕のソフトウェアエンジニアとしての働き方は『Design It!』に大きく影響を受けています。
この本は、ソフトウェアアーキテクトとなるためにどのように仕事をすればいいか、について書かれています。
自分が好きなのは、ソフトウェアアーキテクトは様々なステークホルダーと関与しながら価値を作っていく部分です(自分なりの解釈です)。
ここでいうステークホルダーとはユーザー、機能を提案する人、システムを利用する人、そして開発者などあらゆる人を指しています。
リリースする価値はただ単に何かができる機能を作るだけではなく、人々と協調することやより良い開発者体験を作ること(リファクタリングとか)も含まれており、またそれはソフトウェアエンジニアが責任を持つべきことだと書かれています。
以前は実装中に気になるところを見つけたが直した方が良いかわからない、と判断に迷うことが多かったですが、今は一連の流れのなかで小さく切り出してリリースすることを考えることで速く『やる』ことの一部として考えることができるようになりました。
(既知の知識や経験)と(分析・運用)
本番環境にリリースするための仕事を進める前・後段階にも「やる」ためにできることがいくつかあるなと思っています。
自分が扱っている技術やサービスを隅々まで知っていれば当然速く仕事を進めることができると思いますが、時間は有限で何度も挫折しています。
今取り組んでいるのは、ビジネスやチームがやろうとしていることの方向性を理解することです。
例えば、ビジネス側も含めたMTGに出る際に、やれていないけどやりたそうなことに注目したり「チームの方向性的にこの仕事があるとしたら次はこういう動きになりそうだな」と次の仕事を想像するようにしています。
こういった動きで次にプロダクトのどこが変更されそうかを想像をして、わからないところが多そうだったらちょこっと仕組みを理解しておきます。
これは、CARTAのシニアグレードエンジニアが書いた記事に感化されました。「速さを得るためにチームの状況を理解し、さらに隅々までコードを読んだ」という内容が書いてあり、全てをやるのは無理かもと思いながら自分なりに試行錯誤をしてみています。
運用については、同じ会社で長く働いていると自分が作った部分が増え、設計や実装に対する長期的なFBを身をもって感じやすいというメリットがあるなと感じています。新しく入ったメンバーが触って初めて気づくところや、長期的に運用して初めて判明する問題などもあります。また、よく知っているコードが増えることで認知負荷が下がり、また新たな問題に挑戦しやすくなるメリットもあると思っています。
あとがき
小さく素早く、たくさん「やる」ことで成長するを読んだり、最近育休から復帰して自分の成長について改めて考える中で、一旦言語化しておきたいなということを書きました。
勢いで書いていますが、アウトプットすることでまたFBを得たいなと思っているのでとりあえず出してみるという気持ちです。
そして、まだまだ出来ていないこともたくさんあります。がんばるぞ!