コードの価値を高める、プログラミングのマイルール 2025
Table of Contents
2009年入学、2015年修士卒の鈴木孝宏(sussan0416)です。修了後は、10年間エンジニアをしています。途中フリーランスを5年やったりとかもありました。2025年1月、16年ぶりに、札幌にUターンしてきました。 アドベントカレンダーは現役の学生が多いですが、卒業生も参加OKとのことですので、今年も1参加させていただきます 🙇
今回は、最近考えていた、自分なりのプログラミングのルールを、書いてみたいと思います。AIによる補助が欠かせなくなった今、日々大量生産されていくアルファベットの羅列を見て、コードの価値ってなんだろうなと、改めて考えていました。また、AIが出してくる結果や、自分が出すプルリクエストを見ながら、動きそうだ・正しそうだと感じさせるにはどうしたら良いかを考えていました。このポストでは、その思考過程をたどりながら、コードの価値を高めるためのプログラミングのマイルールを示したいと思います2。
コードに価値はあるのか #
こんなこと言うと、怒られそうですけどね……(ちょうど良い表現が、他に思いつかなかった)。
私のようなソフトウェアエンジニアは、日々プログラミングをし、コードが書かれたテキストファイルを生産しています。しかし、このコード自体は成果物ではなく、コンパイルやビルドプロセスによって生み出された、動くソフトウェアが成果物(結果を検証できるもの)になります。成果物になって初めて、使える・使えないがはっきりするわけです。つまり、動いて使えるようになって初めて価値を持つ—誰かの課題を解決したり、助けたりできる能力を持つ—ということです。そう考えると、私たちが生産しているコードや、コードが書かれたファイルは、成果物ではない=価値はないということになるのでしょうか……?
例えば、社会人が日々生み出しているWordやExcelやPowerPointなどのドキュメント(文書)は、それ自体が結果であり成果物だったりもしますよね。価値あるものということですよね。
| ドキュメント(文書) | ソフトウェア | コード | |
|---|---|---|---|
| 成果物である (結果を検証できる) |
Yes | Yes | ? |
| 使える/使えないを判別可能 | Yes | Yes | ? |
正しさを検証できたもの = 使えるもの = 価値あるもの #
社会人が日々生み出すドキュメント(文書)は、ファイルを開いて読んでしまえば、内容の正しさ・明確さ・説得力などを検証することができます。 一方で、エンジニアが日々書いているコードは、それ自体を読んでも、正しさを検証することができません3。全く動かないプログラムである可能性もあるし、余計なことをするプログラムである可能性もあります。実際に動かしてみないと、検証することができないのです。
| ドキュメント(文書) | ソフトウェア | コード | |
|---|---|---|---|
| ファイルを開けば 検証可能 |
Yes | Yes | No |
わかりやすい例があります。読み慣れていないプログラミング言語で書かれたプルリクエストを、レビューすることになったとします。このとき、きっと、こんな気持ちになるのではないでしょうか。
「書いてあることは間違ってなさそうだけど、本当に動くの……?」
ルール1: コードを検証可能にする #
実装したコードが、本当に動くことを証明するには、それを実行するテストコード4を実装したら良いですね。 期待通り動くことを、テストコードで証明したら良いというわけです。
もし、さっき例えたプルリクエストの状況で、テストコードも用意されていたとします。このとき、きっと、こんな気持ちになるはずです。
「テストケースも妥当だし、テスト通ってるし、コードのほうも不自然な感じないから……まぁ良さそうかな。LGTM。」
この「テスト通ってるし」が重要です。これまで、コード単体では正しさを検証できなかったのが、テストコードと一緒になることで、検証可能なものになったのです。 正しさを検証できたコードは、使えるコードなので、価値があるコードになったということです。5
実装したコードが正しいことを保証するために……
- 可能な限りテストをつける
- 「テストが通る = 少なくともこの条件では動く」と分かるようにする
- テストコードを、実行可能な説明書・仕様書として扱う
ルール2: ドキュメントとしての価値を高め、作品に昇華する #
テストで検証して正しく動くことを保証することで、コードに価値を持たせました。 しかし、動く価値も大事ですが、そもそも、コード自体に読まれるドキュメントとしての価値を持たせられるのではないでしょうか。 コードが書かれたファイルや、プロジェクトのフォルダ全体を俯瞰した時に、まるで1つの作品のように構成することも、できるのではないでしょうか。
これを実現するために、自分なりに、以下のようなルールを設けて、実装してみています。
- フォルダ名・ファイル名・クラス名
- 「この仕様が書いてありそう」と期待させる名前をつける
- 言葉の定義を整理している意識で、ファイルを分ける
- 本の章立てを考える気持ちで、フォルダを分ける
- コード
- 1ファイルに書くコード量を、読める量にとどめる(僕は100行〜150行くらいで限界)
- クラス名からイメージできること以外は、書かない
- コードに対する意思決定の理由を、コメントとして残す
これらのルールがどれほど有効かは、最近始めたばかりなので、結論が出ていません。しかし、コードの明解さが変わってきたのは事実です。 例えば、ファイル名やクラス名で「ここで何を定義するか」をひとことで言えるようにすると、そのひとことで言える分だけを実装したら良いわけです。 もし、そのクラスをひとことで言うには具体的すぎる実装があったら、それは別ファイル・別クラスに切り出すべき詳細な情報ということになります。
import SwiftUI
/// ユーザーを新規作成するボタンのUIを定義する(それ以外は書かない)
struct CreateNewUserButton: View {
var body: some View {
Button(action: {
// 「ボタンのUIを定義する」と言っておいて、
// ボタンを押した時の処理を書くのは具体的すぎるので、
// `Action`に切り出してある
CreateNewUserAction().perform()
}) {
// ボタンのラベル(ボタンのUIだから、ここに書いてOK)
Text("Add User")
.foregroundColor(.white)
.background(Color.blue)
.cornerRadius(8)
}
}
}
このように、クラス・ファイルをひとことで言うには具体的すぎる部分を切り出す作業を続けていくことで、自然と、ロジックは小さく分割されていきます。
大きかったViewクラスは見た目だけを定義するようになり、onClickのような処理もActionクラス6を呼ぶだけになったり、通信もClientを経由するようになったりと、1つのクラスが小さくなっていきます。そして、全体を俯瞰してみると、 自然と組織化された作品(アーキテクチャ) のようなものになっていきます。
言い換えるなら、「仕様のありかを感じさせる名前にこだわる、名前と実装の一致を意識する、他の人が読んで辛くない量にする」という感じでしょうか。このルールを、しばらくの間、続けてみようと思っています。7
さてこれで、コード・ファイル・フォルダ自体を、まるで、言葉の定義を集めた辞書のような価値あるものとして、組織化することができたのではないでしょうか。
コードには価値がある #
ソフトウェアにならなければ価値を確かめられなかった(成果物として正しさを検証できなかった)コードが、今や、1つの作品のように、その存在自体が価値あるものになったような気がしてきます。ここで改めて、現時点でのプログラミングにおける私のルールを列挙します。
- テスト
- 可能な限りテストをつける
- 「テストが通る = 少なくともこの条件では動く」と分かるようにする
- テストコードを、実行可能な説明書・仕様書として扱う
- フォルダ名・ファイル名・クラス名
- 「この仕様が書いてありそう」と期待させる名前をつける
- 言葉の定義を整理している意識で、ファイルを分ける
- 本の章立てを考える気持ちで、フォルダを分ける
- コード
- 1ファイルに書くコード量を、読める量にとどめる(僕は100行〜150行くらいで限界)
- クラス名からイメージできること以外は、書かない
- コードに対する意思決定の理由を、コメントとして残す
このようなルールは、いろんな書籍8で当たり前のように「関心の分離」とか「単一責任の原則」などといった言葉で解説されています。しかし、正直なところ、あんまり腹落ちしていなかったんですよね……。
言っていることは分かるし、クラスを機能単位で小さくすることは意識してるけど、そもそも、関心とか責任って、結局なに……?
エンジニアを10年やっても腹落ちしていなかったのですが、ここまでの思考を通して、なんとなくわかったような気がします……。
その他のルール #
ルール3: 差分で変更意図を語る #
差分そのものも、ドキュメントとしての価値を持たせることができます。 差分を他人に見せた時に、その意図が伝わることを意識して、差分を作ります。
// 差分が語ってくれるようになる例え
var body: some View {
SurveyForm {
UserNameTextField()
+ FavoriteAnimeTextField() // あ、好きなアニメを書かせるのね
}
}
ルール4: 人間は設計に責任を持ち、実装はAIに穴埋めさせる #
AIに実装作業の全てを任せても良いのですが、プロジェクトのコードが無秩序になっていくことがあります9。 これを回避するため、AIに任せる前に、理想的なAPI(要するに設計)だけを書いておき、実装をAIに任せるやりかたを試しています。 このとき、静的解析のエラーは気にしません。また、多少のミスも気にせず、空クラス、空関数を作ります。
Button("Send Answer") {
// こんな感じで使いたいなーって書いておく。
// 静的解析がエラーでも気にしない。
SendSurveyAnswerAction().perform()
}
struct SendSurveyAnswerAction {
func perform() async throws -> AnswerID {
// 中身は空っぽ。AIに書いてもらう。
// 静的解析で returnしてない と言われても良い。
}
}
このように、空の実装を用意した上でAIに穴埋めさせれば、プロジェクトの秩序を保ちつつ、効率的に実装を進めることができるようになります。10
ルール5: importとレイヤーを結びつけない #
このクラスはEntityだけど、UIKit(iOSのUIフレームワーク)をimportしているから、このEntityは、UI層に置こう
いやいや、Entityなら、Entityに置こう。
UseCaseか……。ビジネスロジックだから、CoreGraphics(Appleの描画ライブラリ)はimportしちゃだめだな。 本当はCGImage(画像クラス)を使いたいところだけど、Dataで処理するかー、大変だけどなー……
UseCaseだろうと、CoreGraphicsをimportしたら良い。ビジネスロジックとかコアに近づくにつれて、言語のプリミティブな型だけを使わなきゃいけないって、そんなことはないはず。
まとめ #
ここ2ヶ月くらい考えていた、コードの価値や、自分なりのルールを、書き連ねてみました。 「こんなの当たり前すぎる!」という人や「これは違うんじゃない?」と思う人も、いるかもしれません。 もしかしたら、「このルールならできるかも!」と思ってくれる人も、いるかもしれません。 ここで挙げたルールは、まだまだ発展途上です。コードを書いていくうちに、また変化するでしょう。 他の方からのフィードバックや読んだ書籍から、考えをアップデートすることもあると思います。 したがって、このルールが最終形態とは思っていません。コードを書いて悩みながら、また、更新していくことでしょう。
最後に、「コードの価値」についてChatGPTと対話する中で定まってきた「自分用のチェックリスト」を、下に掲載して終わりにします。 長文ありがとうございました!
明日は、3パート全てで投稿があるようです。
- Part1 Sudoさん
- Part2 履修失敗さんの「芸術」
- Part3 Girky0815(1022034)さんの「Google Antigravity で Material 3 Expressive 風のタイマーアプリを作ってみた」
です!!
(ChatGPTと対話する中で固まってきた、自分なりのチェックリスト)
- 🔤 名前・責務
- ファイル名・クラス名から役割が想像できる
- 名前から想像できない処理を書いていない
- “何を書かないか”を明確にできている
- 📏 行数
- 1ファイルが概ね 100行前後で収まっている
- スクロールせずに全体像が理解できる
- 100行を越える場合、分割の検討をした
- 🧱 レイヤー
- import の種類でレイヤーを判断していない
- レイヤーは責務・依存方向・データフローで決めている
- 🧪 テスト
- テストが「実行可能な仕様書」になっている
- 実装したコードが意図通り動くことを保証できている
- 🔍 Git diff
- 差分だけで「なぜ必要か」理解できる
- 変更が小さく、役割が局所化されている
- クラス名・メソッド名と差分の内容が一致している
- 🎨 View(SwiftUI)
- View は 50〜100行前後に収まっている
- View を「置けば完結」になっている
- 「〇〇Viewでは、〇〇を定義する」以上のことを書いていない
- 👤 未来の読者への配慮
- 半年後の自分が読んでもわかる
- 命名・行数・構造・テストが“読む人”に優しい
- コメントは補足であり、主仕様はコードが語っている
もっとあるけど、このポストに関連あるものを掲載しました。
-
昨年のアドベントカレンダーの続きとして「この1年間でどれだけ未来大に関われたか - 2025年を振り返る」といったポストを書いていたのですが、誰得感が出てきてしまったので、別のテーマで書き直しました。 ↩︎
-
現段階での思考のスナップショットとして。書き残しておきます。 ↩︎
-
読めば明らかな場合もあるけど。 ↩︎
-
このポストでいうテストコードは、意図通り動作することを保証することが目的のコード。テストには、ユニットテストやインテグレーションテストなど様々な種類がありますが、結局はどれも、仕様を満たしていることを保証することが目的のはず。 ↩︎
-
まぁ、テスト自体が正しいこと、実装者が仕様を正しく理解していることが前提なんですけどね…。 ↩︎
-
ここでいうActionは、なんらかのアーキテクチャのActionではないです。SwiftUIだと、Buttonをタップした時に実行されるクロージャに、actionという名前付き引数になっているので、
Actionクラスってことにしています。ドメイン側のアーキテクチャがDDDだったら、Serviceになったりするかも? ↩︎ -
これらのルールは、もしかすると、主要な技術書では専門用語として出てくるものかもしれません。例えば「単一責任の原則」だったり、「関心の分離」だったり、何か別の名前がついているかもしれません。 ↩︎
-
これまで読んだ本だと、Clean Architecture、現場で役立つシステム設計の原則、ドメイン駆動設計入門、良いコード/悪いコードで学ぶ設計入門、プリンシプル・オブ・プログラング、脳に収まるコードの書き方など…… ↩︎
-
事前にきっちりと制約を決めておけば、アーキテクチャを毀損することなくバイブコーディングできますが、最初から制約が確定するプロジェクトは珍しい気がする。発展途上のプロジェクトだったり、チームのスキルが徐々に向上してきた場合(いや、まぁ往々にして個人開発がそうなのですが)、設計があとから決まっていく・変わっていくなんて、よくあることです。 ↩︎
-
AIも賢いですから、プロジェクトのアーキテクチャを認識して実装してくれます。よりプロジェクト固有の制約を伝えるために、CLAUDE.md・GEMINI.md・copilot-instructions.mdを使うことも有用です。人間が持つコンテキストをAIに十分に伝えることで、設計も含めて、AIに任せられるようになります。 ↩︎