どんな記事か?
こちらのイベント参加の記事になります。
筆者自身の経験をもとに、コードのシンプルさを保つために難しい技術的な部分ではなく、誰でも意識しだいで取り組めて、プログラミンをする上で重要だと感じたことを記事にさせて頂きます。
KISSの原則
いきなりですが、KISSの原則をご存知でしょうか。
有名な原則のうちの1つで、「Keep it simple stupid」の頭文字をとったものです。
直訳すると「簡潔にしておけ、この間抜け」となりますが、「シンプルさを追求すべきだよね」という原則です。
コードが複雑になると、複雑さ自体がリスクとなります。
ここでいうリスクとは以下を指します。
- 拡張性が低く使いづらい
- コードの可読性が低く読みづらい
- 開発・保守のコストが高い
コードが複雑になりやすいケースとは
では、コードが複雑になりやすいケースとはどんなケースでしょうか?
もちろんプロジェクトや環境によって異なりますが、大きく分類すると以下の4つかなと思います。
- 仕様そのものが複雑なケース
- 言語やフレームワークへの知見が少なく、複雑になってしまうケース
- リーダブルコードや設計(ここではレイヤーを指します)への知見が少なく、複雑になってしまうケース
- 前提が間違っており、間違ったまま進めた結果、コードが複雑になってしまうケース(今回取り上げるケース)
それぞれのケースを解説
それぞれのケースを解説いたします。
1. 仕様そのものが複雑なケース
まず、「仕様そのものが複雑なケース」です。
大規模なアプリなどリッチなものを作ろうとすると、どうしても仕様が複雑になってしまいます。
仕様が複雑である場合、あたり前ですがそれを実現させようとするコード自体も複雑になりやすいと言えます。
対処法
交渉できる余地があれば、要求レベルをなるべく落とさずに仕様を簡単な方向へ倒すなど対応が必要です。
交渉できる余地がなければ、できる範囲で複雑にならないように実現するしかありません。
また、ハードルはかなり高くなってしまいますが、頭の良い先人たちがプログラマが遭遇する同じような問題を解決すべく、パターン化された「デザインパターン」を適切に取り組むことも手段の1つだと思います。
2. 言語やフレームワークへの知見が少なく、複雑になってしまうケース
続いては、「言語やフレームワークへの知見が少なく、複雑になってしまうケース」です。
機能を実現させるコードを簡潔に記述する術がわからず、「あぁでもない、こうでもない」とゴニョゴニョ遠回りしてしまうケースです。
(簡潔 = ワンライナーではございません。筆者は過度なワンライナー否定派です)
対処法
これは単純に経験と知見を蓄えていくしかないため、自分で色々勉強しながら、優しい先輩に教えてもらいつつ、蓄えていきましょう。
新しい気づきや教えてもらったことは、忘れないようにしっかりメモして引き出しを増やしていきましょう。
3. リーダブルコードや設計への知見が少なく、複雑になってしまうケース
続いて3点目は、「リーダブルコードや設計への知見が少なく、複雑になってしまうケース」です。
設計とは大きな枠ではなく、レイヤーのことを指しています。
レイヤーについては深堀致しませんが、View層であれば「関心ごとが見た目だけになっていて、ビジネスロジックとは切り離されているか」、などです。
つまり、「適切な関心の分離」がなされているかになります。
また「リーダブルコード」とは、オライリーから出版されている書籍です。
リーダブルコードには、命名についてや単一責任の原則などすぐに取り組めて且つ、効果の大きな手法が数多く記載されています。
個人的には、全プログラマーにおすすめしたい書籍で多くの学びがあります。
対処法
レイヤー云々は全体を見渡す必要があるため、先輩にしっかりと教えてもらいながら、ぼんやりとでも意識できるようになれれば良いかなと思います。
最初の頃はリーダブルコードの手法を実践するだけでも、コードのシンプルさを保てるようになると思います。
筆者がかなり初期の頃に、簡単にまとめた記事がございますので、リンクだけ載せておきます。
4. 前提が間違っており、間違ったまま進めた結果、コードが複雑になってしまうケース
最後に、今回取り上げるケースになります。
こちらに該当するのは、仕様が複雑ではないのにコードが複雑になってしまうようなケースが該当いたします。
難しい技術的な話ではなく そもそもやろうとしている前提が誤っていれば、当然アウトプットされるものも間違っているよね という内容です。
例えばですが、「仕様を正しく理解しておらず、なんとなくコードを書き始めたらコードがごちゃごちゃになってしまった」など。
対処法
では、前提が正しいかどうか? をどうやって判断すれば良いのでしょうか?
ここからは、筆者が有効だと感じた、「クリティカルシンキング」について述べさせていただきます。
クリティカルシンキングとは?
まず、クリティカルシンキングとは?ですが、批判的思考法 と呼ばれています。
批判とは決して「攻撃的に批判する」ということではなく、ソースに対して常に疑問を持つ思考法の1つです。
そのため、目的を常に意識して「そもそも何を作ろうとしているのか?」と一度立ち止まって、本質を深堀していく思考法です。
出典元)https://manetore.net/glossary3815/
クリティカルシンキング特徴
クリティカルシンキングの簡単な特徴です。
- 批判的思考法
- 攻撃的という意味ではない
- ソースに対して常に疑問を持つこと
- 目的を常に強く意識する
- そもそも何のためにやるのか
- そもそも何を解決させたいのか
- 考え方のクセを理解する
- 本質まで考え続ける
- 目的達成のための思考法などと呼ばれる
ロジカルシンキングとの違い
思考法のフレームワークとして「ロジカルシンキング」がございますが、ロジカルシンキングとクリティカルシンキングとの違いについてです。
出典元)https://dyzo.consulting/5222/
上記図を見ていただいてわかるように、ロジカルシンキングは複数のソースや前提から積み上げて結論を導き出したり、逆に1つの問いからツリーを複数生やして思考を広げたりする手法です。
一方のクリティカルシンキングは、「そもそもの前提が正しいのか?」を常に問い続けます。
根本や前提が違えば、導き出されるものは全く違ったものになってしまう
ロジカルシンキングでいかに筋の通った結論を出したとしても、前提が間違っていれば導き出されるものも当然間違ってしまいます。
仕様が複雑ではないのに、コードが複雑になってしまうのは経験上このケースが該当すると感じます。
クリティカルシンキングで前提を見直してみる
クリティカルシンキングを用いて前提を見直す際に、筆者が留意している点がございます。
- そもそも何を実装 / 解決したいのか
- 仕様自体を正しく把握できているか
- 誤った認識で誤った機能を作ろうとしていないか
- 仕様が複雑すぎるのであれば、要求レベルを落とさずに仕様をシンプルな方向へ打診してみる
- 何を実現させたいのか、仕様を正しく理解できていれば仕様レベルでの打診ができるようになる
- 仕様自体を正しく把握できているか
- そもそもコードを書いているレイヤーは正しい場所か
- 例:View層にビジネスロジックが混じっていないか
- 使う側に知識があるとバグの元となり、保守も大変
- 例:View層にビジネスロジックが混じっていないか
- そもそも性質の違うものを無理に共通化しようとしていないか
- アクターは誰なのか?
- 元々違うドメインのものを合体させようとすると、歪になる
- etc...
これらに留意することで、コードが複雑になっている時点で、前提が誤っていないか立ち止まって振り返ることができます。
実際に筆者が陥ったケース
実際に筆者自身が、陥ってしまいコードの複雑さと格闘していたケースです。
- やろうとしたこと
- 共通コンポーネントを作成したい
- 共通側はどんなデータかを知る必要がないようにしたい
- 前提が誤っていた時の状況
- usecase層で記述していたが、デザイン(UI)があったり、componentに依存方向が向いてしまっていた
- 実装を進めていくと、共通コンポーネントなのに、ジェネリクス以外の具体的な型があったり、TypeScriptの型を実装のために捻じ曲げてオプショナルにしてしまったり、本末転倒な状態になっていた
- コードが複雑怪奇で実装にも時間がかかっていた
- 根本を見直した後
- usecase層ではなく適切なレイヤーへ置いた
- 実装のために型を捻じ曲げる必要が無くなった
- 不要なコードがなくなり、見通しがよくなった
- 結果コード自体がシンプルになった(KISSの原則)
このように、コードが複雑になっているなと感じた時点で、前提を見直していくことで、コードをシンプルに保つことができました。
まとめ
今回のまとめです。
- KISSの原則とは
- 「コードはシンプルにしよう」と言う原則
- コードが複雑になりやすいケースとは
- 仕様そのものが複雑なケース
- コードも複雑になりがち
- 言語やフレームワークへの知見が少なく、複雑になってしまうケース
- 思ったようにコーディングできなくて、ゴニョゴニョなってしまうケース
- リーダブルコードやレイヤーへの知見が少なく、複雑になってしまうケース
- 責務の分離や手法への知見が乏しいケース
- 前提が誤っており、間違ったまま進めた結果、コードが複雑になってしまうケース
- 今回取り上げたケース
- 仕様はシンプルにも関わらず、コードが複雑になってしまうケース
- 仕様そのものが複雑なケース
- クリティカルシンキングとは?
- 批判的思考法
- 攻撃的という意味ではない
- ソースに対して常に疑問を持つこと
- 目的を常に強く意識する
- そもそも何のためにやるのか
- そもそも何を解決させたいのか
- 考え方のクセを理解する
- 本質まで考え続ける
- 目的達成のための思考法などと呼ばれる
- 批判的思考法
- コードが複雑になっていれば、一度立ち止まって前提を見つめ直してみる
最後に
コーディングしていると、目の前の機能実現に向けて一杯一杯になり、視野が狭くなってしまう時がどうしてもあると思います。
しかし、客観的にコードを見つめ直してみた時に、「コードが複雑になっているな」と感じることがあれば、一度立ち止まって前提を見直してみることをおすすめいたします。
経験が浅ければコードが複雑になっていることすら気づかないケースもあるでしょう。
その時は書籍を読んでみたり、ちゃんとしたレビューを受けたりして、 まずは「気づけるようになること」 を目標に、焦らずゆっくり経験を積んでいきましょう。
諸先輩の皆さん通ってきた道です。
諦めず正しい方向性で努力すれば、必ず点と点とが結びついて「そういうことだったのか!」となる時が必ず訪れます。
「継続は力なり」です。
以上、新人プログラマ応援 イベント参加の記事でした。