Upgrade to Pro — share decks privately, control downloads, hide ads and more …

開発生産性・開発体験改善の Rules of Thumb 👍

110416
August 13, 2024
17

開発生産性・開発体験改善の Rules of Thumb 👍

某社内イベントにて、開発組織の開発生産性・開発体験改善、特にアプリケーション開発の文脈でできる改善について発表しました. このスライドは、その登壇資料のうち、社内の事情を含まない一般的部分を抽出したものです.

以下はその概要です.

開発生産性・開発体験改善の Rules of Thumb 👍

目標
- **リリースの効率化**: サイクルの短縮とエラー修正の迅速化。
- **人材管理**: 新規人材の獲得と既存メンバーのリテンションを図る。
- **オンボーディングの軽減**: メンバーの出入りをスムーズにし、組織の安定性を保つ。

ルール・ポイント
1 **ボトルネックの改善**:
- リリース頻度やエラー修正時間に直接影響する部分から取り組む。
- 計測の習慣を持つ。

2 **コードの最適化**:
- コード量を減らし、読む負担を減少させる。
- コードの理解に多くの時間がかかるため、理解しやすいコードを書くことが重要。

3 **上流での問題解決**:
- 問題を早期に解決し、下流に影響を及ぼさないようにする。
- 上流の都合を下流に漏らさないことで、ユーザーに不要な調査や変更を強いない。

方法論と実践
- **コード生成**: 冗長なコードの削減、仕様に基づく自動生成の推進(例: protobuf, GraphQL)。
- **モジュール分割**: アーキテクチャを分離し、変更の伝播を防ぐ。アプリケーションとライブラリの分割を行うことで、効率的なバージョン管理や変更管理を実現する。

110416

August 13, 2024
Tweet

Transcript

  1. WHO AM I やっていた・いること @WORK アプリ開発 (Android) バックエンド開発 (Go・ Rust)

    terraform 職人 データパイプライン (Apache Spark) 負債の連帯保証人 やっていること @その他 OSS Contribution(有名なもの だと Scala コンパイラ )
  2. 開発生産性・開発体験改善の Rules of Thumb ボトルネックから改善する . コードを書く量を減らす . 読む負担を下げる .

    より (依存関係の )上流で問題を解決する &上流の都合を下流に漏らさない . 例 : インフラ・ミドルウェア > ライブラリ > アプリケーション 例 : (Web標準などより広義の )仕様 > (ベンダー SDK やミドルウェアの実装 ) > (社内 の )仕様 > 社内の実装 例 : コンパイル時 > テスト時 > 開発環境実行時 > 本番環境実行時
  3. 開発生産性・開発体験改善の Rules of Thumb ボトルネックから改善する ビルドや CI のチューニング、 otel の自動計測

    (auto instrumentation)、テストカバレッジの 向上、エラー監視用 SaaS の利用など、リリース頻度、パフォーマンス計測やエラーの原因特 定・復旧時間の数字に直接効く、かつアプリケーションの変更が最小になるものから手をつ けるのが吉 . ボトルネックを特定できるようにログ、トレース、 (マイクロ )ベンチマークなど、計測の習慣 を !
  4. 開発生産性・開発体験改善の Rules of Thumb コードを書く量を減らす、読む負担を下げる コードを読む時間と書く時間の割合は 10:1 と言われています 参考 :

    開発者は開発に使う労力の 58% をコードの理解に費やしているとも言われています . Software professionals spent 58% of their development efforts on code comprehension. https://ieeexplore.ieee.org/document/7997917
  5. 開発生産性・開発体験改善の Rules of Thumb コードを書く量を減らす、読む負担を下げるモチベーション 担当者が退職したり、担当者が他のプロジェクトに移った (&運が悪いと放置された )ものを引 き継ぐこともあります .

    動いている (≒お金を産んでいる )アプリケーションを触る際に既存の資産を有効活用するには 基本的に誰かの書いたコードを読まざるを得ません .
  6. 開発生産性・開発体験改善の Rules of Thumb より上流で問題を解決する &上流の都合を下流に漏らさない より上流で問題を解決する方がより多くのユーザーがその恩恵を受けられ、重複した作業が 減ります . なお、上流で行うだけでは不十分で、上流の

    (実装上の )都合を下流に漏らさないこ とが、ユーザーに本質的でない調査や変更を要求しなくていい ため望ましいです . 参考 : The golden Rules of software quality Open–closed principle
  7. 開発生産性・開発体験改善の Rules of Thumb 上流の都合を下流に漏らさないモチベーション あるサービス Aが上流の実装を漏らしていると、そのサービスを利用するクライアントは、サ ービス A が公開する

    API が、そのサービス Aが定める (依存してもいい安全な )仕様なのか、上 流のサービスの (安全ではない )実装なのか調査する必要があります .
  8. 開発生産性・開発体験改善の Rules of Thumb 上流の都合を下流に漏らさないモチベーション パブリックなインターフェースを公開する場合、公開する側は互換性維持の何らかのポリシ ー (※ )を定めるべきですが、あるサービス A

    が上流の実装を漏らしていると、サービス Aはコ ントロールできない上流の実装に関する互換性維持のポリシーという、できない約束をクラ イアントに対してすることになります . ポリシーを定めない (約束をしない )場合はサービス A以下のクライアント群がそれぞれ上流の 実装を吸収する処理を用意しなければなりません . ※ 例 : Go 1 and the Future of Go Programs Long-term compatibility plans for Scala 3
  9. 参考 : コード生成の例 IDL: protobuf Google Cloud SDK IDL: GraphQL

    GitHub API IDL: smithy AWS SDK IDL: thrift Open API Slack SDK おまけ : (コンパイル時 )マクロ Rust macro_rules! Template Haskell
  10. コード生成 : Motivation 仕様 First アプローチの強制 システム内・システム間のやりとりのあるべき状態が定義される 例えば、 protobuf を管理する中央レポジトリがあれば、それを

    spec の協議や 意思決定の場として利用できる サービス間の責任の範囲を決められる spec に書いたことは保証しなければならないが、書いていないものに依存し た場合は依存した側の責務と言い切れる
  11. 余談 : Open API(Swagger) は便利だが不十分 Open API(Swagger) は人間が見るドキュメントを生成するには便利だが機械的にコード生成 するには不十分 問題点

    コードジェネレータの仕様の違いによってシリアライズ・デシリアライズの実装が異な るので汎用的なコード生成器として利用できない 例 : oneof や enum フィールドの ser/de の (明確な )仕様はない 独自型・モジュール分割・参照の解決など、コードを組織化する基本的な機能が不十分 URI、 UUID や Duration 型など、中レベルの型へのマッピングが存在しない
  12. ZOZO Tech Blog: OpenAPI Generatorに適した OpenAPIの書き方 のように、汎用的なコード生成を優先して詳細な仕様書 (型定義 )としてのスキーマを諦める方 針もある

    . その場合、下流のサービスは、スキーマのコメントと上流の実装を信じるか、バリデーショ ンを再度行う手間が生じる .
  13. 余談 : Open API(Swagger) Alternatives Open API よりも新しい IDL(GraphQL スキーマ、

    Protobuf など ) と TypeScript・ Rust・ Kotlin・ Scala・ Swift などの比較的モダンな静的型付け言語の組み合わせならば、詳細な仕様 書 (型定義 )とコード生成を両立できる可能性が高い .
  14. モジュール分割 クリーンアーキテクチャ、ヘキサゴナルアーキテクチャなど、さまざまなアーキテクチャが あるが、肝心なのは I/O(特に DB、クラウドインフラやコントロール下にない API) や RPC フ レームワークとそれ以外がうまく分離されていること

    以下は一例 . {project root} └── modules ├── prelude: 特定のアプリケーションに依存しない型、機能や拡張. ├── core: ビジネスロジック. prelude に依存. | ├── feature-a | ├── ... | └── feature-z ├── cli(optional): core に依存. └── http: api と core に依存. web RPC フレームワークへの依存を含む.
  15. モジュール分割 : 「うまく」分離されている とは (ソースコードを入念に読まなくても )依存の方向や依存の内容が機械的に保証できる 例 : core モジュールが

    web フレームワークに依存していない 例 : コア部分を再利用して cli(など別の呼び出し方 ) を提供できる Convention over Configuration(CoC)を強制できる 内部の変更が外部に不必要に伝播しない 例 : prelude の変更は core には伝播するが cli や http には伝播しない 例 : prelude、 core、 http モジュールはそれぞれ別のライフサイクルを持てる コードベースが特定のフレームワークの寿命に影響されにくい
  16. モジュール分割 : App と Lib の分割 コアロジックと I/O や RPC

    フレームワークが分離されていると、モジュールをアプリケーシ ョンとライブラリに区別できる . ライブラリを GitHub Packages、 Google Artifact Registry、 AWS Code Artifact などで配布 すれば、効率よくバージョン管理や変更の伝播ができる . ※ ツールチェーンによっては GitHub Repository をそのまま依存のソースにできる . {project root} └── modules ├── lib:prelude: 特定のアプリケーションに依存しない型、機能や拡張. ├── lib:core: ビジネスロジック | ├── feature-a | ├── ... | └── feature-z ├── app:cli: core に依存. └── app:http: core に依存. web RPC フレームワークへの依存を含む
  17. 余談 : モジュール分割 : App と Lib の分割 ライブラリベースのアプローチは万能薬ではなく、ライブラリを中心とした設計にする場合 には以下の点を検討する必要がある

    . Google Artifact Registry、 AWS Code Artifact のようなセキュアで安定したライブラリ 配布基盤の用意 Self-Host Renovate のような Push ベースの依存更新自動化の用意 パッケージのバージョン管理・互換性チェックなどの自動化
  18. 再掲 : 開発生産性・開発体験改善の Rules of Thumb ボトルネックから改善する . コードを書く量を減らす .

    読む負担を下げる . より (依存関係の )上流で問題を解決する &上流の都合を下流に漏らさない .