自走プログラマ

最終更新日

清水川貴之,清原弘貴,tell-k 著,株式会社ビープラウド 監修

コード実装

1.1 関数設計

  • [ ] 関数名は処理内容を想像できる名前にする
  • [ ] 関数名はより具体的な意味の英単語を使おう
  • [ ] 関数名から想像できる型の戻り値を返す
  • [ ] 副作用のない関数にまとめる
  • [ ] 意味づけをできるまとまりで関数化する
  • [ ] リストや辞書をデフォルト引数にしない
  • [ ] コレクションを引数にせず、intやstrを受け取る
  • [ ] インデックス番号に意味を持たせない
  • [ ] 関数の引数に可変長引数を乱用しない
  • [ ] コメントには「なぜ」を書く
  • [ ] コントローラには処理を書かない

1.2 クラス設計

  • [ ] 辞書ではなくクラスを定義する
  • [ ] Data classを使う
  • [ ] 別メソッドに値を渡すためだけの属性を設定しない
  • [ ] インスタンスを作る関数をクラスメソッドにする

1.3 モジュール設計

  • [ ] utils.pyのような汎用的な名前を避ける
  • [ ] ビジネスロジックをモジュールに分割する
  • [ ] モジュール名のおすすめ集

1.4 ユニットテスト

  • [ ] テストにテスト対象と同等の実装を書かない
  • [ ] 1つのテストメソッドでは1つの項目のみ確認する
  • [ ] テストケースは準備、実行、検証に分割しよう
  • [ ] 単体テストをする観点から実装の設計を洗練させる
  • [ ] テストから外部環境への依存を排除しよう
  • [ ] テスト用のデータはテスト後に削除しよう
  • [ ] テストユーティリティを活用する
  • [ ] テストケースごとにテストデータを用意する
  • [ ] テストの実行順序に依存しないテストを書く
  • [ ] 戻り値がリストの関数のテストで要素数をテストする
  • [ ] テストで確認する内容に関するデータのみ作成する
  • [ ] 過剰なmockを避ける
  • [ ] カバレッジだけではなく重要な処理は条件網羅する

1.5 実装の進め方

  • [ ] 公式ドキュメントを読もう
  • [ ] 一度に実装する範囲を小さくしよう
  • [ ] 基本的な機能だけ実装してレビューしよう
  • [ ] 実装方針を相談しよう
  • [ ] 実装予定箇所にコメントを入れた時点でレビューしよう
  • [ ] 必要十分なコードにする
  • [ ] 開発アーキテクチャドキュメント

1.6 レビュー

  • [ ] PRの差分にレビュアー向け説明を書こう
  • [ ] PRに不要な差分を持たせないようにしよう
  • [ ] レビュアーはレビューの根拠を明示しよう
  • [ ] レビューのチェックリストを作ろう
  • [ ] レビュー時間を予め見積もりに含めよう
  • [ ] ちょっとした修正のつもりでコードを際限なく書き換えてしまう

モデル設計

2.1 データ設計

  • [ ] マスターデータとトランザクションデータを分けよう
  • [ ] トランザクションデータは正確に記録しよう
  • [ ] クエリで使いやすいテーブル設計をする

2.2 テーブル定義

  • [ ] NULLをなるべく避ける
  • [ ] 一意制約をつける
  • [ ] 参照頻度が低いカラムはテーブルを分ける
  • [ ] 予備カラムを用意しない
  • [ ] ブール値でなく日時にする
  • [ ] データはなるべく物理削除する
  • [ ] Typeカラムを神格化しない
  • [ ] 有意コードをなるべく定義しない
  • [ ] カラム名を統一する

2.3 Django ORMとの付き合い方

  • [ ] DBのスキーママイグレーションとデータマイグレーションを分ける
  • [ ] データマイグレーションはロールバックも実装する
  • [ ] Django ORMでどんなSQLが発行されているか気にしよう
  • [ ] ORMのN+1問題を回避しよう
  • [ ] SQLから逆算してDjango ORMを組み立てる

エラー設計

3.1 エラーハンドリング

  • [ ] 臆さずにエラーを発生させる
  • [ ] 例外を握りつぶさない
  • [ ] Try節は短く書く
  • [ ] 専用の例外クラスでエラー原因を明示する

3.2 ロギング

  • [ ] トラブル解決に役立つログを出力しよう
  • [ ] ログがどこに出ているか確認しよう
  • [ ] ログメッセージをフォーマットしてロガーに渡さない
  • [ ] 個別の名前でロガーを作らない
  • [ ] Info, errorだけでなくログレベルを使い分ける
  • [ ] ログにはprintでなくloggerを使う
  • [ ] ログには5W1Hを書く
  • [ ] ログファイルを管理する
  • [ ] Sentryでエラーログを通知・監視する

3.3 トラブルシューティング・デバック

  • [ ] シンプルに実装しパフォーマンスを計測して改善しよう
  • [ ] トランザクション内はなるべく短い時間で処理する
  • [ ] ソースコードの更新が確実に動作に反映させる工夫をしよう

システム設計

4.1 プロジェクト構成

  • [ ] 本番環境はシンプルな仕組みで構築する
  • [ ] OSが提供するPythonを使う
  • [ ] OS標準以外のPythonを使う
  • [ ] Docker公式のPythonを使う
  • [ ] Pythonの仮想環境を使う
  • [ ] リポジトリのルートディレクトリはシンプルに構成する
  • [ ] 状況依存の設定を環境変数に分離する
  • [ ] 設定ファイルもバージョン管理しよう

4.2 サーバ構成

  • [ ] 共有ストレージを用意しよう
  • [ ] ファイルをCDNから配信する
  • [ ] KVS(Key Value Store)を利用しよう
  • [ ] 時間のかかる処理は非同期化しよう
  • [ ] タスク非同期処理

4.3 プロセス設計

  • [ ] サービスマネージャーでプロセスを管理する
  • [ ] デーモンは自動で起動させよう
  • [ ] Celeryのタスクにはプリミティブなデータを渡そう

4.4 ライブラリ

  • [ ] 要件から適切なライブラリを選ぼう
  • [ ] バージョンをいつ上げるのか
  • [ ] フレームワークを使おう(巨人の肩に乗ろう)
  • [ ] フレームワークの機能を使おう

4.5 リソース設計

  • [ ] ファイルパスはプログラムからの相対パスで組み立てよう
  • [ ] ファイルを格納するディレクトリを分散させる
  • [ ] 一時的な作業ファイルは一時ファイル置き場に作成する
  • [ ] 一時的な作業ファイルには絶対に競合しない名前を使う
  • [ ] セッションデータの保存にはRDBかKVSを使おう

4.6 ネットワーク

  • [ ] 127.0.0.1と0.0.0.0の違い
  • [ ] ssh port forwardingによるリモートサーバーアクセス
  • [ ] リバースプロキシ
  • [ ] Unixドメインソケットによるリバースプロキシ接続
  • [ ] 不正なドメイン名でのアクセスを拒否する
  • [ ] hostsファイルを変こすいてドメイン登録と異なるIPアドレスにアクセスする

やることの明確化

5.1 要件定義

  • [ ] いきなり作り始めてはいけない
  • [ ] 作りたい価値から考える
  • [ ] 100%の要件定義を目指さない

5.2 画面モックアップ

  • [ ] 文字だけでは伝えず、画像や画面で伝える
  • [ ] モックアップは完成させよう
  • [ ] 遷移、入力、表示に注目しよう
  • [ ] コアになる画面から書こう
  • [ ] モックアップから実装までをイメージしよう
  • [ ] 最小で実用できる部分から作ろう
  • [ ] ストーリーが満たせるかレビューしよう

ryuichi