生産性向上は学生時代からの関心事
はじめまして、フリーランスエンジニアの堀(@hori_ryota)です。Goとドメイン駆動設計と株取引が好きです。開発の生産性を技術的に向上することをメインミッションにしていて、コード生成技術を駆使して開発をDRYにすることが得意です。
今回は開発生産性を高める際に気をつけていることについてご紹介できればと思います。
▲DDDについてまとめているブログ
本題に入る前に、私が生産性の向上にどのように取り組んできたかを簡単にご説明したいと思います。
私は、もともと社会人になる前から、色々なことを自動化したり効率化したりすることが好きでした。学生時代に実験データの整形などをプログラミングで解決することに楽しさを感じ、就職活動でも、より自動化や効率化により貢献できそうな分野はどこかと考え、機械系の大学からIT系のエンジニア職を志しました。
働き始めてからは、手元作業以外にも関心が広がり、本記事で扱うような、より広義での生産性に注目するようになります。前職のサイバーエージェントでも、離職直前まで生産性向上のチームの立ち上げなどに関わっていました。
フリーランスだからこそ求められる生産性
先に述べた通り、開発生産性についてはフリーランスになる以前から強い関心を持っていたのですが、フリーランスになって正社員時代とは意識が少し変わりました。
1つは求められることが変わったこと。もう1つは自分の収入やキャリアのことです。
フリーランスとしての業務内容
現在は金融系の会社にてデータフローの構築や新規サービスの立ち上げに携わりつつ、OffersMagazineを運営しているOffers経由でも案件をいただいています。
▼金融系の会社
- 稼働:週3〜4
- 内容:データフローの構築、新規サービスの立ち上げ
- 使用技術:Go、AWS、Terraformなど
▼フードテック系のサービス
- 稼働:週2〜3
- 内容:テストフロー改善や設計改善など
- 使用技術:Go
どの仕事も裁量範囲が広く、効率化のアイデアなど試したいことが試せる環境である点がとても嬉しいです。
実際にフリーランスになってわかったことですが、フリーランスは意外と仕事を入れる枠がありません。たとえ週に休みが1日だったとしても、稼働できるのは週6日まで。そうなってくると、週3日以下の稼働の案件でやっと2つ入れられる程度です。
最近では株取引のシステムトレードのツールも個人で開発しているため、圧倒的に時間が足りません。
サービス知識が不足した状態での開発の参加
フリーランスとしてお仕事をいただく以上、クライアントからは劇的な成果を求められていると思って携わるようにしています。相性の良い領域で仕事をすることで、自分の技術や知見にレバレッジをかけ、サービスの成長に貢献しやすいのがフリーランスエンジニアの醍醐味だと思っています。
一方で、フリーランスとして外部から携わる場合、サービスについての知識が万全な状態で始められることはなかなかありません。サービスの概念と乖離した設計は、自分の手を離れたときに負債としてサービスの足を引っ張ってしまうことが多いです。
新しいサービスの概念には積極的に対応することが大切だと思っています。サービスの知識とチームの状況は、設計の根本的な要素なので、新しいサービス知識を得る度に根本的な設計変更を行うこともしばしばあります。
限られた時間の中でサービスの今後も考え、高い価値を提供するには、サービスをより深く知るためのコミュニケーション力は当然として、サービスの変更により生じる開発コストに怯まない腕力と、変更を厭わない設計技術が重要です。
これらを鍛え開発生産性を向上することを心がけています。
フリーランスはいかに早く成果を出せるか
周囲の不安を取り除くことも、お互いのコストを減らすためには重要です。特にフリーランスの場合は、いかにスピード感を持って成果を見える状態にし、難易度の高い課題解決に力を注げるか、が大切なので開発速度の向上には常に気を配っています。
また、自分の収入とキャリアのためにも効率化は重要です。
短期的な生産性が収入に直結するのはもちろん、効率的に開発できる業務範囲が広がると加速度的に仕事をこなせるようになります。フリーランスは、実稼働だけでなくフリーランスとしての活動方針を考える時間も必要なため、時間あたりの成果は常に意識する必要があるかと思います。
そもそも開発生産性とは
ここまで断りもなく、開発生産性について触れてきたので、ここで改めて定義したいと思います。
開発生産性というと、「実装作業の効率」のように聞こえるかもしれませんが、ここでは、もっと広い意味で「開発プロジェクトにおける継続的な価値提供」の生産性の意味で使っています。
主に以下の3点を重視しています。
- 想定外の変化に柔軟に対応できるか
- 人間は人間がやるべき仕事に集中できているか
- 迅速に価値提供ができているか
開発過程では「作成」よりも「変更」の難易度が高まりやすいので、特に設計や実装の変更容易性は強く意識しています。変更が生じる状況を減らせればベターではありますが、実際には状況の変化による変更はもちろん、新たにサービスについて得た理解を実装に取り入れるための変更は常に生じます。
上記のように、開発の進め方には常に変更が発生することを意識した上で、迅速に継続的な価値提供を行うための生産性を開発生産性と呼んでいます。
設計段階で気をつけていること
開発生産性に強く影響する設計のポイントに変更容易性が挙げられます。変更が容易な設計として、次のような条件を重視しています。
- サービス要件の変化に対して、どこを変更すればいいかが明確であること
- 変更時のコミュニケーションのしやすいこと
- 作業コストが低いこと
私は、これらを達成するためのアプローチの一つとして、ドメイン駆動設計を好んでいます。
サービスの概念と実装の一致
ドメイン駆動設計では、役職を超えてチーム内で概念の認識を揃え、チームで概念の表現(モデル)を育てることで、メンバー間のコミュニケーションや実装など幅広い領域で様々な相乗効果を生みます。
実装においても概念をコードで「表現」するように努めることで、概念の変更に柔軟に対応できるだけでなく、実装からもフィードバックを得られるため、相乗効果を狙えます。
ドメイン駆動設計の実装では以下の2つを区別することが重要です。
- 概念層: 対象アプリケーションの概念を実装で表現する層
- 非概念層:対象アプリケーション外との帳尻合わせ、技術的詳細
この概念層ではとにかく表現力にこだわり、モデリングとの親和性を高め相乗効果を狙います。
一方で、ドメイン駆動設計では実装作業のコストは高くなる傾向にあります。これには次のような要因があります。
- 表現力を高めるために型を丁寧に実装すること
- アクセサを安直に使わず「いちいち」振る舞いとしてメソッドを定義すること
- 概念層をきれいに保つため非概念層で「帳尻合わせ」のような実装が必要なこと
そのため、ドメイン駆動設計の導入にはトレードオフがあり、小規模なプロジェクトでは導入に躊躇することが多いと思います。私は「人間は人間がやるべきことに集中しよう」を掲げ、本質的な概念の表現以外については可能な限りコード生成により自動で生成することで生産性を保つようにすることが多いです。
ドメイン駆動設計の詳細については以前ブログも書いたのでもしよければご参照いただければ幸いです。
ビジネスオーナーと連携したモデリング
前項は概念と実装を一致させる戦術的な内容でしたが、根幹の欲求は概念の共通認識化です。
アプリケーション開発では、価値提供欲求を持ったビジネスオーナーと開発チームで分断や専門化が生じ、伝言ゲームにより概念の認識がズレてしまうなど弊害が生じてしまうことは多いと思います。
▼概念の認識がズレる仕組み
▼理想的な状態
開発チームはビジネスオーナーと密にコミュニケーションして情報を引き出すだけではなく、ビジネスオーナーと協力して開発からのフィードバックをモデリングに反映していくことも重要です。
概念を実装で「表現」すると、表現のしづらさなどの手応えが多く得られます。これらを力技で解決するのではなく、モデリングに反映し続けることで乖離の少ない実用的で価値の高い設計となることが期待されます。
原典準拠を目指すような設計ではなく、広く状況を加味して継続的な価値提供につながるような設計が必要だと考えています。生産性の高い設計ができるよう、普段からのコミュニケーションの円滑化にも気を配ることを重視しています。
開発段階で気をつけていること
フリーランスで活動していることもあり、時間の効率化は非常に重要視しています。そのため、実装作業の生産性にもこだわり、次のような手を動かす時間を減らすスキルを意識的に取り入れるように努めています。
- エディタのカスマイズ
- 正規表現の習熟
- データの取扱いのスクリプト化
- 冪等性の維持
特に効いているのはエディタのVim(Neovim)で、多様なkey bindやマクロ機能(操作を覚えさせて繰り返し実行できるもの)は生産性に大きな寄与があります。
正規表現の習熟も重要です。sedなどによる一括置換はもちろんですが、上記のVimと合わせると定型的な編集作業は半自動で高速に実施することができるようになります。
最近ではデータ活用周りの業務も多いので、CSVをSQLで扱うツールは特に多用しています。エクセルファイルなども含めた多様なデータを分解、整形し、後述のコード生成技術と合わせて、自動で内部用の定義書や実装を生成するなど自動化の手札を増やしています。
また、運用時のトラブル対応コストは稼働時間を浪費し開発生産性を下げる大きな要因になりやすいです。インフラ構築やバッチ処理を始め、可能な限り全てにおいて冪等性を保てるよう意識するようにしています。
コード生成
変更があったときの心理的なストレスは開発生産性における一つの指標として考えています。特にAPIや詰め替えなどの定型的な記述で、「手が疲れる」ものは強いストレスが生じやすく、不適切な使いまわしやコピペコードによる負債の要因となり、変更自体を難しくします。
コード生成技術により本質的な情報から関連実装を出力するようにすると、ドキュメントレベルの定義書の変更だけで実装が完結するようになり非常に生産性が高くなります。
とはいえ、コード生成技術のメンテナンスに時間を取られ生産性が下がってしまっては本末転倒です。過度な共通化は避け、目的に沿ったシンプルな生成処理をプロジェクト内に作成していくことを重視しています。
不可逆な導入は避け、手作業でも作成するコードの生成をまずは自動化してみるのをおすすめしています。
生産性を高めて変更しやすい開発体制を
まだフリーランスとして活動して1年ですが、過渡的なビジネスへの開発需要の高まりを感じています。また、昨今の社会事情もあり副業を始めた方も多いのではないでしょうか。
開発生産性を高めて変更しやすい開発体制を構築すると、自分の本質的な強みをより活かす時間を増やせると思います。もし今回の記事がなにかのご参考になれば幸いです。