世界を動かす技術を、日本語で。

ソフトウェアエンジニアリングにおける「良いセンス」とは何か?

概要

  • 技術的センス技術的スキル は異なる概念
  • センスは 価値観の選択 に関わり、スキルは 能力 に関わる
  • ソフトウェア開発では 価値観の優先順位 がセンスを決定
  • 柔軟性の欠如 が悪いセンスの主因
  • 良いセンスは 状況に応じた価値観の選択 で判断

技術的センスと技術的スキルの違い

  • 技術的スキル :勉強や反復によって向上する能力
  • 技術的センス :どのようなコードや設計が「良い」と感じるかという 価値観
  • スキルが高くてもセンスが悪い、逆に スキルが低くてもセンスが良い 場合も存在
  • 料理で例えると、「味の違いが分かるが、まだ自分で作れない」状態がセンス先行
  • センスは 経験や観察価値観の選択 で育つ傾向

ソフトウェアにおけるセンスの指標

  • どんなコードが「美しい」と思うか
  • どんなコードや設計が「醜い」と感じるか
  • どの設計判断に強い満足感を覚えるか
  • どんな技術的問題に強い関心やストレスを感じるか
  • どの問題を簡単に受け流せるか

センスとスキルの違いの具体例

  • 例:mapやfilterの利用を好むエンジニアとforループを好むエンジニア
    • mapやfilterは 純粋関数 でバグが減る、直感的に「良い」と感じる
    • 一方、Golangのようにforループが性能的・拡張的に優れている場合も
    • 好み=価値観の違い であり、スキルの優劣ではない

技術的センスの本質

  • ソフトウェア設計は トレードオフ の連続
  • 全ての技術的判断にはメリットとデメリットがある
  • 未熟なエンジニア :自分の好みを「絶対正しい」と思い込む傾向
  • 成熟したエンジニア :両方の立場や価値観を理解し、状況ごとに最適な選択を意識
  • センスとは「技術Xが技術Yより常に優れている」ではなく、「この状況ではXのメリットがYを上回る」と判断できる柔軟性

エンジニアの価値観(センス)を構成する要素

  • Resiliency(耐障害性) :障害発生時の自動回復力

  • Speed(速度) :理論上の限界にどれだけ近いか

  • Readability(可読性) :新規参加者への説明容易性、短く分かりやすい関数名、ドキュメントの充実度

  • Correctness(正確性) :不正な状態の防止、テストや型・アサートの徹底、形式手法の活用

  • Flexibility(柔軟性) :拡張・修正の容易さ、影響範囲の小ささ

  • Portability(移植性) :特定環境への依存度、他環境への再展開の容易さ

  • Scalability(スケーラビリティ) :トラフィック増加時の対応力、自動スケールの可否

  • Development speed(開発速度) :拡張の速さ、専門知識の必要性

  • その他: エレガンス、最新技術、オープンソース活用、運用コスト など

    • 価値観の優先順位が 個々のセンス を決定
    • 例: 速度・正確性重視ならRust可搬性よりスケーラビリティ重視ならAWS特化 など

悪いセンスの特徴

  • プロジェクトに合わない価値観 を押し付ける傾向
  • 過去の成功体験から「自分の好きなやり方」を強く主張
  • 「ベストプラクティスだから」と 文脈を無視した判断 をする
  • 柔軟性の欠如 =悪いセンス
  • 特定領域では有効でも、 環境やプロジェクトが変わると機能しなくなる

良いセンスの特徴

  • 技術的能力 よりも 状況に合った価値観の選択 ができること
  • お題や模擬問題ではなく、 実際のプロジェクト で成果が出ているかで判断
  • 様々な種類のプロジェクトで 設計判断が成功しているか が指標
  • 柔軟性と観察力 を持ち、状況ごとに価値観の優先順位を調整できる

良いセンスの育て方

  • 多様なプロジェクト経験 を積む
  • 各プロジェクトで「どこが簡単で、どこが難しいか」に注目
  • 普遍的な正解や強い意見 を持ちすぎず、柔軟性を重視
  • 時には 経験より早くセンスを身につける人 も存在

まとめ

  • 技術的センス は、プロジェクトごとに最適な価値観を選び取る能力
  • 柔軟性と観察力 が良いセンスの鍵
  • 自己の価値観 を絶対視せず、状況に応じて変化させる姿勢が重要

Hackerたちの意見

このことの面白い結果の一つは、センスの悪いエンジニアは壊れたコンパスのようだということ。正しい場所にいると、壊れたコンパスでも北を指す。でも、動き出すとその壊れたコンパスが間違った方向に導いてしまう。だから、センスの悪いエンジニアでも、彼らの好みがプロジェクトのニーズと合致する特定のニッチではかなり効果的だったりする。この段落は、エンジニアリングの文脈で誰かのセンスを議論することが基本的に無意味だと思う理由をよく表している。この「予測可能に壊れたコンパス」の人は目立つから、20分の行動面接をすればフィルタリングできる。でも、もっと危険なのは「部分的に壊れたコンパス」で、一見するとちゃんと機能しているように見えるけど、実際には常に127度ずれている。

「部分的に壊れたコンパス」のエンジニアの例を挙げてもらえる?

良いセンスっていうのは、誰もが「そんなの誰でも書けるよ!」って言うような、シンプルに見えるコードを書くことだよね。

それが僕の基準でもある。複雑なものをシンプルなステップにまとめられる人にはいつも感心する。K&R Cの例のコードみたいにね。でも、お願いだから、もっと良いコメントを残してほしい。

プロジェクトに適したパフォーマンス要件とのバランスを取ることも大事だし、同じように健全なコミュニティがあって、続けていけそうな依存関係を選ぶことも大切だよね。ベンダーを選ぶときも同じで、「次の契約更新のときにぼったくられるか?」とか「もしぼったくられたらどんな選択肢があるか?」って質問が必要。

みんな「そんなの誰でも書ける!」って言うけど、問題の領域によるよね?ファスト逆二乗根[0]のコードを良いセンスだと思う? [0] https://en.wikipedia.org/wiki/Fast_inverse_square_root#Overv...

必須のシンプルさを簡単に。何かがシンプルだからって、誰でも理解できるわけじゃないからね。

そして悲しいことに、こういうコードの作者は、KISS原則に従って他の人の時間と労力を節約していることに対して、認識されないことが多い(たいていそうだよね)。理由は分からないけど、他の人には透明じゃないみたい。だから、テクノロジー業界には、無駄な複雑さを持つシステムを扱ったり維持したりするための仕事やチームが存在しているんだ。

でも、問題は人にその価値を理解してもらうことなんだよね。コードが退屈に見えるし、実際退屈だし。多くのジュニアだけど優秀でやる気のある開発者(自分も含めて)は、賢いコードを書きたいと思ってるけど、実際にはその必要がない環境にいることが多い。CRUDのバックエンドとフロントエンドにはこの問題があって、複雑さは(あるべきではない)コード自体ではなく、ドメインやアーキテクチャなどの高次の部分にあるんだよね。それに、退屈さからアーキテクチャを過剰に複雑にする人たちもいて、スケーリングのような見かけ上の問題やカゴ文化に基づいて、マイクロサービスやラムダを持ち込む代わりに、単純で実績のある解決策で目の前の問題を解決することをしないんだ。だから、「シンプルなCRUDアプリケーションのためのJava開発者を探しています」っていう求人では、優秀な開発者は見つからないよ。

その通り。エンジニアが特別なことをする能力があるのは時々便利だけど、最初は手強そうに見える問題に対して、シンプルで普通の解決策を一貫して見つける方がもっと良いよね。

それは良いセンスじゃなくて、良いエンジニアリングだね。

ソフトウェアは一目で理解しやすく、新しいエンジニアがオンボードしやすいか?これは思ったより難しい。そもそも「新しいエンジニア」って誰?ジュニア?10年の経験者?30年?どんな基準があるの?「可読性」って本当に幅広い概念で、ゼロから無限までの許容レベルがある。可読性は実際には非概念的なものだよ。マクスウェルの有名な方程式は、ある人には読みやすいけど、他の人には全く理解できない。だから「コードは可読性が必要」と言うとき、具体的に誰に向けて言ってるの?

読めないコードには2つの広く見られるクラスがある。誰にも読めないコード。これは読めないコードだ。それから、作者(AIでも人間でも)にしか読めないコード。これも読めないものだ。「可読性は概念ではない」と言うのは本当に変だ。

反対だな。誰かがコードを読む能力は指数関数的に成長するわけじゃない。数年の経験を積むと、みんな同じプラトーに達する。経験年数が多いからと言って、もっと複雑なコードを理解できるわけじゃない。「3〜4年の経験があるエンジニアの大多数にとって可読性がある」と目指すなら、それが目標に達しているってことだよ。

その方程式の話だけど、彼が書いたときはかなり難解だと考えられてたんだよね。今のものはずっと美しくて「読みやすい」とされてるけど、それはヘイヴィサイドや他の人たちの仕事のおかげなんだ。

+1、著者自身の話に戻るけど、慣れが大きな役割を果たすよね。新しいエンジニアがマッピングやフィルタリングに精通していれば、手動ループがほとんどないコードベースに乗り込むのが楽になると思う。

完全に同意。読みやすさは実際に「読む」+「能力」という言葉そのものにあるよね。コードと読者の両方の能力が関わってる。

私をナイーブだと思ってもいいけど、ジュニアでも会社で働き始めたら、基本的な構文やイディオムには慣れてるべきだと思うんだ。それでも、言語の特徴を使いすぎると、誰にとってもコードが読みづらくなることがあるよね。例えば、古典的なif/elseを好む人もいれば、悪名高い三項演算子やその多くの子孫を使うのを好む人もいる。でも、結局は自分の好みに戻るんだよね…

読みやすいコードは、読者に対する共感を持っていて、解釈の認知負荷を最小限にしようとするコードなんだ。それが抽象化レイヤーやデザインパターンの目的の一つでもある。確かに、これは主観的で、読者の専門知識やコードベースへの既存の慣れに依存するけど、コードの読みやすさが存在しないって主張するのはおかしいよね。ジョイスの『ユリシーズ』がスースの『キャット・イン・ザ・ハット』と同じくらい読みやすいって言うの?

コードの可読性は指標じゃないよ。トレードオフなんだ。結局のところ、プログラマーが迷ったときに、読みやすいコードを選ぶか、ちょっと難解で巧妙なハックを選ぶかってことだね。

「ローカルコード」の可読性について悩む価値はほとんどないよ。コードベースの大部分で同じパターンを使うことが、全体の可読性を高めるんだ。たとえそのパターンが複雑でも、あまり逸脱せずに繰り返し使われる限り、コードベースは可読性を保つことができる。要するに、ローカルで孤立したコードは、コードベース全体に感染しなければ、どんなに読みづらくても問題ないんだ(共有可能なミュータブルステートや悪いAPIを使うことで感染する場合を除いて)。

ファッションの分野で「良いセンス」とは、独自の方法で服を選び、それがうまく組み合わさる人を指す。独立していると意味がない服でも、組み合わせることで強力な効果を生む。記事がその方向に進むことを期待していたんだけど、ソフトウェアエンジニアが決める主観的な組み合わせが、本当にセンスの問題であって、単なる技術的なトレードオフの決定ではないことを議論できるのか。この記事自体がセンスの悪い例かもしれないと思う。いくつかの異なるトピックを行き来していて、各セクションは独立してうまく書かれているけど、全体としては記事が目指していた「見た目」をあまり伝えていない。(著者の今後の執筆を discouragement するつもりはないよ。テーマとしては素晴らしい選択だと思う。ただ、実行についての僕の意見を述べているだけ。)

「服は独立していると意味がない」という意見には賛成できないな。衣服は、組み合わせる前から文化的、歴史的、象徴的な重みを持ってるし、ファッションは単にアウトフィットを組み合わせることだけじゃないからね。ファッションにはトレードオフもたくさんあるし、制作だけじゃなくて、日常の着こなしやミックス&マッチにも関わってくるんだよ。

大多数のエンジニアや技術者はファッションセンスがあまり良くないから、一般的な良いセンスを理解するのが難しいんだよね。技術的なものの大半は普通の人にはクールじゃないし、オタクっぽいんだ。プログラミング言語もクールじゃない。だから、プログラミングでは「クールじゃない」からスタートして、スケールを下がっていく必要があるんだ。クールじゃない:Rust、C++、ほとんどの言語 痛々しくクールじゃない:関数型や変わったもの。Bash、Linuxなど。

ソフトウェアエンジニアが決めている主観的な組み合わせは、単なる技術的なトレードオフの問題じゃなくて、本当に好みの問題だと主張できるものは何だろう。技術的なトレードオフだと思っていることの中には、絶対に確認できないものや、トレードオフが非常に小さいから実際には重要じゃないと思うものもある。

りんごとオレンジを比べてるみたいだね。ファッションの良いセンスは、ソフトウェアエンジニアリングよりもずっと主観的だよ。明らかに、一方は主観的な分野で、もう一方は常に形式的な科学に結びつくから。面白いのは、ソフトウェアエンジニアリングが社会科学から始まることで、ほとんどの選択が無意識に、あるいは少なくとも他の人と話し合わずに行われるってことだね。

あなたが探求したい考え方は、美しさやエレガンスの認識にもっと関係してると思う。それは歴史上の哲学者たちのテーマで、単一の記事でカバーできるとは思えない。クリストファー・アレクサンダーは建築に関してこれを深く研究していて、彼のアイデアはソフトウェアアーキテクチャの多くの思想家に影響を与えた。アレクサンダーは客観的な美が存在することを主張している。OOPSLAカンファレンスでのアレクサンダーの基調講演は読む価値があるし、ロイ・フィールドリングの論文もそうだ。この記事に出てくる「価値」は、フィールドリングの論文では「アーキテクチャの特性」として整理されている。

つまり、未熟なエンジニアは自分の好みに対して柔軟性がないんだ。自分が好きなものは分かってるけど、その好みを原則的なエンジニアリングの立場と勘違いしてる。こういうのには遭遇したことがあるけど、経験豊富なエンジニアでもこういう未熟さに悩まされることがあると思う。昔、友達のコンピュータサイエンスの課題を手伝ってたことがあって、彼らのコードが気に入らなくて書き直したい衝動に駆られたことを覚えてる。実際に書き直し始めると、時間がかかりすぎて彼らには全然分からなくなるんじゃないかって思った。彼らの考えを否定してどうやって助けられるんだろう?もう一度考え直してみると、彼らはバカじゃないし、アプローチを少し調整すればうまくいくんじゃないかと思った。調整を手伝ったら、彼らは結果を理解できて喜んでくれた。その後、自分の問題への考え方が変わって、自分のコードも別の視点から見たことでずっと良くなった。実際、感謝すべきなのは自分の方だったんだ。今でもそうなんだけど、まだ偏見がある。でも心の奥ではそれを分かってて、冷静になったときには他の視点にちゃんとチャンスを与えて、本当に価値があると分かったときには嬉しく思うようにしてる。原則はちょっと主観的で、考えなしにそれに頼りすぎるのは怠惰だよね。状況やその価値をちゃんと考えてないってことだから。

この原則(ごめんね;)はすべての分野に当てはまるよね。もっと思い出せたらいいな。優しいリマインダー、ありがとう!

だからこそ、いろんなプログラミング言語を試すのが好きなんだ。次に理解しようとする言語は、知っている言語とはできるだけ違うものにしようとしてる。そうすることで、常に「ひらめき」があって、既存の考え方に挑戦できるから。それを他の言語にも適用できるしね。最初は「おかしい」とか「変だ」と感じることを受け入れないといけないよ。それがなぜそうなるのか、どうなるのかを理解するまでは。

すごくいいコメントだね。君の考え方は、僕が直接雇用する人たちや、プロジェクトに関わる人たちに対するアプローチと似てる。物事を達成する方法は色々あるって認識することが大事だよね。最終的な結果や目標が達成できれば、僕の具体的なやり方やプロセスに合わせる必要はないんだ。

「良いセンス」って、良いAPIや他の「良い」コードを経験することで養われると思う。良いコード(やAPI)を見たら分かるし、時間が経てば自分でも書けるようになるはず。ただ、新しい分野にいると、良いコーディングセンスを持つのは難しいよね。(でも、君が指摘するように、経験が必ずしもセンスを保証するわけじゃない。センスを求めて、認識して、反映させることが必要なんだ。)

確かに、経験豊富なエンジニアでもこういう未熟さに陥ることがあると思う。経験が必ずしも成熟につながるわけじゃないんだ。特に成功を収めたエンジニアは、自分のやり方が正しいと信じ込んでしまうことが多いから、経験を積むにつれて自分のやり方に固執することが一般的なんだよね。

私もCSの課題を手伝ったときに全く同じ経験をしたよ。その時は、彼らの既存のアプローチに合わせる知恵がなくて、もっと過激な書き直しに傾いてた。彼らがバカだと思ったわけじゃなくて、単に彼らのアプローチが好きじゃなかったんだ。理解しようとする時間も取らなかったしね。

ジュニアに対して、最適じゃないやり方をしているとは絶対に言わないよ。いつも、どうしてそのやり方を選んだのかを聞くようにしてる。会話の最後には、どちらかが何かを学んでる。時には私が別のアプローチを学ぶこともあるし、時には彼らがそのアプローチが長期的にはうまくいかない理由を学ぶこともある。どちらにしても、対立的な会話にはならないんだ。

成熟度は経験の時間と必ずしも相関しないし、感情的・社会的成熟も生物学的年齢とは必ずしも一致しない。私がこの論文のアイデアが頭に入ってきたのは、キャリアの12年目だった。

経験を積むことで、優れたプログラマーはソフトウェアエンジニアリングの主観的な部分と客観的な部分を認識し、区別することを学ぶと思う。そして、前者にはもっと緩やかでオープンなアプローチを、後者にはより厳格なアプローチを持つようになるんじゃないかな。

偏見やバイアス、固い考え方の解決策は、個人の世界観を超えた教育や経験だと思う。誰か他の人の視点を通して世界を理解しようとすることが、自分自身やプロとして成長する方法なんだよね。エンジニアとして、幅広い知識を持つ者として、別の角度や解決策が存在することを知るだけで、問題に対する見方が変わって、最初の直感よりも良い解決策が思いつくことがあるんだ。

あなたにとって「見た目が良い」コードってどんなの?「見た目が悪い」コードは?個人的には、これは単なる好みじゃなくて、正しさやパフォーマンス、メンテナンス性に基づいたパターン認識のスキルだと思う。 > どのデザインの決定に自信を持っていて、どれがまあまあだと思う?それは単なる感覚じゃなくて、理由から来てるよね。良いセンス=良いスキルってことだよね?誰かがオブジェクト指向よりも関数型言語を選ぶのは、センスがいいから?彼らは経験を通じて、不変性や合成にきれいにマッピングされる問題と、カプセル化や状態にマッピングされる問題を学んできたんだ。そのため、あるパラダイムに対する「センス」は、トレードオフやデバッグの痛点、長期的なメンテナンス性を認識するスキルの反映に過ぎない。センスに見えるものは、実際には専門知識が直感を形作っているだけなんだ。著者がチームの目標に合わないメンバーのセンスが悪いと感じる理由は分かるけど、実際にはこれだけなんだよね。彼らが経験から形成した意見が、あなたの意見と合わないだけなんだ。

この記事の「価値」は、ロイ・フィールドリングのソフトウェアアーキテクチャに関する博士論文に関連してる。フィールドリングの論文はRESTでよく知られてるけど、実際にはもっと広範で多様性があるんだ。彼は、あらゆるソフトウェアアーキテクチャについて考えたり理由付けしたりする方法を整理して、RESTを例として提示したんだ。この記事に出てくる「価値」は、アーキテクチャの特性(多様性、スケーラビリティ、可観測性、可読性、メンテナンス性など)に関連してるけど、アーキテクチャの制約を理解することがもっと重要だと思う。なぜなら、それがアンチパターンの場所やアーキテクチャがどう進化するか(または進化しないか)を教えてくれるから。 https://ics.uci.edu/~fielding/pubs/dissertation/top.htm

私は技術的なセンスは好奇心の一形態だと思ってる。異なるパラダイムを探求し、自分の技術のために質の高いソフトウェアを求めることで成長するんだ。多くの人が給料のためだけにプログラミングをするけど、それじゃあ良いセンスが必要とする執着が欠けてる。人のセンスは、彼らがフィードで共有するコンテンツからよく分かるよね。

面白い記事だね。特に印象に残ったのはこれだな:「良いセンスをどうやって育てるか?難しいけど、いろんなことに取り組んで、どのプロジェクト(またはそのプロジェクトのどの部分)が簡単で、どれが難しいかに注意を払うことをおすすめするよ。柔軟性を重視して、ソフトウェアの書き方について強い普遍的な意見を持たないようにしよう。」

主観的なことを客観的なことのように話すのが、悪いセンスの証なんじゃないかな。