🚃

未知の実装を恐れない:小さな不自然を見逃さない責務思考のススメ

2025/02/06に公開

TL; DR

  • システム開発において、毎回「慣れている方法で実装する」ではなく「責務的にはこのレイヤーで開発すべきだから、知らないことでも調べて開発する」という責務思考が成長のエンジンになる

本記事における“不自然なソースコード”の定義

不自然なソースコードとは、「 レビューで指摘されればすぐに“確かに”と納得するけれど、自分で書いているときには気づけなかったコード 」を指します。大規模アーキテクチャ上の根本的な誤りというよりは、たとえば以下のような“小さな違和感”が特徴です。

  • 本来はあるモジュールに責務があるのに、別のモジュールで無理やり実装されている
  • 変数や引数設計がチグハグになっていて、後続の処理で複雑な変換を強いられる

こうした不自然さは一見すると些細ですが、長期的な拡張性や保守性に悪影響を及ぼします。本記事では、不自然なソースコードの典型例を示しつつ、その背景と回避のポイントを考察します。


セレクトボックスの「未選択」と「選択しない」の扱い――よくある不自然さの例

不自然な実装例

React Hook FormやZodを使ったフォーム実装を考えてみます。要件としては以下のようなものです。

  • セレクトボックスで「未選択」の状態と「選択しない」を用意する
  • 見た目は異なるが、結果的な挙動は同じ(選択していない扱い)

ところが、実装者が以下のようなコードを書いてしまったとします。

// formのオプションを定義する処理にて
const allOption = { label: '選択しない', value: 'all' };
const hogeOptions = [
  allOption,
  ...hogeMaster.map((hoge) => ({
    label: hoge.name,
    value: String(hoge.id),
  })),
];

// react hook formのsubmitハンドラ内にて
// 「選択しない」を選択した場合は除外
if (value === 'all') return false;
// 上記以外は残す
return true;

いったんこれで動作はしますが、「value === 'all' なら除外する」という処理がSubmitハンドラに書かれている点が不自然です。本来はUIコンポーネント(セレクトボックス側)で「どちらを選んでも同じ値(たとえば undefined)をフォームに渡す」ようにしておけば、わざわざハンドラで特殊処理をしなくても済みます。

このように、後続のロジックで強引に変換するという実装スタイルは、機能拡張のたびに問題点が積み重なりやすいのです。

ここで主張したいことは、問題は実装が不自然であることそのものよりも、「実装の過程で責務が不自然なコードが仕上がったときに、そこから立ち戻れずに進んでしまった」という思考フローにあるということです。

理想的な方向性

  • セレクトボックス(UI)の責務として、「未選択」と「選択しない」の両方が undefined としてフォームに渡るようにする
  • どうしても「all」など特殊文字列を使いたい場合は、ZodのTransform機能などUIに近いレイヤーで変換する
  • 結果として、後工程での複雑な変換が不要になり、Submit関数やビジネスロジックが肥大化せずに済む

もちろん理想的な方向性では実装できないこともあるでしょう。しかしこの方向性で実装してみた結果、無理だったので後続の処理で変換しました、というフローを経たならば、同じsubmitハンドラに任せる方向でももっと責務を意識した実装やコメントで補足が行われた成果物になるはずです。


なぜ「不自然なソースコード」が生まれるのか

“社員”アナロジーで捉える責務の偏り

コードを社員にたとえると、それぞれが適切な役割(責務)を担うべきです。先の例ですと、UIを担当する社員、Validationを担当する社員、Submitハンドラを担当する社員、というふうに、処理の責務ごとに社員が分かれているイメージです。

しかし、実装者が「このモジュールならとりあえず実装しやすいから」「ここでまとめてやったほうが楽だから」と、Submitハンドラ社員に安易に責務を持たせてしまったのが今回の事例でした。そして結果的に一箇所がどんどん肥大化します。

  • 正しい姿:UIはUI、ドメインロジックはドメインロジックといった形で社員(モジュール)ごとに仕事を分担
  • 不自然な姿:社長(実装者)が“仕事を振りやすいから”といった手軽さで一人の社員に過剰な仕事を振り続ける

認知バイアスがもたらす「いま見えている方法で済ませる」心理

不自然な実装は、「スキル不足」よりも「いま分かる範囲で片付けてしまいたい」という認知バイアスに起因することが少なくありません。

  • 新しい技術やパターンを調べるのはコストがかかる
  • とりあえず手元ですぐ書ける実装を選んでしまう
  • 後になって複雑化に気づき、書き直しが困難に……

このバイアスを自覚するだけでも「本来どこで処理するのが自然か?」を意識しやすくなり、不自然さを回避するきっかけが生まれます。


「責務はここにあるはずだが、実装方法が分からない」ときのスタンス

責務の所在を先に決める

不自然な実装の多くは、「ここに責務があるはずだが、具体的な実装方法が思いつかない」状態で挫折し、他のレイヤーで無理やり片付けてしまうことに起因します。最初に決めておくべきは次の点です。

「分からないから他の場所で処理する」ではなく、「本来ここがやるべきなので学習や調査を進める」

たとえば、セレクトボックスで「未選択」を表現しづらいなら、React Hook Formやライブラリのドキュメントを読み直す、チームに相談するなどして、UI層で統一できる方法をまず探ります。

新しい知識を吸収する学習サイクル

「責務的にはUI層で処理したほうが良い。でもやり方が分からない」――このギャップこそが学習サイクルを生み出す原動力です。ZodのTransformを調べたり、React Hook Formの詳しいAPIを探索してみることで、結果的に知見が広がります。

もし「いつもの手軽なやり方」で済ませていたら、一生その“手軽な範囲”だけしか知識が増えないでしょう。コードに不自然さを残さず、責務に合った方法を模索する姿勢こそ、エンジニアの成長を促します。


不自然さを見逃さないことで得られる成長

他にもある「本当はもっとラクに書ける」例

セレクトボックス以外にも、「自分がまだ知らない方法」であれば簡潔に実装できるのに、知識不足や認知バイアスで遠回りしてしまうケースは多々存在します。たとえば以下のような例です。

  • SQLのWINDOW関数を使えば簡潔に集計できるのに、「どうせ複雑になりそう」と思い込み、結果的にアプリケーションメモリ上でループを回して処理してしまう
  • 初めて使う外部APIで実装するとき、本来はエラー監視やログ設計をしっかりすべきだが、「とにかく動くものを早く出そう」と省いてしまい、後々の障害原因を追えなくなる

これらは決して特殊な失敗談ではなく、「知らないからこそ、学ぼうという発想」に至らず、自分の見えている範囲だけで解決を急いでしまう典型的な例と言えます。

自分で偉そうに記事を書いておきながら恐縮ですが、これまで過去にやらかした事例をたくさん思い出してきました。知らないことに向き合うのは思った以上に難しいことですが、責務思考に立ち返ることで、本来やるべき実装指針を見つけられるはずです。

不自然さを排除するほど抽象化能力が高まる

小さな違和感をその都度丁寧に解消していくと、次第に「どのレイヤーにどんな責務を置くべきか?」という判断がスピーディーかつ正確になります。また、未知の技術を取り入れることに抵抗がなくなり、新しい課題に対しても柔軟に対処できるようになります。これは保守性・拡張性の向上はもちろん、エンジニア個人のキャリアアップにも直結するメリットです。


まとめ:不自然な実装を「今分かるやり方」で済ませない

  • 不自然なソースコードは、大抵「本当はこうするのが自然だけど、いま手元でラクに実装できる方法でやってしまう」という流れで生まれる
  • スキル不足というより、認知バイアスや慣れた方法への安易な依存が根本要因
  • 具体的な実装がすぐピンと来なくても、「本来ここに責務があるはずだ」というロジカルシンキングを先に行う
  • そこから調べたり試したりするプロセスで、未知の機能やパターンを吸収するチャンスが得られる

結果的に、その積み重ねがエンジニアとしての成長とプロダクトの品質向上の両方をもたらします。「小さな不自然だから」と見過ごさず、責務の所在を意識し、“学びの好機”を逃さない姿勢を持ちたいものです。


Edited with ChatGPT🧠
本記事はアウトラインおよび要点をChatGPTに投げて執筆を進めました。
業務内でプロジェクトの振り返りを行っているときに出てきた対話がベースになっており、主張は私自身のものですが、大半の文章がAI生成によるものです。

編集後記

  • GPTで記事を書かせるとき、キーとなる言い回しは指定すると、若干人間らしい文章に寄せることができそう
  • 本記事の内容、抽象化すると「エンジニアは如何にして無知の知を得るか」という議題に発展できそう。そう考えると、たとえば「実装方法は浮かばないけど世の中のWebサービスならたいてい悩みそうなことだからきっと解決できる」といった思考法も、自分が知らない解決策に至るためのヒントだったりしますね
  • 割と僕自身が、自分より知識がある人から根掘り葉掘り聞いて強くなろうという思考じゃなくて、自分で自分を強くなる方法を知っている方が、自分より知識がある人とGive-and-Giveの関係性になれてもっと良いよねみたいな指向性なので、そういう趣旨に寄りがちかもしれない
マナリンク Tech Blog

Discussion