TL;DR
わかりにくいコードをこの世から無くしたい気持ちになった私が、「わかりやすい名前付け」を悶々と考えた末にたどり着いた3つのコツを紹介する記事です。
- 「もう一人の自分」にコードを読み返してもらう
- うまく名前を付けられない時は、リファクタする
- 冗長さとシンプルさのバランスを見極める
僕「わかりやすいコードが書きたい」
日々私たちはコードを書きます。
そのコードは、 「わかりやすいコード」 ですか?
それとも、 「わかりにくいコード」 ですか?
個私は 「わかりやすいものが好き」 です。
だから、私は 「わかりやすいコードを書きたい」 と思っています。
ただ、 「わかりやすいコードが何か」ということはよくわかっていませんでした 。
「『わかりやすい』ってなんだ?」と考えて一晩寝れなかった時もありました(嘘
いくらかソースコードを書いてレビューしてもらったり、他の人のコードをレビューをする中で、
「わかりやすいコードに共通する何か」があることに気付きました。
それは、 良い名前付けが徹底されている ことです。
プログラムを書く上で、 変数名、関数名、クラス名、パッケージ名などの コードを構成する要素に名前を付ける機会がたくさんあります 。
「わかりやすいコードだなぁ」と思うコードに共通するのは、 そのような構成要素の役割をうまく表現できている名前が付けられている ということでした。
「何を当たり前なことを」という気持ちになってしまうかもしれないですが、
私は この名前付けこそが「わかりやすいコードを書くための核心」と思うようになりました 。
もちろん、このような名前付けが重要であるという記事はよく見ますし、多くの本で同様のことが述べられています。
ただ、 自分の中で「名前付け」に対する考え方というかマインドセット(?、言ってみたいだけ)が出来上がってきた気がするので、
このタイミングでアウトプットしてみようと思います 。
この記事について
この記事は、「わかりやすい」ってなんだろう、みたいなところを軽く考察してから、
実際に「わかりやすいコードを書くための名前付けのコツ」を3つ紹介するという形です。
気軽な気持ちで読んでもらえるとありがたいです。
対象読者
- わかりやすいコードを書きたいけど、書き方がわからない人
- 他の人が書いた複雑なコードに悩まされている人
この記事を読む上の注意点
この記事に書かれていることは、あくまで私の経験と勘に基づくところが大きいです。
このやり方がしっくりこない人もいるかもしれません。
もし、 「こんな考え方もあるよ!」「これはさすがに違うんじゃない?」といった意見があれば、コメントなり Twitter なりでお伝えしていただけると嬉しいです 。
それでは、まずは「わかりやすい」ってなんだろう、という考察からです。
そもそも「わかりやすい名前」ってなんやねん!
プログラムを書く人であれば、変数名や関数名といった名前を自分で定義する必要があります。
この世には、 「わかりやすい名前」 「わかりにくい名前」 などが存在しているわけですが、 これらの違いとはなんでしょうか?
文脈で「わかりやすさ」は変わる!
一概に「○○という変数名がわかりやすい!」と結論することはできません。
なぜなら、**「わかりやすいかどうかは文脈によるから」**です。
例えば、技術系ニュースサイトを作る時に、とある記事を表す Article
というクラス名をつけたとします。
最初の段階では、ずいぶんとわかりやすい名前に思えますね。
色々人気も出てきて、美容系の記事も出したいとなり、 BeautyArticle
が追加されました。
(どんなサイトやねん、となりますがそこはおいといて
この段階で、技術系記事は Article
、美容系記事は BeautyArticle
となります。
うーん、今となっては、技術系記事は TechArticle
とかのが良さそうですよね。
最初の技術系記事だけの段階では、 Article
は良い名前だったのに、
美容系記事が入って Article
は曖昧な名前になってしまいました。
つまり、名前の良し悪しは、その時の状況や文脈に大きく依存するのです。
文脈によって良し悪しが決まるということは、絶対的に優れた名前などはないことがわかります。
最初から最善を求めず、段々と良くする
この「絶対的に優れた名前など存在しない」という事実こそが、まさに名前付けが難しい本質的な理由です。
「じゃあ、どうすりゃわかりやすい名前を付けれんねん・・・」
と頭を抱えてしまうわけですが、こういう時の考え方として、
最初から最善を求めるのではなく、段々と良くしていけば良い
というものがあると思っています。
例えば、最初の段階で Article
と名前付けしたのはしょうがないけれど、
他の美容系記事などが入ってきそうなら早めに TechArticle
に変えた方が良いかもしれません。
これは開発の中のほんの小さな出来事です。
ただ、このように名前付けというのは一筋縄でできるわけではない、ということを伝えるための例でした。
ここからは、実際に自分なりに考えて実用的だと思うコツを紹介していきます。
- 「もう一人の自分」にコードを読み返してもらう
- うまく名前を付けられない時は、リファクタする
- 冗長さとシンプルさのバランスを見極める
コツ1. 「もう一人の自分」にコードを読み返してもらう
一発で完璧なコードは書けない!
プロダクトをチームで作っているならば、自分が書いたコードを他の人や未来の自分が読む機会はいつか訪れます。
書かれたコードを一目で理解できれば、時間も節約できるし、嬉しいですね。
と言っても、最初から読みやすいコードを書こうとするのは難しいです。
これは、こういった記事などの長い文章を書くときにもありがちです。
書いてるときはノリノリなのに、読み返してみると「長すぎ」とか「読みにくい」と感じることがあります。
一発で完璧な文章を書ける天才でない限り、文章の推敲は欠かせない作業です。
コードを書く時にも同じようなことが言えて、一発目に書いたコードが完璧である人はなかなかいないはずです。
読み返してみて、「あれっ、この変数ってなんだっけ」などとなれば、それは十分にわかりやすいとは言えない可能性があります。
「初めてコードを読む自分」になりきる
わかりやすくするコツとしては、ある程度コードを書いたあと、頭の中に「もう一人の自分」を用意して読み返してもらいます。
もちろん書いた本人であればコードの構成がわかっているので意味がないと思われるかもしれません。
しかし、ここはあえて**「初めてコードを読んだ自分」としての立場で読み直してみます**。
すると、 「初見だと、ここがわからないな」とか「コードの順番を入れ替えると読みやすいそう」とか色々な発見が得られます 。
他の人によるコードレビューでも同じことができそうと思うかもしれませんが、案外そうではないと感じています。
私感ですが、バグや間違いを指摘するレビューはしやすい一方、「ちょっとした読みにくさ」は指摘し辛さがあるため、レビュー時にスルーされがちです。
だからこそ、自分の視点で、思う存分レビューしてあげる姿勢があると良さそうですね。
もちろん、とりあえず動くコードを早く書きたい欲求は自然です。
「おし、開発すっぞ!」とノリに乗っているときは、細かい変数名や関数名は適当にしてしまいそうになります。
この欲求を抑えながら、「推敲」に時間をかけてみると、長い目で見ると大きな時間の節約になるかもですね。
重要なのは、「他の人のため」「未来の自分のため」に少し時間を割いて手直してあげる優しげな気持ちという気がします。
コツ2. うまく名前を付けられない時は、リファクタする
名前付けができない時は危険視号
良い変数名や関数名が付けられない時は、危険信号です。
コードそのものに問題がある可能性があります。
プログラムを書くときは、英語を使うことが多いと思います。
英語にはよく使われる単語が数千個ありますが、それらを二、三個組み合わせれば途方もない表現が可能です。
しっくり来る名前が付けられない場合は、複雑な概念をそのまま扱おうとしている可能性があります。
複雑な概念に無理やり名前を付けてしまうと、読んだ人が誤解する可能性が高まります。
exec
とか run
辺りの名前が多く出てくる時は曖昧な関数の切り方になってるかもしれないです。
名前付けしやすい粒度まで分解する
このような場合は、関数やクラスを分割するリファクタをして、名前付けしやすい単位まで分解するのが良いです。
関数名は、言わば、記事の目次や見出しのようなもの です。
記事の概要だけを読もうとする時は、目次を読んだり見出しだけ見てざっと内容を把握することありますよね。
コードでもそれは同じです。
ざっとコードを読んだときに、 関数名だけを読んでコード全体の流れを把握できれば読者の負担が小さくなります 。
ただ、大雑把な流れを意識しすぎて、関数の切り方が雑になる場合は注意です。
いくつかの処理をまとめてしまっているところは分割して、関数を分解するリファクタが必要となるかもしれません。
コツ3. 冗長さとシンプルさのバランスを見極める
誰でもわかるように詳しく名前付けるべきか、できるだけシンプルな名前にすべきか、どちらなんでしょうか?
これについても必ずこうだ!という解答は存在しないと思います。
あくまで、「他の人が初めてコードを読んだときにわかりやすいと感じるかどうか」を基準とすべき だと考えています。
言葉で説明するのが難しいので、私がどのように「わかりやすいコード」を目指しているかを書いてみます。
冗長な例
UserRepository
というインターフェイスに、ユーザIDを指定してユーザの名前を更新するメソッドを追加してみます。
このコードを読んでどう感じますか?(Goです)
// UserID はユーザの固有IDを表す文字列の型です。
type UserID string
// UserRepository は、 `User` モデルのDBへの書き込みや読み込みなどを抽象化したインターフェイスです。
type UserRepository interface {
// UpdateUserNameByUserID は、与えられたユーザIDを持つユーザの名前を更新するメソッドです。
UpdateUserNameByUserID(userID UserID, newName string) error
}
実践:わかりやすい名前にする
それでは、 UpdateUserNameByUserID
という名前付けの良し悪しについて考えてみます。
詳しい名前で一見良さそうですが、 実は冗長な命名です 。
まず、引数の変数名である userID
について見てみます。この変数の型は UserID
です。
読む人の立場に立つと、 UserID
型の何らかの変数ということは簡単にわかります。
しかし、この場合は、どんなユーザIDかを特に制限するわけではないので 「 UserID
型の何かしらの値がある」ことがわかれば十分なわけです 。
UserRepository
の中のメソッドなので、 userID
ではなく id
と書けば、読む人にも十分伝わります。
つまり、 userID -> id
にします。
また、 UpdateUserNameByUserID
の ByUserID
は引数を見れば明らかなので必要なさそうです。
ということで、 UpdateUserNameByUserID -> UpdateUserName
にします。
さらに言うと、 UpdateUserName
の User
は本当に必要でしょうか?
読んでいる人はこのメソッドが UserRepository
にあるとわかっているわけです。
UpdateName
で十分でしょう。
newName
のところは人によりそうですが、 名前更新のメソッドの引数に名前が渡されれば、それが「新しい名前」を表すのは明らかだと考えても良さそうです。
つまり、 newName -> name
にしてしまいます 。
書き直してみると、次のようになります。
// UserID はユーザの固有IDを表す文字列の型です。
type UserID string
// UserRepository は、 `User` モデルのDBへの書き込みや読み込みなどを抽象化したインターフェイスです。
type UserRepository interface {
// UpdateName は、与えられたユーザIDを持つユーザの名前を更新するメソッドです。
UpdateName(id UserID, name string) error
}
関数名で頑張りすぎて全てを説明すると、コードも必要以上に長くなりますし、可読性が落ちていきます。
この例のように、 引数や戻り値の型名、インターフェイス名など総合的に見て読者が理解するのに必要十分な情報を書くようにすると、とてもすっきり表現できます。
なんか張り切って図なんか作っちゃいました。
名前が短すぎると、理解するために多くの前提知識を必要とするためわかりやすさが減ってしまいます 。
一方、名前が長すぎる場合は、上の例でもわかるように、余分な情報が多く、コードが増えて読む側の負担が増えてしまいます。
ですので、この中間にある 長すぎず、でも短すぎないバランスの良い長さの名前を付けることが重要となります。
まとめ
なんやかんや結構長くなってしまいましたがいかがでしたでしょうか?
まず、「わかりやすいコードってなんだろう」という考察から始め、次のような名前付けのコツを3個紹介してみました。
- 「もう一人の自分」にコードを読み返してもらう
- うまく名前を付けられない時は、リファクタする
- 冗長さとシンプルさのバランスを見極める
本当は、リファクタの手順なんかも紹介したかったのですが、明らかに記事の量が膨大になりそうだったので、また今度にします。
最近、「良い名前が付けられた段階でプログラムは大半が終わっている」みたいな哲学を持っていて、他の人はどうなんだろうと思って記事を書いてみることにしました。
「こんな別の考え方もあるよ」といった意見は大歓迎なので、コメントとかしてもらえるととても嬉しがります。
ついでに、 Twitter(@zawawahoge)のフォローしてもらえると特に泣いて喜びます。
参考資料
記事を書く上で参考にした資料を載せておきます。ありがとう
-
読みやすいコードを書くために(@shimataro999)
詳細に書かれている良記事でした。それに比べると自分の記事は具体例が少なくて情けなくなりましたw -
レガシーコード改善ガイド
自分のリファクタ好きのきっかけとなったレベルの良著。めっちゃオススメ。
Special Thanks
私の何気ないツイートに反応してくださって、この記事を書くきっかけとなった @ucan-lab さん、ありがとうございました!
https://twitter.com/zawawahoge/status/1322510183751278594