Yappli Tech Blog

株式会社ヤプリの開発メンバーによるブログです。最新の技術情報からチーム・働き方に関するテーマまで、日々の熱い想いを持って発信していきます。

成果を出す技術

サーバーサイドエンジニアの田実です!

私はコードの実装スピードが早いらしく、どうやったらそんなに早く実装できるのか、成果を出せるのかと度々聞かれます。 改めて成果を出すスピードがどこに起因しているのかを掘り下げて考えたところ、それを達成するためのいくつかの要素がありそうだったため、ブログでまとめていこうかと思います。

※本記事は ヤプリ#1 Advent Calendar 2023 の 12日目の記事になります!

ソフトスキル編

背景や課題を理解する

新機能開発、既存機能修正、基盤改善、運用効率化などなど、どの領域であってもそれらを行うモチベーションとなる背景と課題があります。 誰がどういうペインを持っていて、それを解消することで得られるメリットは何なのか、というのを理解しておくと、課題解決の指針を立てやすくなります。 背景や課題を正しく理解しないで解決をしようとすると、リリースした後にペインが解消されなかったり、手戻りが発生する可能性があります。 課題の真因を理解しなかった結果、実は作らなくても良いようなスマートな解決方法があるのにモノを作ってしまい、それらのコードが後々に技術的負債になる、ということもよくあります。 また、自身だけが背景・課題を理解するのではなく、課題を起票した人や一緒につくる人とともに理解を作っていくことが重要です。そのために、次に紹介する「コミュニケーション」が重要になってくると考えます。

コミュニケーションの質とスピード

非同期コミュニケーションであってもレスポンスは早めに行うようにしています。 回答を寝かしていたりボールをたくさん持った状態になると、認知負荷が増え、自身が不安な気持ちになりがちです。 レスポンスを早くすると、相手側もコンテキストスイッチがかかることなくコミュニケーションできるため、認識を揃えやすくする狙いもあります。

また、ラリーが多いと情報共有がうまくいかなくなるケースがあるため、背景や意図なども含めて可能な限りまとめて伝えるようにしています。 同じ職種・ロールであっても知っている情報に差分があるため、前提や背景を正しく伝える必要があります。 まとめて伝える過程で課題の整理をした結果、コミュニケーションを取る前に疑問が解消したり、よりスマートな解決方法を思いつくきっかけになることもあります。

テキストベースで認識を合わせるのが厳しい場合は、実際に成果物を見せたり、図表を使ってコミュニケーションすると共通認識を作りやすいです。 画面系であればキャプチャを撮って共有したり、実際に開発環境を触ってもらって認識を合わせることがあります。 弊社だとスプレッドシートやConfluenceで表を書いたり、Figmaやdraw.ioを使って図を書いて共有しています。

タスクを分解して少しずつやっていく

大きい課題ほど何から手をつけていいのかわからなくなりがちです。 少しでも進捗を前に進めていくことが大事なので、タスクを分割して各タスクのゴールを設定し1つずつ消化しています。

また小さいタスクでも↓のようにマークダウンっぽい感じで適当にメモ帳に書いて、[x] をつけたり優先して対応したいタスクにマークをつけて可視化しています。

* ◯◯◯対応
  * [x] データ件数確認
  * [x] データ内容確認diff
  * [x] インデックス確認
  * [ ] リリース

これをやると、やることが簡単に整理・可視化できたり、完了したタスクを見てモチベーションや自己肯定感があがるのでオススメです。

6割ルール

各ビジネス領域の最低限の品質は担保するという前提で、基本的には完璧を目指しすぎないようにしています。 完璧を目指しすぎてリリースが滞留すると、モチベーションや自己肯定感が下がりがちです。 また、ビジネス・サービス・組織の不確実性から、プロダクションコードにおいては完璧な実装というのものは存在せず、ベターな実装の積み重ねが大事なように思います。 そういった理由から「以前よりベターな状態になるし一旦リリース!」「まだこの辺考えないといけないけどそんなに問題じゃないし別途対応!」という感じで期限と品質に折り合いをつけてリリースしています。とはいえ一歩間違うと割れ窓になってしまうため、このあたりのさじ加減が難しいのですがw

リリース・保守・運用して初めてわかることもありますし、リリースしないことにはフィードバックももらえません。 納期 というと嫌悪感ある人がいると思いますが、リリースすることにより価値提供をより早く、より増やしていく意味でも納期を意識するのは大事だと思います。 例えば3ヶ月遅延してようやくリリースしたけど意外と使われないとか、リリースが遅れることによりメンバーのモチベーションが低下して疲弊する、みたいなケースはよくあると思います。 そのため、大きい機能はリリースを適切に分け、場合によっては仕様を引き算していくことも必要になります。

ハードスキル

引き出しを多く持つ

ドメインや技術的な引き出しを多く持っていると、見積もり・設計・実装の指針を立てやすくなります。 そのためにもコードを読み書きする量を増やしたり、リリース後の保守、不具合対応の経験を増やしていくことが重要です。 それによってアプリケーションコードの構造を把握した結果、実装の迷いがなくなりスピードも上がります。 現状理解ができると、よりよいコード・アーキテクチャを考える余裕・余白ができ、それにより品質も上がります。

さらに、インフラなども含めてシステム全体を理解しておくと、よりよい解決方法でアプローチできたり、リリースしたあとの手戻りも少なくなります。 キャッシュをどのレイヤでやるのがコスト・運用・保守の面で最適なのか?負荷が増えたときはどういったアプローチが取れそうか?ログや監視はどこに入れるのか?など、システムを理解して技術的な選択肢を出せるようにしておくと、不具合が発生したときの判断も的確かつスピード感を持ってできるようになります。 また、これらのシステム理解(とビジネス理解)が増えれば増えるほど、局所最適に陥らない最適化ができると思います。

まず適当に書く(第一歩を大切に

実装する場合は、全体の骨組みだけ書いて雰囲気だけの正常系のコードから書き始めています。 例えば、あるAPIの処理を1から実装する場合は適当にルーティングとコントローラ・メソッドだけ実装して、バリデーションは一旦無視、動かないけどなんとなく動きそうな雰囲気が出ている正常系のコードを書きます。既存コードからコピペも結構しています…w ただし、単にコピペするだけだと重複コードが増えたりコード品質が悪化する可能性もあるので、良い感じに共通化したりボーイスカウトルール的に整備しています。

その後、テストをコピペしたりして書き始め、動かないところを直して正常系だけ動くようにします。 正常系が動くようになったらバリデーションなど準異常系、異常系の処理を詰めていきます。必要に応じてリファクタリングも行います。

この方法の良いところは、早めに正常系が出来上がったり、最初に面倒な骨組みの実装をやることで「後は差分でコードを書いていけば良い」というマインドに持っていけることです。 だいたいタスクのやり始めは億劫だし、進捗をある程度満たしていないと不安になります。とりあえず勢いで書き始める、細かいところは後で!という感じで最初の一歩を踏み出しやすくしている感じです。ソフトスキルで述べたような「6割ルール」「タスクの細分化」の話に近いかもしれません。

また、コピペも人によっては嫌悪感ありそうなんですが、もちろんコピペグラマーみたいな感じになるのはご法度なんですが、最初のステップとしては良いと思っています。 コピペするには既存コードの実装を読む必要があり、既存コードと実装の雰囲気を合わせやすくなります。 ドメイン知識、既存コードの構造把握、コーディング規約、言語やライブラリの知見・サービスでの使われ方など開発をする上では様々な認知負荷があります。 コピペによって認知負荷を下げた状態で骨組みだけは作ることができ、その後はレビューのように1行ずつコードを読んで理解・変更していき、これらの知識をインプットしていけば良いと思います。GitHub Copilotとかだって既存コードのコピペみたいなもんじゃないですか!w

自分の手でちゃんとテストする

弊社は基本的にQAチームに検証をお願いするフローになっていますが、検証をすべて丸投げするのではなく、自動テストを十分書いた上で、事前に手を動かして検証するようにしています。 APIであればレスポンスのJSONをざっと目で確認したり、iOS/Androidアプリのシミュレータを立ち上げて簡単な動作確認をしています。 実装者であればホワイトボックステストが可能なので、不安な部分は一時的にログを出力して、期待している値が入っているかも確認していたりします。 既存の振る舞いに影響を与えるコード変更に関しては、既存データを確認し、意図しない挙動にならないかの検証も行っています。

不具合の情報連携はコミュニケーションコストがかかりがちなので、これらの事前検証によりアプリケーションや環境起因の不具合による手戻りを極力減らしています。 E2E以外の自動テストでも検証可能ではあるのですが、モックしている部分などインフラ構成・設定によって意図しない挙動になることもあるので、簡易的な手動テストをやるだけでも意外と不具合を発見できたりします。自分で検証を行う過程で、インフラやスマホアプリなど周辺技術の知識を得られるメリットもあります。

作らない技術

基本的に何でもかんでもコードで解決!ではなく、ありものでできないかを検討しています。 どんなに設計や実装が優れたコードであっても、新規にコードを書くことは負債になりかねます。 弊社ではBIツールとしてRedashやLookerを使っていますが、社内向けにダウンロードや閲覧したいという要件であればこれらのツールで十分です。 RedashはCSV・JSON出力するAPIも整備されているので、スプレッドシートなどに連携して運用するなど応用が効くのでオススメです。

また、開発工数がそれなりに必要、保守も大変、コスパが悪い、といった要件は落としてもらうか、次フェーズに持ち越しにしてもらうようコミュニケーションを取ることが多いです。 リリースしてフィードバックを得ると「次フェーズで作る予定だった機能は不要かも」とか「優先度的に別のところ改善した方が良さそう」といった新しい課題も見えてきます。 あれ、「6割ルール」と同じこと言ってる。

まとめ

色々書きましたが、一般的によく言われている要素な感じでしたね…! あまり特殊なことはやってないです。そして自分が全部できているかというとそうではないです。面倒だなと思ってやらないことも多々あります。 ただ、スピード感を持って成果を出したタスクは間違いなく上で書いたような要因があるように思いますし、これらを面倒だと思ってやらなかった結果、解決の質とスピードが落ちてしまったと思うこともあります。 これらの習慣は一朝一夕では身につかず、自分自身もまだまだ足りない要素がたくさんあります。今回書いた内容が仕事をする上で参考になれば幸いです!

余談

アドベントカレンダーの投稿に大幅に遅れてしまいました…。このスピード感不足は しっかり書かないといけない という思いから「6割ルール」が遵守できなかったところが原因ですね。 「タスク分解」もできてなかったし、それらを起因としたモチベーション不足もありそう。そして遅れたからといって品質も上がっていない!w