IntelliJ IDEAのSequenceDiagramプラグインが便利
この、SequenceDiagramプラグインで、
vanco.github.io
こんな感じのシーケンス図が描けます。
素敵なのが、
- 好きなメソッドから始められる
- 深さが選べる
点です。
コードレビュー時などに、深さ2でServiceクラスから始めると、私の好きな感じのコードになっているかどうかがよくわかります。
参考:持論:Application Layerがシンプルなコードは読みやすい - エンジニア的なネタを毎週書くブログ
以前は、こういったコードから自動生成された図は、ノイズが多くて使い物にならない…と思っていました。
けれども最近は、
「自動生成された図が汚い、ということはそもそもコードが悪いのでは?」
と思うようになってきました。
例えばこれ。
右から左に呼び出しが伸びてるのが気持ち悪いです。
以前の私であれば、「この呼ばれているクラスを右に持っていければいいのに… ツールがイケていない!」と思っていたところでしたが、
そもそもこんな向きに呼び出しがかかる、元のコードが悪いのではないでしょうか。
こういう考え方になってきたのは、12月のJJUG CCでirofさんの「JIGを使った設計」を聞いたからなのかなぁ… と思います。
【極論ですけど】JavaでforEachを使ったら負けだと思う
正直使い所がわからないんですよね、forEach.
ログとかprintfとかする以外は…
コレクションを更新するな
未だに時々見るのがこういうコード。
List<X> list = new ArrayList<>(); 適当なコレクション.forEach() .map(t -> list.add(t.getXXXX()));
これとっても良くない。
スレッドセーフでない
上記をあまり深く考えずにパラレルストリームにしちゃいますと
List<X> list = new ArrayList<>(); 適当なコレクション.forEach().parallelStream() .map(x -> list.add(x.getXXXX()));
ArrayListに対する追加処理がスレッドセーフでないため、確率的に不具合が起きてしまいます。*1
パラレルにしなければいい…のですが、Project Lambdaの目的の一つがマルチコアへの対応なわけで、「parallelStreamを使って並列化できないものはラムダ式で書くな」くらいに私は思っています。(私の勝手ルールではありますが)
Lambdaで更新するの「関数」でない
Lambda式内では外で定義した変数に代入ができません。
これは、「状態」を極力排除することによって、バグの入り込む余地を減らすため… と私は認識しています。
ですが、上記のようにコレクションに対する操作や、Setterでの代入はJavaの言語仕様上できてしまいます。
…とはいえ、できるからやっていい、というものでもないと思います。
「リストを作る」と明確に書く方法がある
List<X> list = 適当なコレクション.stream() //parallelも可
.map(X::getXXXX)
.collect(Collector.toList());
そもそもこのように、リストを作るための書き方が用意されているのに、これを使わずに汎用的なforEachでなんとかする… というのは美しさに欠けます。
更新しないとなると、forEachは出力くらいしか使いみちがないのでは
上で書いたとおり、コンパイルエラーにはならない… とはいえ、Lambda式内で何かを「更新」するのは不適切と考えます。
そうなると、冒頭に書いたとおり、何かの出力くらいしか使いみちがないなぁ… ということになり、
よっぽどのことがない限り、「forEachを使ったら負け」だと思うのです。
*1:私が経験したことのある事象だと、「適当なコレクション」よりも多い要素がlistに追加されるという謎現象が発生し、その要素をgetするとnullが入ってる → ヌルポで落ちる というものを何度かみました。
"Rename Hackathon"をしてみました
チーム内で、お祭り的なイベントとして、"Rename Hackathon"というイベントをチーム内でしてみました。
ルール
結果
- 参加者 : 6人(因みに…4名は日本オフィス。2名はインドオフィス。リネームタイムはリモートで同時に。)
- 30分間に出された総プルリクエスト数 : 32
- ルール違反 : 2件(複数箇所修正、パッケージを1回層削除)
- 重複したため投票で却下 : 2件
- コードレビューで却下 : 8件(まだ一部レビュー中なので増えるかも)
- ということで残ったプルリクエスト数 : 12 ~ 20
- 修正の例
- クラス
- 不要(しかも意味不明)な接頭辞や接尾辞の削除
- 省略されすぎていて分かりにくい名前を展開
- メソッド
- booleanを返すcheckXXXX メソッドを isXXXXX メソッドに
- 変数
- i などの無意味な名前を 意味のある名前に
- クラス
所感
楽しかった
お祭りみたいで楽しかったです。ある程度ゲーム性のあるルール*2をしっかり作ったので、数を競うのも楽しんでくれた感がありました。
コードがきれいになった
これはもちろん。本来なら最初のコーディング時に埋め込まれるべきでない名前もちらほらありましたが、どうしてもできてしまうのは避けられないもの。
また、開発者のドメインナレッジが増すことによってより良い名前を後から思いつくこともあります。
そういった、普段のもやもやを片付けられた良い機会でした。
初級者の学びに
32件中8件はコードレビューで却下ということで、たかだかRenameなんですが、意外と他の人の了承を得られていないんですね。*3
「良い名付けとはなにか」の学びができた、良い機会になったと思います。
「解決策から考える病」に名前をつけたい
…って、タイトルで名前つけちゃってますが。
どうしても人間、「なんとなく思いついたソリューション」に飛びついちゃうんですよね。
寝坊しまくってるから目覚まし時計を買わなきゃ…! ってなりがち。
その前に、そもそもなぜ寝坊しているか? について考えないといけない。*1
※上の画像は以前に書いたこちらの資料より。もともとKPTのやり方を説明した資料ですが、根本的な考え方は共通だと思います。
自分がこの考え方ができるのは… 弊社の入社前課題でもらったこの本のおかげっぽいです。
他にも色んな経験が元になっているのだとは思いますが、「なんで自分、こういう考え方をするようになったんだっけ?」と思案したときに、思い出すのはこの本です。
*1:実際のチームだと…「そもそも寝坊は悪いことなのか? 悪いとしたらなぜ?」まで一旦掘り下げたいところです
JavaのHashMapは無限ループを引き起こす
知らんかった。理由がぼんやりはイメージ湧くけどしっくり来てないので後でちゃんと調べ…たい。(だいたいやらないパターン…)
d.hatena.ne.jp
www.atmarkit.co.jp
wadahiro.hatenablog.com
回避方法はいろいろあるみたいだけど、ConcurrentHashMapをつかってスレッドセーフにするのが楽なのかな?
web.plus-idea.net
価値観ババ抜き大体験会!に参加してきました #devlove
悩めるオジサンの私が、自分を見つけるためにぴったりそうな価値観ババ抜き体験会に参加してきました。
https://devlove.doorkeeper.jp/events/85438
価値観ババ抜きって何?? というのを書こうと思ったのですが 冗長になる&講師じゃない自分が変に説明して誤解が広がっても嫌だな
ということで、上記のイベント告知 及び、コチラの公式サイトのリンクをご参照ください。
http://myvaluecard.com/
いきなり考えさせられる名札書き
何この「どこから来た」って!
ストレートに社名を書こうとも思ったんですが、あぁ、なんかあるんだろうなこれ と 邪推し、こんな感じに。
「『シングルプレーヤーとマネジメントの間』から来ました」って… 今見返すとすごく恥ずかしい。
でもこの手の、自分と対話するゲームするときはこのくらい、のっけから自分を晒していかないとですよね!
ちなみに、この名札は、開始前の雑談以降は全く使いませんでした(笑)
ババ抜きの結果
さて、最終的に5枚のカードが手元に残るのですが… 私の結果はこちら!!
いやいやいやいや 「美」ってなんだよ、「美」って。よりによって俺が「美」って。
って思うんですが。
このカード、偶然にも最初の5枚に入ってまして、
「なんだこれ? すぐ捨てよう」
と思ったものの、
「でも、バグのないシステム、きちんと『切られ』た、読みやすいコードって、まさに『美』だよなぁ」
と思ったら
「これはこれで 大切かぁ…」
と思い
気づけば最後まで残ってしまいました。
また、ゲーム中は各カードはあまり繋がりがなく、バラバラに5枚残った… と感じていたのですが、
よくよく見ていると…
なんとなーく 隣のカード同士の関連のようなものが見えてきました。
まさかの、最後の1枚、「メイン」になったのは…
更にここから追加のワーク。残った5枚の中から1枚のメインと2枚のサブを選ぶことに。
「そら、この中からメインを選ぶんだったら『楽しさ』よ」
と思ったんですが、どうしてもしっくりこない。
どうしてもどうしても気持ちがそっちに行かず…
最終的に私が選んだのは… これ。
「『美』しいシステムを作るには『知識』が必要であり、それを学ぶモチベーションとして支えるのが『楽しさ』」
という、「美」を頂点にしたピラミッドができてしまいました。
えええ…
これだと俺の中で一番大事なことが「美しい」ことになってしまうんですけど……
とはいえ、恥ずかしさとか、どう思われるかとか、そういうのを捨てて、自分に問いかけたときに、
もう一回やったらどうなるんだろう
今回は偶然にもはじめの手札に「美」があったのでこのような結果になってしまったのですが、もし「美」がずっと他の人に持たれていたり、あるいはずっと場にあったとしたら*1、全く違う結果になったのでしょうか。
その場合自分は何をメインに置いたのか…
時期をおいてまたやってみたいものです。
実際、平日の夜にやるのか休日にやるのかでも結果が変わるとのこと。
脳内がお仕事モードなのかプライベートモードなのか、あるいは、仕事モードの中でも何に時間や脳みそを取られているのか といった状況によってかなり結果が変わりそうですね。
最後にお手紙タイム
最後は、一緒にババ抜きをした他の3名に向けて、お手紙を書いて渡す というちょっと恥ずかしいけど嬉しい時間でした。
*1:カードを取られるたびに自分で場から一枚好きなものを選ぶことができるのですが… 自分から「美」は取らないような気がします。それとも今回みたいに、たまたま目があってしまった後に同じ思考になって結局取るんだろうか…
あらゆる「システム」の挙動は入力と出力だけで説明できる
どんな粒度、どんな用途の「システム」も、挙動は入力と出力だけで説明できます。
プログラムのサブルーチン(function, method, ...)
「引数」と「返り値」で挙動が説明できます。
public String greet (String name){ return "Hello " + name + "!"; }
でも、データ更新したりするでしょ? 入力と出力だけじゃ説明できないじゃない!
このようにシステムを見ると、「状態が更新される」ことも挙動の説明としてする必要があります。
ですが、ここだけをシステムとして見ると… DBへの更新は「出力」の一種と見ることができます。
このシステムは、APIのクライアントと、DB という2種類の外部システムに、出力をするシステムです。
プログラムのサブルーチンの場合も同様です。
class Person { String name; public setName(String name) { this.name = name; } }
このコードは、このようにも捉えられますが
nameはPersonから依存があるだけの別インスタンスなので、このようにも捉えられます。
逆にDBからデータを読むようなシステムは、「入力が2つある」と捉えることができます。