
僕がプログラムを作る手順
プログラムを作る時に、紙に設計を書いてから書く人、いきなりコードを打ち始める人、色々なパターンがあると思います。
僕がプログラムを書く手順について雑にまとめてみました。
関数と書いてるものは、場合によってはクラス・メソッドその他かもしれません。ご自身の環境に合わせて適宜読み替えてください。
まずはプログラミング自身というよりはそこに至るまでの話から始めます。
脳内のあれこれを吐き出す
まずは何を作るのか、どうやって作るのか、なぜ作るのかなどを整理します。
紙やホワイトボードは最強です。UMLなりポンチ絵なり、文字なり好きな物をものすごい解像度で描けます。
安いノートを買ってきてもいいですし、ホワイトボードや、消せる紙、NuBoardなどを使うというのもいいでしょう。ちなみにお金を掛けずに擬似的NuBoardをするのであればクリアファイルを活用するといいでしょう。
タブレット+ペンもとても便利です。
ただ、僕がよくやるのは、プライベートなテキストファイルに脳内の全てを自然言語で吐き出すことです。実装しなきゃいけない要件、なぜ実装するのか?実装せずに済ませられないのか?技術的にどういう風にやるべきか?やりたいか?どれくらいの時間でできそうか?あるいはさらに、心境だったり、悩んでることだったりも書き出します。
テキストファイルの弱点は、一次元であることです。頑張って文字を並べれば、二次元っぽく扱えますが、基本的には一次元です。アウトラインツールを駆使したりして構造を作ることもできますが、紙やそれに類似するツールの方が遙かに簡単です。
思考の整理さえ出来ればいいので、紙でもテキストファイルでも、その時の自分に合ったやり方でやれば大丈夫です。
僕がテキストファイルに自然言語で吐き出すのをやる理由は、自分の思考を形にする事で脳から追い出すためです。綺麗に整形することは目的ではありません。整形は後からやればいいのです。同時に2つの事をすべきではありません。
原則
・ ある一つの作業をする時に複数のことをやらない
・ 作業はなるべく小さく分割する(数をこなす)
ある大きな、複数のことを含んだ作業というのは、やるの大変だし、手戻りがあるとタイムロスが激しいです。くりかえしますが大変です。
プログラムの設計論でも「密結合と疎結合」とか「1つのクラスには1つの責務」みたいなことが語られますが、人間の思考や作業も同様で同時にすることが増えれば増えるほど、複雑度は増します。先ほどの例でいえば、脳内を吐き出すことと、整理することは分けた方がシンプルになります。
ただし、密結合にも利点があるように、複数の作業を意図的に混ぜた方が効果的な場合もあります。ですので必ずしの守らなければいけないわけではないですが、原則として覚えておくといいでしょう。
物事をなるべく小さく切り分けるという、分割統治という考え方はプログラマなら、絶対に覚えておくべき事です。
ここまでは方法論でしたが、次に実際にプログラミングをするための準備として環境整備をします。
準備
プログラムを書くとき、余計なことを考えなくてもいいように準備が絶対に必要です。まず最初に、Hello, World でいいから動くことを優先します。これが出来てる事が大前提です。何かの理由で動かすことがどうしてもできない場合、それは開発が面倒・困難な環境だと言えます。
環境整備自体が目的ではないでしょうから、なるべく楽にセットアップ出来る方法を探っておくといいでしょう。
次に、コードを修正したら変更が反映されるか確認します。Hello, Worldの文言を変えたらそれが反映されるかどうか。これはわりとバカに出来ません。環境によってはキャッシュのせいで更新が効かないという可能性もあります。よくある凡ミスに「違うファイルをいじっていた」というのもあったりします。
コードを修正して変更が反映されるまでに時間がかかりすぎる場合も、わりと辛いので、マシンのスペックを上げる、開発環境を見直すなどが必要かもしれません。
・ プログラムを書いてそれが実際に動く環境を用意する
・ プログラムを修正してそれが反映されるか確認する
・ なるべくこれらを高速にできるようにする
脳内の全てを吐き出して、環境も整備したら、実際に作業開始です。
動くことを基準としたアプローチあれこれ
人間は、実際に行動しないとやる気が出ない生き物らしいので、まずはキーボードにあれこれ入力すると、それが火種になってくれることがあります。
TDD
TDD(テスト駆動開発)というものがあります。これはユニットテストを主体として開発していく設計論です。よくTDDを「最初にテストを書く(テストファースト)」や「全部のテストを書く(カバレッジ100%信仰)」と混同する人がいますが、全く違います。
TDDでのユニットテストは、ある関数の入力と出力はどういう形にすべきか?だけを手を動かしながら考えるためにあります。
1. データ入出力のユースケースを考えてユニットテストを書く
2. そのテストを満たせる最低限のコードを書く
3. コードを綺麗に書き直す
TDDの基本はこれら3つを繰り返すとされていて、これの繰り返しをテンポ良くやることがコツですが、必ずしも守るべきことではありません。
TDDとは、手を動かしながら設計を書く行為です。ユニットテストを記述し、それに対する実コードという形で、実際に動く設計書を書いているのです。
そのため、データのユースケースの洗い出し・整理・記述と、それに合わせた関数のインターフェース設計さえできればいいので、TDDのサイクルがどうこうは、どちらかというと「コツ」の話です。
ボトムアップで組み立てる事が得意な人や、演繹の得意な人ならこの3つのサイクルを回すことを主軸として、テストファーストでの実装まで踏み込めるかもしれませんが、できる限りは設計としてのTDDと、実装としてのテストファーストは、考え方を分けるべきです。
そもそも、TDDでは設計を大幅に見直す事もあるのでテストやコードは捨てることが普通にあります。
コンポーネントから作る
たとえばウェブ開発の場合、ある一定の単位のコンポーネントから作り始めるというアプローチがあります。この時アトミックデザインでいう原子・分子・有機体と分けたとして、どこから作ってもかまいません。
ボトムアップが得意な人は最小限の不可分な単位である原子からコツコツくみ上げるといいかもしれませんし、トップダウンが得意な人は有機体とかの大きなコンポーネントから作っていくといいかもしれません。
基本的にはコンポーネントにはまずダミーデータを入れて作り始めるといいでしょう。いきなりデータの流れ・やりとりとか考え出すとそれは「複数のことを同時にやっている」ことになります。
有機体からやるトップダウン方式の場合は、Figmaのようなデザインツールを使って画面のイメージ図を作成するか、あるいは単に紙にざっくり描いてから、それを満たすコンポーネントを作るといいでしょう。まずはコンポーネントで実際に画面が作ることを目標とします。
HTML/CSSを使って、実際に画面ができあがることをまず優先してみましょう。内部の細かい挙動は後で実装すればいいのです。同時に1つの事です。コンポーネントのサイズや役割が適切かどうかは少しずつリファクタリングを行います。
・ ざっくり見た目を作る
・ コンポーネントとして組み立てる
・ コンポーネントの名前・粒度・責務が適切になるようリファクタリング
・ ダミーデータ以外を流し込めるようにする
いってみれば見た目を使ったTDDみたいなものです。
データベースをアクセスするモジュールから作る
よくDDDやクリーンアーキテクチャでいうインフラ層・リポジトリ層から作るというアプローチです。この時必要なことはデータベースアクセスに特化することと、ビジネスロジックには依存しないことに注意するとクリーンになります。
RDBやNoSQL、あるいはブラウザのlocalStorageなど色々なものがあるでしょう。これもユニットテストと同様の考え方を持ち込むといいでしょう。
モジュールの設計が妥当かどうか?データベースの設計が妥当かどうか?を考えるのです。
モックを使ったユニットテストや、ダミーデータベースを実際に使ったテストをやるといいでしょう。後者は環境構築の手間や速度の問題と、複数のことを同時にやることになってしまいます。
たとえばSQLを使う場合、ユニットテストではモジュールの入出力と発行されるSQLをテストし、SQLを別途ダミーデータベースでテストする、という分割をしてもいいでしょう。
後者は時間がかかる代わりに、SQLが適切かどうかの確認ができます。後者はそれほどの頻度でテストする必要はないはずなので、分けておくのです。
ここまではユニットテストなどを駆使して実際に動くアプローチを紹介しました。次は動作しないアプローチを紹介します。
ダミー関数から書く
ある意味机上の空論設計と同じなんですが、ダミーとなる関数から書き始めるというやり方もあります。
function 飲み会() {
日程調整();
予約();
準備();
飲む();
死んだように眠る();
}
function 日程調整() {
// たぶん、調整さんかな…。まぁなんか考える!!!!
}
ニュアンスとしてはこんな感じでしょうか。関数名は英語が望ましいですが、説明のためなのでいったん日本語で書いてます。
ここからは2つパターンがあります。
1つ目は、設計に注力すること。これは関数の呼び出し階層を設計することだけ考えることです。どういうパーツが必要なのかを擬似的なコードで表現する行為です。
2つ目は、勝手に動いてくれる最小限のコードを書く。TDDでやってもいいですし、TDDと同じ事をユニットテストではなく、最小限動作するアプリから作っていく(手動で動作を確認する)という方法もあります。
ただし後者はコナン・ザ・バーバリアン(グレート)みたいな蛮族のプログラミングです。力こそパワーな人が、力任せにやる行為と言えます。文明人にはTDDなりユニットテストをオススメします。
スパイクを打つ
スパイクが何か?というと、プログラミングにおいて大切な 'スパイクを打つ'とは? などの記事を読んでみてください。いきなり大きな単位を作るのではなくて、小さな単位で技術検証をするものです。
この時コツとして、スパイク単独で動くようにしましょう。プロジェクトの大きなディレクトリ内にスパイクのコードを入れようとすると泥沼です。
まとめ
人間は複数のことを同時にやろうとすると脳がパニックを起こします。頭のスペックがスゴイ人はそれができちゃうようですが、そういう人でも例えば病気などによってスペックが一時的に落ちるケースもあり得ます(うつ病とかまさにスペックがめっちゃ落ちるやつ)。
そのためには、複数のことを同時にやらないというのが大切です。小さいものを組み合わせる、あるいは実際に動く物から詰めていく、みたいなアプローチをそれぞれ試してみるといいかもしれません。
やり方は1つではありません。1つのやり方だけを採用する必要もありません。
気軽にクリエイターの支援と、記事のオススメができます!