どんな人向けか
新人の頃は、周囲の人や年次の近い先輩のやり方をまねて、段々とコードが書けるようになるというのが、よくありますね。その次の段階として、自分なりのやり方だったり、もっと良いやり方がないかと、視野を広げてみたいプログラマー向けです。でも、新人だったりビギナーの人の方が知っておくと得かもしれません。
追記
関連するワードとして、ベストプラクティスドリフトと、そのブログ。
https://zenn.dev/hodagi/articles/52d80908745f18
新人の方へ
期待と不安を抱えている新人プログラマーの方に、ネガティブな内容をすすめるのもどうかとも思ったのですが、良いことを知るためには、何が悪いのかも知るのも重要と思い、追記してみました。
最初は周囲の人を真似るので精一杯かもしれませんが、どこかのタイミングで振り返って、もっと良いやり方はないのか、一般的なやり方かどうかというのは、時折意識すると良いと思います。
いきなり、がっつり調べて上位互換のやり方を迂闊に提案すると、人間関係に軋轢がでかねないです。その辺はいい意味で大人になりましょう。
悪いやり方ほど簡単に真似できてしまう、真似されてしまう
プログラミングに限らないですが、バッドノウハウの多くは、初心者でも簡単にできてしまうために、悪いやり方ほど、真似されてあっという間に根付いてしまうようです。知らず知らずにバッドノウハウの地雷を踏んでしまうからこそ、初心者といえるかもしれませんが。
また、一緒にコードを書いているときに、自分の悪い癖ほど後輩に移ってしまうという経験をされた方も多いのではないでしょうか。
これらを防ぐには、
- 教える側は自分の悪い癖と向き合う
- 教わる側は良いやり方かどうかを、真似た後でもいいから調べてみる
という風に、お互いがもっと良いやり方がないか、これはバッドノウハウになっていないかのアンテナを張る必要があるでしょう。
自分の悪い癖を真似されてしまったら、「自分もついついやってしまうが、これはアカンやつや。お互い気をつけよな」と、相手のやり方が良くないと気づいたら、「これはアカンやつやないでしょうか」と、お互いに素直に言って受け入れられるかが大事です。
仕事をより円滑に進めるために、必要な行為だと自然に受けとめられる文化だとよいです。
具体例
昔は自分もよくやらかしていて、その頃のコードを見ると恥ずかしくて穴に入りたい気分ですが、そういったのも含めて、これまで出会ったものをあげていきます。
1. ドキュメンテーションコメントを書かない
javaやrdoc、jsdocなどを全然書かないということです。
一回リリースしたらおしまいとか、そのシステムが終わるまで自分がずっと面倒をみることが確定しているなど、他にそのコードを読む人がほぼいない場合でもない限りは、全く書かないのはまずいです。
すくなくとも、クラスに対してどういう役割をするか程度は書いた方が、設計に問題ないかを気づくきっかけにもなり、読みやすくも書きやすくもなるはずです。書くようになると、ライブラリのdocコメントも読めるようになって、うまく使えるようになってきまし、そこから良い書き方の例を知ることになって好循環です。
そうでないと、クラスの役割が過剰に増えたり、使い方がよくわからないメソッドが、じわじわ増えてきます。docコメントの書き方がわからず、読み方がわからず、必要な情報が手に入りにくくなってすぐに頭打ちになります。
2. 使わなくなったコードを放置している or コメントアウトして残している
仕様変更など、急な変更にすぐ対応できるようにだったり、切り戻ししやすくするために残したのかもしれませんが、大体は無駄に終わります。
gitやsubversionで管理してあれば、それらで戻せます。ある程度時間がたってから必要になった場合は、未来の自分なら、残したときよりも上位互換となる良いコードが書ける(そうなっていないと成長が止まっていてもっとヤバい..)ので、忘れてしまってもさして問題はないです。
コメントアウトで残されていると、読むときにかなりノイズになるし、そのまま残されている場合も、使われているかどうかをIDEで調べる手間がでてきて、後からメンテする人の負担になってしまいます。
javaの@Deprecated
に相当するものがあるなら、最低でもそれをつけましょう。
余談ですが、JDK9からは@Deprecated
が色々細かく指定できるようになるかもらしいです。
http://d.hatena.ne.jp/bitter_fox/20151211/1449809933
3. 変更履歴をコメント
いつ、だれが編集したかをコメントで残したり、変更前の内容をコメントに残したりですね。
下記の記事にあるとおり、バージョン管理システムがあれば不要ですし、そこのコミットコメントでやることです。
4. 言語仕様とは違う独自ルールでコメント
javadocが正しく生成されないようなルール(慣習?)でドキュメンテーションコメント(っぽい)ものを書いてしまうことです。
例えば、javadocは最初のピリオドの箇所まで、サマリとして表示されるのですが、ピリオドを使わずに日本語の句読点や改行タグだけで書いてしまったりです。ひどいときは改行タグがなかったりします。
/*
* このメソッドはhogehogeします。
* こんなときにつかってください。
*/
public void hoge() {
}
まともなjavadocを生成しなくよいプロジェクトだけをやり続ける、一種の閉じた環境ならそれでもいいかもしれません。それで回っているならあえて変えることもないかもしれませんが、正しいドキュメンテーションコメントの書き方はおさえていないと、思わぬところで自分の評価が下がるかもしれません。
5. メソッドが使われている場所をgrepで探す
これは言語によると思いますが、javaであれば、eclipseでもIntelliJでも、呼び出し先を列挙する機能があります。これを使った方が楽だし、それぞれのところにジャンプもできます。webアプリのフレームワークで、ビューテンプレートでの呼び出しを拾ってくれないので、そういうときにgrepをつかえばよいでしょう。
6. メソッドのリネームをgrepの結果を置換でやる
これも言語によると思いますが、IDEの機能でやった方が安全です。eclipseやIntelliJならリファクタリングという、そのまんまのネーミングの機能で用意されています。
grepでやるにしても、一件ずつ確認しながらならまだよいですが、盲目的にやるとだいたい余計なものも置換するのがおちです。
7. コミットコメントを書かない
gitでもsubversionでも関係なく、たとえ自分一人でしか開発していないときでも、チーム開発を想定して最低限のコミットコメントはつけた方がいいです。なんらかの事情で、作業を他の人に引き渡したり、分担するとき、後から見る人はコミットコメントをまず見ます。これがすっからんだと、悲しみと絶望の感情に包まれるので、やめた方がいいです。
昨日の自分は他人と思って書いた方が、自分で後からみたときも迷うことが減ります。その意味でもコミットコメントは、明日以降の自分に、今の自分の考えを明確に伝えるためのものにしましょう。
8. PRをつくらずに、作業ブランチをマージ
これはGitHubの使い方ですね。変更を加えるためのブランチを作るとこまではいいのですが、なぜかPRをつくらずに、レビューしてもらったらそれをmasterブランチとかにマージするというフローです。
滅多に変更が入らないレポジトリにしても、レビューしやすさ、変更履歴のおいやすさを考えても、PRをつくった方がいいですし、昨今の流行にもかなっているはずです。
9. 言語のバージョンが古いときの書き方をする
プロジェクトにはよっては、どうしても古いバージョンでやるしかないときもありますが、そうでもないなら、古いバージョンのときのやり方をするのは好ましくないです。
例えば、javaは7からならtry-with-resource文があるので、BufferedReaderなどをfinally句でcloseするやり方はしなくよいです。
10. 言語のバージョンが古いときのAPIを使う
例えば、Java8がリリースされてからそれなりにたつのに、Calendar APIを使ったサンプルコードを見かけます。プロジェクト内でコードを統一するためとか、バージョンが上げられないなどがない限りは、新しいものを使いましょう。
古いバージョンであっても、joda-time を極力導入しましょう。java1.5から使えるデファクトスタンダードです。Java8以降のバージョンアップを考慮すると、joda-timeの使い方を慣れておいた方がよさそうです。
古いバージョンのときのやり方のほうが、ググったときに見つかりやすく、それをコピペしてつかってしまがちです。昔はそんなことをやってしまい、あとから見直してとても後悔しました... この時代に10年以上前みたいなコードを書いてしまったのかと。
ググったものを参考にすること自体はOKですが、記事の内容が古くて現状に沿っているかどうかも踏み込んでおきましょう。
11. パッケージ分けをあまりしない
パッケージの切り分けをしないで、ひとつのパッケージに何十個もクラスをおいてしまうことです。そういうライブラリもありますが、IDEでも見づらくなるのと、修正対象を見つけるのが大変になります。特に後から入ってくる人にとっては、パッケージ単位で大筋をまず掴もうとするので、全体像が掴みにくくなります。
大体は違った役割のものも混ざってくるので、どこかの段階でパッケージを新たにきって整理をした方が、設計的にもよいはずです。オブジェクト指向に沿った設計なり、DDDなり、そのときにあった形に寄せていくと、クラスの役割も明確になって、肥大化したり、影響範囲が広がるの防げるはずです。
全体の設計に踏み込まないと、どんなパラダイムの言語を使っても、結局は手続き的なことばかり書くことになりがちです。
12. 劣化版の車輪の再発明をする or フレームワークが持っているライブラリを使わない
ライブラリを探したり、使い方を見つけられないことに起因するのですが、そういったものをつかえば、安全かつ簡単にできることを、自前でつくってしまうことです。
例えば、設定ファイル内での下記のような値の代入をする機能です。PlayFrameworkなどを使っているなら、typesafeのconfigなどをつかえば、この機能はあるのですが、それらを使わずにプロパティファイルを読み込んで、自前でそれっぽい仕組みを用意してしまったり... そもそも再発明といえるレベルではないかも。
dataDir=/var/lib
log=${dataDir}/log
メール送信も、commons-emailをフレームワークが含んでいるのに、javamailを直で使ったり、joda-timeをつかわずに、DateやCalendarで日付計算をしたり...
まとめ
結構長くなってしまった。ほんとに恥ずかしいことをやってきたものです。
こうした記事を書いても、同じような悲劇はどこかで繰り返されてしまうかもしれません。ケースによってはバッドというほどでないこともあるでしょうが、いずれは明確な上位互換がでてくるのもこの業界の常です。定期的な見直しは必要ですね。
参考サイト