目次
今回は社内の成果発表会「P-Review ’19」にて発表した、エンジニア H.Fさんの資料を紹介します。
※この記事は個人の研究発表で、会社としての見解ではございません。
こちらに載せられているプログラムは、すべて資料のために作成されたものであり、実際のプログラムとは異なります。
H.Fさん
2018年7月アピゲー部エンジニアとして入社。
入社後は主に自社開発ゲームのゲームエンジニアを担当。
早速ですが皆様にお聞きしたいことがあります。この2人は誰でしょう?
「すずきさん」と「たなかさん」かな……?
正解は……
右側にいる鈴木という表記の人は「テリー大隅さん」。田中Tシャツを着ている人の名前は「牛山牛子」さんという名前だそうです。
!?!?
意味わからないですよね……?
それでは、「以心伝心」発表を始めたいと思います!
以心伝心とは
• いしん-でんしん【以⼼伝⼼】
ー⽂字や⾔葉を使わなくても、お互いの⼼と⼼で通じ合うこと。
▽もとは禅宗の語で、⾔葉や⽂字で表されない仏法の神髄を、師
から弟⼦の⼼に伝えることを意味した。「⼼こころを以もって⼼
こころに伝つたう」と訓読する。(参考:google辞書)
まず以心伝心とは、文字や言葉を使わなくても……などと意味は色々と書いてありますが、つまりお互いがわかりあっている状態のことだと自分は解釈しています。
目的
コーディングでの機能拡張や改良や諸々の対応をしている時に、そのコードが自分が対応したものとは限りません。書いてあるコードが読みやすいと、実装が早くなって作業効率が上がったり、その日は途中で終わっちゃった場合であっても、次の日すぐに把握しやすくなります!
こういう経験ありませんか?
そもそも、コードを読む際に一瞬でも思考が止まるようなコードは好まれないと思います。
では、一瞬でも思考が止まるようなコードとはなんなのか。
エンジニアの方、こういう経験はありませんか?
①名前と内容が一致しない
メソッドや変数の名前が一致しない。
例えば、「A」のコードだったとして、メソッド名はなぜか「B」だったとか……謎ですよね。
②全てが繋がっている
コードの流れがすべて繋がっている状態。
改行とかがなく、コードの処理がすべて繋がっていて読みにくい状態ですね。
③処理に行くまでが長い
次に、ネストが深すぎて処理に行くまでが長いという状態。
④肯定された後に否定をされる
次にif文の条件とかで肯定されている文の後に、否定をされている状態が連続されているという状態です。
コードを読むのが嫌になってきます……。
なので、今すぐできる相手への伝え方についてのポイントをまとめてみました。
● 名前
名前の命名をちゃんとすることにより、処理の把握自体がすぐにできると思います。
● 美しさ
先ほど言った処理の流れが繋がっている状態ですと、どこに何の処理があるのかわからなかったり、一度思考が止まった時にどこから見直せばいいのかいまいちわからなくなってしまうことがあります。
● ネストの深度
処理に行くまでが長い状態、if文がたくさん並んでいる状態ですと、見直す時に最初から見直さないとちゃんとした見直しにならないというところですね。
● 肯定文と否定文の混在
今すぐにでも相手に伝えられるような効率になるかと思います。
それでは、ひとつずつ説明していきたいと思います。
名前
• な‐まえ【名前】
• ① ある⼈や事物を他の⼈や事物と区別して表すために付けた呼び⽅。名。
• ② ⽒名。またその名字を除いた部分。「ここに−を書いて下さい」
( 参考:⼤辞林第三版)
僕が検索した中だと、2種類の意味がありました。
今回に適する意味は「①ある⼈や事物を他の⼈や事物と区別して表すために付けた呼び⽅。名。」です。
つまり伝わらない名前は、名前としての役割を果たしていないということになります。
なので最初に、名前に必要な情報を詰めます。
アバウトすぎるので、少し分解して説明していきます。
明確な単語を選択
まず明確な単語を選択します。
広義的には間違っていないけれども細部を表せていない単語を選択することを、今回問題に取り上げています。
改善点としては、広義に間違っていない単語の解釈を一つ掘ることで、明確にできるのではないかと思います。
例えば「stop」という名前を付けている場合、取り消しが不可能な処理であれば「kill」をつけたり、取り消しや「stop」を解除できるようなものであれば「pause」にするとかですね。
抽象的ではなく具体的な単語を選択する
2つ目、抽象的ではなく具体的な単語を選択する。
名前に属性の情報を付け⾜すと、「何をしたいのか」などを瞬時に明確に理解できるようになります。
こちらに関しては、日にちが経った後でも変数名を見るだけで、どんな値が格納されているのかをすぐに確認ができるようになると思います。例えば「delay」っていう変数があったとしてその「delay」に入っているのは何か↓
• delay -> delay_msec, delay_min
• size -> size_mb
• limit -> max_kbps, min_num
このように置いてみましょう!
誤解が⽣まれない単語を選択
3つ目、最善な単語というのは誤解が⽣まれない単語のことです。
逆に⾔えば、誤解が⽣まれない単語は最善な単語になる。
例えば、 エンジニアですと名前の頭に「is」や「has」を付けると、「bool」を返すメソッドだったり変数だと思います。なので、「bool」の値を返すようなメソッドじゃないのに、「is」や「has」を付けると誤解が生まれるということです。
省略から始まるミステリー
4つ目、できる限り省略をしない。
ポピュラーな単語のポピュラーな省略の仕⽅であれば問題ないと思いますが、これがプロジェクト単位での固有名詞や、あまりポピュラーではない単語の省略になると、急に翻訳も利かなければ検索しても出てこないようなミレニアム懸賞問題レベルの難問になってしまいます。なので基本は省略をしないのをオススメします。
でも、エディターの横幅の関係上で省略をしたい場合は、コメントなどでメモを残しておいた⽅がいいでしょう。
否定の副詞が⼊ると頭は⼀旦停⽌する
5つ目、否定をしないこと。こちらは英語の⽂法にすると分かり易いと思います。
a.「 This is the pen I used」
b.「 This is the pen I didnʼt used」
a.とは違って、b.⽂では「didnʼt 」の部分で、一瞬だけ処理を把握するためのプロセスに「”usedを否定して~” 」というプロセスが追加されませんでしたか?
⼀単語が増えることによって考えることが増えて、そこで⼀瞬思考が⽌まることが多くなるのであまりオススメしません。
名前が⻑過ぎると読む気が失せる
6つ目、名前の長さです。名前が長すぎると、とても読む気が失せます。
一番最初にある変数の宣言は、この長さが続くと、この後の変数を使う部分のように、とてもとても読みにくくなると思います。
おまけ~メソッドの命名について~
名前の命名について、先ほど6つくらいのポイントを上げました。処理の内容を具体的に表せていると良いと提⽰しましたが、メソッドの命名が処理の内容を具体的に表せていると、名前と処理の⽐較をしたときに逸脱した処理を⾏っていた場合は、そのメソッドは機能を持ち過ぎという⼀つの判断にもなると思います。
美しさ
コーディングによる美しさとは、見た目の問題としてコードが整理整頓されていること、コードの縦線が揃えられていること、エディターの横幅を越えないようにされていることがあげられます。
こちらのモデルを例にして説明していきたいと思います。
コードを整理整頓する
先ほど全部羅列されていたコードを処理ごとに分けてみました。この4つを分けることによって、どの処理がどこで何をしているのかわかりやすくなっていると思います。
コードの縦線を揃える
コードの縦線を揃えられてることによって、変数だったりメソッドがどこでどんな値を入れているのかが見やすくなると思います。
エディターの横幅を越えない
先ほど見せたコードですが、エディターの横幅を超えたことにより、改行されている部分があります。
こちらの部分をメソッドの引数に合わせて改行するのと一緒に、引数の縦線を合わせるのを加えることによって、こちらのメソッドの処理が何を引数にして何を返しているのかが分かりやすくできたと思います。
ついでに、個⼈的な趣向も追加
最初の羅列されているコードのをさっきのポイントを含めて、なおかつ個人的な趣向を含めて直しますと……
コメントを足しただけなのですが、これをすることによってどういう処理なのかをレイヤーで把握するのが早くなります。
ネストの深度
始めに、ネストについて説明していきます。
ネスト【nest 】⼊れ⼦/ ネスティング/ nesting
ネストとは、あるものの中に、それと同じ形や種類の(⼀回り
⼩さい)ものが⼊っている状態や構造のこと。ITの分野では、
コンピュータプログラムやデータ構造において、ある構造の内部に同じ構造が含まれている状態のことを指す。
ひとつのスコープの中に、また処理が入っている状態のことです。
ネストの深さは闇の深さ
条件が複数になったことによって、これが続いていきますとどんどん深くなっていきます。ネストの深さは闇の深さとも言われているほどです。
これもそうですが、コードから不吉な匂いがしてきます……。
こちらのコードの問題点は、ネストの深さによりメンテナンス性が落ちていること。というのも、条件が複数になることによって、一つ処理を戻ってこれがどうだったのかを把握するときに、またその条件に対して思考をしなくてはいけなくなるので、把握の時間が伸びることでメンテナンス性が落ちてしまうんです。
そして、何よりも読みたくなくなる。こちらの改善⽅法は2つあります。
①例外処理はreturnする( ガード節)
「return」をすることによって1つネストを浅くしております。
ここでは「next」にしているんですけども、実際やっていることは「return」とほぼ一緒なので同じです。
②メソッド化して、処理を細分化する
同じような処理がたくさんあったりするとメソッド化をしますが、ネストの深い部分を一つ一つ分解してメソッド化をするというのも一つの対処だと思っております。
おまけ
• 現状ボス判定のないエネミーの、「kind」が1で「attack_pattern」が1のものだけのユニークな処理になっている。
• ここから何かを拡張しようと思うとif⽂の分岐を⽣やしたりとどんどん汚くなるのが⽬に⾒えているため、個⼈的には
– ボス⽤の「update」メソッド
– 親メソッドにも少し⼿を加えて、「kind」と「attack_pattern」の種別とそれに合わせて係数が変更されるようなメソッドを作成しておくと、プランナーのマスター操作だけでコード側の変更がなしでできるようになるから良いです。
肯定⽂と否定⽂
if文のところ見ていただきますと、最初の「master.i==1」の部分が肯定文です。
次に「!」がついているところが否定文になります。
また次の肯定文がきて、否定文となっています。
このように否定と肯定文が混在することによって思考のプロセスが止まることになると思います。
問題点
● 肯定⽂と否定⽂を混在させると、知りたい処理にたどり着くまでが遠くなり思考が止まる要因になったり、誤認をさせる可能性が⾼くなります。
• if文の条件式に肯定⽂と否定⽂を混在させてネストを深くされると、読む側は戻った時に同じところをまた考えなくてはいけなくなるので脳内メモリをガリガリ消費されていくような気がします。
改善⽅法
これらの改善方法については先ほど説明しました「例外処理は早い段階でreturnする。(ガード節) 」「メソッド化をして処理を細分化する。」に加えて、「⾔語によっては勝⼿に⽤意してくれてたりする。」ということもあるのでそちらについて説明していきます。
Ruby の場合
Rubyの場合ですと、「nil?メソッド」だったり、「empty?メソッド」というものがあります。
先ほど言った「true」を返すメソッドです。
Ruby on Rails の場合
「blank?メソッド」、「present?メソッド」の2つがあります!
C# の場合
調べたところ、「null合体演算子」というものがあるそうです。
例文を書きましたが、「hoge ?? ”Null”」「hoge 」が「null」 なら、「”Null”」 が返されるものだったりとか、「HasValue」というメソッドがあったりするそうです。
まとめ
• 名前
⼀⽬で⼊ってる値や処理が推測できる命名をする。
• 美しさ
処理毎に⼀⾏空けたり縦線を揃えたりして、綺麗に魅せる努⼒をする。
• ネストの深度
例外処理は早い段階でreturnして弾いたり、メソッド化をする。
• 肯定⽂と否定⽂の混在
肯定⽂と否定⽂の混在は混乱の元。
できるだけ否定形は使わないようにして、混在しそうになったら⼯夫する。
こちらのポイントを押さえることより、他のエンジニアが見てもわかりやすいコードが書けるようになると思います!
最後に
この4つの中で今すぐにでも変えられることは「名前」だと思います。
皆さんも以心伝心のようにすぐに伝わる命名を意識して、一緒に効率化を目指しましょう!
名前って大事ですよね~!アイコもほかの人が見ることも考えて、ファイル名などを気を付けることから始めてみようと思います!