Kengo's blog

Technical articles about original projects, JVM, Static Analysis and TypeScript.

How I find and learn new technical things

Sometimes my teammates ask me about how to find and learn new technologies. It would be common question for technologist and developers, so I will try to summarise current my theories.

How to find new technologies

RSS (articles)

RSS is still my best method to collect information from WWW. I have already tried AI based curation like Gunosy and SmartNews, but they summarise information from only limited sites. To collect information from everywhere, RSS is the best way for now.

I use feedly pro to summarise information and check it everyday morning. Its free version is also good and enough, please try.

Here I will list several sites from my subscriptions:

e-book

RSS is good to find new things, but it might not enough to learn new things because each article is small and not well organised. Best solution is the book, it is designed for my usage; It is well packaged so I can find all related information and background.

So when I want to learn some specific topic like BLE, ROS, Arduino or Scala, I visit following sites to purchase e-book.

GitBook and similar sites have potential to be good place to find book, but in many cases, books are not edited.

SNS

I do not use SNS so much for now, because now my network environment is not good. But following sites are good, they have many information what I do not know.

Mailing list

Many OSS projects have mailing list. When you get interested in OSS, I recommend you to find mailing list and join it.

And there are also mailing list which introduce new information continuously.

Meetup

Meetup is good place to meet with new information. You may want to check:

Pocket

Pocket might be the most important tool to collect information. It helps me to postpone reading when I have no time to with with care.

How to make time to learn

Even though you have method, it does not work without time to use. So most important thing is that making time to learn continuously.

Basically I have good concentration at morning, so I make time to learn at morning. If you are also, then please try to make habit and environment to read articles at train, bus, desk or somewhere.

Googleのアサーション用ライブラリTruthを試してみた

Guavaのテストコードを読んでいたらTruthというtesting frameworkが使われていることに気づき、最新の個人プロジェクトで使ってみました。まだアルファ版ですし、自分でも使い続けるかどうか微妙なところですが、試用記録として利点をまとめます。

なお著者がアサーションフレームワークに求めるのは、大人数が関わるプロジェクトにおける「開発者の個性(経験、知識、趣味)に限らず、短時間で保守性が高く直感的なコード・エラーメッセージが書ける」ことです。異なる観点からこのプロダクトを見ると、また違った意見があるかと思います。

assertThat()が必要とされた理由

そもそもassertThat()はなぜ必要なのでしょうか。それはassertTrue(), assertFalse() などのメソッドが生むエラーメッセージが直感的でないからです。

Truthのウェブサイトにのっている例が非常にわかりやすいです。直感的なメッセージにするには、結局文字列で状況を説明する必要があります。この方法は開発者の個性に依存してしまいますし、忙しい時などに文字列を書き漏れる恐れもあります。

List <Entity> entityList = service.search(condition);
assertTrue(entityList.isEmpty());
// -> AssertionError

assertTrue("No entity should be found under this condition", entityList.isEmpty());
// -> AssertionError: No entity should be found under this condition

JUnit4はこの問題に対してassertThat()という解決を用意しています。これによって、比較的可読性の高いメッセージを得ることができます。

List <Entity> entityList = service.search(condition);
assertThat(entityList, is(empty()));
// -> AssertionError: Expected: is an empty collection  but: <[unexpected entity]>

assertThat()には確認する値と、期待する状態を表すMatcherとを渡します。Matcherには様々なものが用意されており、ほぼすべての用途をカバーできると考えられます。

なおassertThat()を利用したコードには「英語として読んで意味が通じる」という利点もありますが、Truthでもそこは変わらないためここでは割愛します。

既存手法の持つ問題

ではなぜ代替が必要なのか。私は状況・目的に応じたMatcherを開発者が知らなければならないことが大きな問題と考えます。

例えばCoreMatchersMatchersだけでも、以下の記事で紹介されている通り様々なMatcherがあります。この他にJUnitMatchers(JUnit4.4以降)もあります。これらを知らないと、assertThat(age < 30, is(true)) のようなエラーメッセージ生成に役立たないMatcherの使い方をしてしまいかねません。

他にもassertThat()で生成されたエラーメッセージには「どの値が」問題であったか(上記の例で言うと「entityListが」問題だった)という情報が含まれておらず、結局テストコードを読まなければどんな処理がどのような理由で失敗したのかがわかりません*1IDE単体テストをガンガン回すテスト駆動開発であれば問題になりませんが、テストが落ちた時の対応はコスト高です。

Truthがもたらす解決

Truthはこの問題に対して、メソッドチェーンとnamed()を導入することで解決を図っています。

Truthは期待する状態を表すコード(前述のMatcherに相当)を、引数でなくメソッドチェーンにて記述します。 メソッドチェーンにより、assertThat(...)を書いた時点で、利用可能なメソッドIDEにより一覧表示されます。開発者はすべてのMatcherとその用途を記憶する必要がありません。必要なもののみが、必要なタイミングで、表示されます。

assertThat(someInt).isEqualTo(5);
assertThat(someCollection).contains("a");
assertThat(aMap).containsKey("foo")

また「何が」期待通りでなかったかを補足するためにnamed()メソッドを提供します

// Reports: "hasError()" is unexpectedly false
assertThat(myBooleanResult).named("hasError()").isTrue();

メッセージそのものを指定するwithFailureMessage()も用意されていますが、個人的にはこちらは使わないで良いのではと思います*2

他にもMultimapのようなGuavaが提供するCollectionフレームワークにデフォルトで対応していたり、自分で新しい型に対応させられたりCollectionの要素に対するAssertionを書けたりと、細かいところで気が利いています。

Truthの問題点

以上、良い所も多いプロダクトですが、最近はさほど活発に更新されてはいないようです。アルファ版と言え枯れつつあるからなのか、まだユーザが少ないのかは不明ですが、Mavenリポジトリの情報を見るとまだ利用数が少ないため後者ではないかという印象です。

またアサーションフレームワークには他にも有名なものがいくつかありますが、それらとの違いに関する公式ドキュメントは現時点ではありません。ドキュメント以外では一応、Issueのコメントに拡張性に違いがあると述べられています。Truthが”very alpha”だという点が気になるようであれば、AssertJが良い選択肢になるかもしれません。

以上、なかなか魅力的なプロダクトだと思いますがいかがでしょうか。

*1:1テストメソッド1アサーションを貫けるなら、あるいは……

*2:そもそも私の関心は「技術者の個性に左右されないテストメッセージの生成」にあるので

Is OKR included in MBO?

I've read How Google Works.
And now I'm interested in OKR (Objective and Key Results), which is explained in this book. It is really similar to MBO (Management By Objective). I'm learning MBO for five years, and I feel that OKR might give me good hints to understand MBO.

In my understanding, OKR is one of the method to execute MBO. In other words, MBO is theory and OKR is operation. Here I will explain my opinion:

MBO explains its aim and why MBO itself can be solution, based on psychology and experience. It lets player to be professional, excited and motivated. But there are many abstract things in its definition (e.g. ), so MBO player need experience to improve how to execute. MBO is a theory and framework, we need to improve our system and operation step-by-step.

OKR provides many concrete definitions and operations (how key results should be, how to score, what is ideal result etc.), so it's easy to adapt to real business. It is also easy to scale, so it suits for big companies. But I feel that it focuses on operation too much, and it is easy to forget about why we should do so easily.

Reference

How Google Works

How Google Works

How to track state of operand stack by FindBugs 3.0.1

Yesterday I released findbugs-slf4j v1.2.0, which supports more useful analysis based on OpcodeStackDetector.

Here I will summarize my problem and solution.

What is TOP?

Problem is that my detector could not track state of OpcodeStack, because stack becomes TOP. I cannot get elements in stack. if stack is TOP.

What TOP means? It comes from the lattice. You may refer following papers for detail:

In context of my plugin, it means that findbugs plugin cannot decide state of Item when it joins separated operation flows (e.g. after for-loop, after if-block and in catch-block). So I cannot get Item from OpcodeStack.

How to define join operation for FindBugs?

Check merge(Item, Item) method in OpcodeStack.

But if you use userValue in Item, it should be hard to join Item because this merge method just compares two userValue and set it to merged Item only when two Items are equal.

What can be solution?

In my case, I stopped using userValue. There are some alternative solutions:

  • specialKind defined in Item might be good way to mark Item
    • It has different and complex logic to merge two Items
  • Use methods in Item class, if FindBugs already track and hold its state
    • In my case, Item#getJavaClass() replaced userValue

昨今のメソッドの命名方法事情まとめ

一時期はメソッド名は動詞で始まらなければならないと言われていましたが、昨今ではJava標準APIでも動詞ではないメソッド名が散見されます。本エントリではその傾向をまとめます。

of, from(from, of, valueOf, fromString, fromNullable etc.)

fromofはEffective Javaでも触れられているように、ファクトリメソッドとして利用されることが多いようです。例えばJAX-RSでは valueOf(), fromString() といった名前のファクトリメソッドを利用します

to, as(toList, asList, toArray etc.)

主に自分自身を別の形に変換するインスタンスを返すメソッドに使います。

またJava8のCollectorsにあるような、変換・生成を担うインスタンスを生成するメソッドにも使います。こちらはプログラムを英文として読めるようにするための命名ですね(stream.collect(toList()) など)。流れるようなインタフェースを採用する際にどうぞ。

接続詞(and, or, andThen, orElse etc.)

Andやorは2つ以上のインスタンスを結合して新しいインスタンスを生成する際に利用します。古いところではHamcrestでも使われています。

Java8では関数合成(lambda同士の結合)やOptional周りでも利用されています。

if(ifPresent, xxxIfYyy)

条件に適合する場合のみ何らかの処理を実行する際に利用します。lambdaが登場したJava8から一般的になった命名と言えるでしょう。

形容詞(boxed, reversed, empty)

自分自身の状態を特定の条件に従って変化させたものを返します。またファクトリメソッドとしても使われています。

同じJava8のAPIでもPredicate.negateは動詞を使った命名になっていて、ちょっと統一感がありません。

名詞(min, max, range, iterator

主に自分自身とは他のインスタンスを返すメソッドに使われます。ファクトリメソッドとしても使われています。

本来であればfind, create, generate, ofといった単語がメソッド名に含まれているべきですが、利用頻度が高いメソッドなので省略している……という印象です。ループカウンタにiという意味のない命名をしても支障がないのと同じでしょうか。自作クラスで使うときは、慎重になったほうが良さそうです。

be動詞(isEmpty, isPresent)

boolean型フィールドのgetter、あるいは状態を表すメソッドに使われています。

その他の動詞

ごく一般的な命名です。

なお三人称単数のSをつけるかどうかは、わりとどうでもよいようです。例えばJava標準クラスでも、Sなしの命名(e.g. Set.add)とSありの命名(Set.contains)が1クラス内で混在していたりします。Sなしの命名のほうが多いので、基本的にはそちらに合わせるとよいでしょう。

JavaのStreamで末尾再帰

JavaのStreamで末尾再帰するというアイデアが今読んでるFunctional Programming in Javaで紹介されていた。

動かしてみたら、確かにStacktraceが浅いままで階乗の計算ができている。 タネはStream.iterate()で、このメソッド再帰の代わりに必要なメソッドの計算を行ってくれている。試していないがStream.generate()でも同じことができるのではないだろうか。

あまり直感的ではないが、実用的なテクニックではありそう。覚えておこう。

追記

マイクロベンチの結果、やはり素直な書き方よりは遅いようだ。アルゴリズム単体における1割のパフォーマンス劣化は、個人的には大きいように思う。