良いコードとは良い感じのコードである

こんにちは、imazです。10年ちょっとRailsエンジニアをしています。
インフラは苦手、CSSやJavaScriptも得意ではない、アーキテクチャとか設計も得意ではない…
SQLとかデバッグが好きです。答えがあることが好き!
作業中めちゃくちゃ独り言が出るのでオフィスで働けないタイプです。

Re: 良いコードってどんなコードですか?という質問を受けたら何と答えるか

snoozer05.hatenablog.jp

今日はしまださんの記事を読んで、私ならどう答えるかなぁ、自分の場合はこうだなぁ、と思ったことを書いておきます。

良いコードを書くために

私がコードを書くときに心がけているのは「コードがなぜそうあるのか説明できるようにすること」です。 コードの一行一行に対して、どういう選択肢があってなぜそのコードを選んだのかというのが理解できているのが良い状態だと思っています。

簡単な例

たとえば、コード中のリテラル(即値)について考えてみます。 私がリテラルを書こうとしたとき、ざっくり3種類の選択肢が思い浮かびます。

思い浮かぶ選択肢をあげる

  1. リテラルのまま書く
  2. 定数にする
  3. コメントをいれる

それぞれのメリット・デメリットを考え、どういうケースに適しているかを考える

  1. リテラルのまま書く
    • メリット
      • コードを読んで、またはデバッグしていて値がすぐわかる
    • デメリット
      • 複数箇所ある場合に変更に手間がかかったり漏れたりしやすい
    • 使うケース
      • 同じ意味の数値が現状存在せず、増える可能性も低い
      • 上記かつ以下のいずれかの場合
        • メソッド名や周りの文脈でその数値が何を表すかがわかる
        • その数値である理由が特にない(CSSの局所的な調整など)
  2. 定数にする
    • メリット
      • 複数箇所にまたがっても変更が容易
      • 適切な名前だとどういう意味の値なのかがすぐわかる
    • デメリット
      • コードを読んだときに値がパッと見でわからない
    • 使うケース
      • 同じ意味の値が複数ある・増えることが想定される場合
        • この場合デメリットは飲み込んだほうが良いことが多い
  3. コメントをいれる
    • メリット
      • コードを見たらそこだけですべてがすぐわかる!値も意味も!
    • デメリット
      • テストにかからないため、修正漏れを機械的に検出できない
      • "動くコードとして意味を持たない" ので誰かの気まぐれなどで急に消える場合があるぞ(びっくり)
    • 使うケース
      • コメントがメンテできるチームの場合
      • 局所的だが値が意味を持ち、周りのコードから意味が読み取れない場合
      • コードを読んで数値がすぐにわかったほうが良い場合
      • あと定数にするほどじゃないなーめんどくさいなーってとき…
        • いいの?他の可能性を考えて判断した結果ならいいです!コードでもトレードオフは発生するのだ…!! ※1

※1 トレードオフについて書いてたら長くなっちゃったので一番下の項目にしました!

最終決定する

ここまで出した上で、今使うならどれなのかを考えます。 リテラル程度であれば手癖で書くことも多いのですが、手癖の思考過程が確立していくまでには上記のような思考を何度も行っているはずです。

この例は主観的でミクロな例ですが、仕事をする上ではサービスの段階(立ち上がったばかりなのか、大きくしているところなのか)、チームの形態(分野専門の人がいるか、入れ替わりが激しいか)、アーキテクチャなどの設計や現状のコードに照らし合わせて、最適な選択肢を選んでいくことになるかと思います。

コードの説明ができるようになる方法

本を読んだりコードを書いたりと知識を身につける方法は色々ありますが、私自身はコードレビューを通して覚えたことが多いように思います。(勉強より先に現場に入ったからかも…) コードレビューをしてもらうときは自分が抜けがちな、あるいは自分が持たない視点からの指摘がもらえるのでダイレクトに知識が増えてそれも良いのですが、説明力がつくのはコードレビューをするときです。

レビューをしはじめた頃、私は雰囲気で「良い感じのコード」を書いていたので、レビューで指摘するときも「なんとなく嫌だな」という感覚しか持っておらず、最初の頃はそれをそのままレビューコメントとして残していました。しかしチームメンバーから別の「なんとなく嫌」な意見がでると平行線になってしまい、結論が出なくて放置状態になることがしばしば。これはよくないなと思い考えを改めました。

他の人に何かを変えてもらうのならそれ相応の根拠や理由が必要! ということで、コメントをするより先に現状のコードのメリット・デメリット、別の案を採択したときのメリット・デメリットも考え、説明できると思ったときにだけ指摘をするようになりました。そうすると面白いことに、多くの「良い感じ」「嫌な感じ」には明確に理由があることに気づきます。
理由を言語化して認識できれば、たとえ環境が変わっても、環境にあわせて最適な選択をする手がかりとなります。「良い感じ」の再現性が得られるということです。

「良い感じ」…これはまさに「良いコード」への道といえるのではないでしょうか。
良い感じを突き詰めた先には良いコードがある!
それはそう…そうなりますよね。主観としての良さね。

このコード好きだな〜と思ったら(またはヤだな〜と思ったら)それがなぜなのかを考えて言語化する、というのを繰り返すことが「良い感じ」をみつける訓練になるのだと思います。 その機会が多いのがコードレビューなのかも。

結論:良いコードとは!

良いコードを書くには「コードがなぜそうあるのか説明できるようにする」。

では良いコードとは?

私の出した結論は「最善の選択肢を選んだコード」です!

良い感じはどこいったの!? あれは主観としての良さを表現していて最高なのですが、主観として・客観としての良さを両方表せるのはこちらかな〜と思って選びました。選択は常にトレードオフなのだ… ※1

「1年後にいいコードが書ける、上手に書ける」というのは、コードを書くときの選択肢が見えるようになること、その選択肢から最善を選びとるための知識が増えるということなのかなと考えています。 最善を選んだと言えるためには明確な理由が必要である、それができていると証明できるのが「説明できること」なのではないかなと思います。

この考え方の良いところは、チームの制約があっても達成できるところです。自分がベストだと思う選択肢がとれない場合でも、「本当はどうありたいのか」「なぜいまこうあるのか(どうして理想の形をとれないのか)」を説明することはできる。ベストのコードを捨てて何かを選んでいるはずなんですよね。短いスパンの中の時間とか。

良いコードが書ける人はみんなこれができるなぁと思います。一緒に仕事してると頼りになるし、めちゃくちゃかっこいいんですよねえ。

そうありたいものだな……

オススメ本の紹介

※1 トレードオフ

トレードオフというのは「何かを得るとき何かを失う」という、どちらかしか選べない関係のことです。
先のリテラルの例で、「1. リテラルのまま書く」と「2. 定数にする」のメリット・デメリットにはまさにその特徴が現れていますね。どちらも得ることはできないのだ…

私は『ソフトウェアアーキテクチャの基礎』の翻訳原稿レビューに参加させていただいたのですが、その本でトレードオフのことをはっきりと知り、初めて開発に関わる様々なトレードオフのことを考えました。本の中の大好きフレーズはこちら

アーキテクトが、トレードオフではない何かを見出したと考えているなら、まだトレードオフを特定していないだけの可能性が高い。

慧眼〜!この師匠が弟子に言う感じのフレーズ、めっちゃ好き…!!

アーキテクチャ決定をするときの考え方として覚えていましたが、原稿レビューの過程でコードのトレードオフについてしまださんから教えていただいていました。

『ソフトウェアアーキテクチャの基礎』第8章を読んだ私の感想
アーキテクト は、1 つの真の設計を見つけることに執着してはならない。 * ここまで何度も言われているこの点を読むたびに、向き不向きがありそうだなと思う…正解がほしい…! 真(実)はいつもひとつであってほしいよぉ!
しまださんの返信
残念ながら正解はないのじゃ...プログラミングも一緒、というのは研鑽Rubyという書籍に書かれていました(あっちはコードのトレードオフの話がたくさん出てくる)

この頃から答えを求めていて笑ってしまう… 正解は、ないのだ…( ˃̣̣̣̣̣̣ ω ˂̣̣̣̣̣̣ )

トレードオフ関連リンク