Kengo's blog

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

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割のパフォーマンス劣化は、個人的には大きいように思う。

CI用語を使わないJenkins入門

Jenkinsの使い方と狙いについて話す機会があるので、自分の考えをまとめる。 時間節約と内容簡素化のため、CIとJenkinsとを分けて説明するのではなく、開発者なら共感できるであろう表現によってJenkinsとCIの双方を説明することを目指す。なお「品質」の定義について、ここでは明確には定めない。

アジェンダ

  • Jenkinsはいろんなことを自動化するサービス
    • 人間に「人にしかできないこと」へ注力させるため、機械の執事を雇って自動化する。
  • 自動化の恩恵は「省力化」と「コミュニケーション促進」
    • 省力化: 人間に「役割」へ注力させるため、Jenkinsは各種「役割」の補佐を行う。コンパイルやテスト、情報収集や統計などルーチン作業を通じて人間が思考し判断することを助ける。ゴールは「人が行うルーチン作業」と「作業完了待ちによる暇」をゼロにすること。
    • コミュニケーション促進: 「役割」間の連携を促すため、ハブとしてコミュニケーションを促進する。組織内での作業重複を排し、各「役割」に必要な情報を必要な形で提供する。ゴールはコミュニケーションによって価値を想像すること、そのサイクルを早めること。

省力化

  • 「ルーチン処理を」「何度も」「同じように」「速やかに」やることには、高い価値がある。
    • 品質を保つには、頻繁に現状を確認する(可視化する)のが近道。
    • 1日に1回確認するのと週に1回確認するのでは、問題発見の早さも対応工数も大きく変わってくる。
    • 理想は変更があるごとに確認すること。Gitを使っているなら、Pushがあるたびに確認すること。
    • これを人にやらせるのは効率が悪いだけでなく、「人にしかできないこと」の邪魔になるので、省力化が必要になる。
  • Jenkinsは機械なので、こうしたルーチン処理の実行に向いている。
    • 機械なので疲れないし教育コストが安い。指示したとおり、同じ作業を何度も間違いなく行ってくれる。
      • 人は増やすと情報を伝え教育する必要があるが、Jenkinsならサーバを追加すればそのまま性能増になる。
      • クラウドが普通になった今、サーバを追加するのは非常に簡単で安い。
      • 変化が多く資産が積み上がる現場では、そうした手法で能力増強できるのは魅力。
  • 「人にしかできないこと」とは「判断」と「成長」と「休息」
    • 判断
      • 実装。バグ修正。品質の管理。スケジュール。開発効率の見直し。開発環境や開発手法の改善。
      • 思考や判断のための材料作りは、Jenkinsでできる。コンパイル、テスト実行、静的解析、カバレッジ測定など。
      • いつ何のためにどのような判断をするのかを人間が考え、あらかじめ判断材料を機械に蓄えさせておく。
      • バグが出たら失敗する自動テストも、バグを「発見」するための判断材料と言える。人間が実装し、機械が実行する。
    • 成長
      • 成長には問題を細分化すること、仮説をたてること、検証をすること、実行すること、振り返りをすることが必要。
      • 検証と振り返りの材料を蓄積するため、「ルーチン処理を」「何度も」「同じように」「速やかに」行う。
      • 「実行」の手段としても執事は非常に有能。人に指示するよりも簡単かつ確実、チームを超えた影響も容易。
    • 休息
      • 帰って寝る
      • 時間と心に余裕がないと、新しい挑戦を始められない。
  • 人間が「判断」し「対応」するために、機械に課題と問題を「確認」「発見」「通知」させる。
    • コンパイル単体テスト、インテグレーションテスト、静的解析といった「確認」「発見」を日々行う。
    • 問題発生時にメールやIRCなどで、役割を担う人間に「通知」する。
    • 通知によって、行動サイクルの開始を早める。リリース前に気づくことで対応コストを抑え、「休息」の時間を作る。

コミュニケーション促進

  • チーム間コミュニケーションの目的=チーム開発の欠点をなくすため
    • なぜチームが必要か
      • 作るものの複雑さと開発速度を両立させるため
      • やるべきことを明確化し、役割として分担させる
    • チームの欠点とはなにか
      • 「知らないこと」が出てくる=担当外の技術・機能・業務を知らないための悪影響
      • 全体としての知識獲得スピードは向上しているはずなので、これは至極当然に発生する
      • 欠点というより、利点を得るために生じる歪みのようなもの、リスク
  • 欠点を補うために必要な物はなにか=獲得した知識の伝播と、コミュニケーションによる現状把握
    • 獲得した知識の啓蒙・汎用化(「巨人の肩」の形成)
      • 他者に対して報告・共有と言った形で知識を伝播させる
      • 知らなくても問題ないように、汎用的なインタフェースで包んでしまう
        • ビジネスニーズを知らない人でも機能破損に気づけるように、自動テストを書く
        • 技術的バックグラウンドを知らない人でも使えるように、モジュールとして提供する
        • チェックリストをいちいち確認しないでもいいように、ビルドツールに自動チェックをさせる
      • Jenkinsはそういった諸々をサポートできる!
        • 情報を満載したサイトの提供
        • 自動テストの実施
        • モジュール間依存関係の管理、依存先変更によるビルドの実施
        • ビルドツールの実行による自動チェック、ならびにチェック結果の管理・表示
    • コミュニケーションによる現状把握
      • 役割の明確化により、問い合わせコストを下げる
      • 今何をやっているかを伝え、他チームから作業を引き受け重複排除する
      • 自分が管理しているルールやチェックリストを、他チームが守っているか確認する
        • Jenkinsは現状の把握と他チーム連携のトリガーになれる。

How to upgrade Jenkins plugin to support latest LTS (1.596)

Today I've updated my Jenkins plugin, to support latest LTS version.

This article will explain what we should do to support latest LTS Jenkins.

Write dependencies on other plugins explicitly

Previously some core features were bundled in Jenkins core, but now they are independent plugins. If you need features of them, you should write dependencies in pom.xml.

  <dependencies>
    <dependency>
      <groupId>org.jenkins-ci.plugins</groupId>
      <artifactId>junit</artifactId>
      <version>1.3</version>
    </dependency>
    <dependency>
      <groupId>org.jenkins-ci.plugins</groupId>
      <artifactId>mailer</artifactId>
      <version>1.10</version>
    </dependency>

See also: Dependencies among plugins - Jenkins - Jenkins Wiki

Replace deprecated API

API which is annotated with @Deprecated should be replaced with recommended API. Check Javadoc and implementation of deprecated method, then you can find how you should replace.

In my case, I had to replace following API:

About how to use JenkinsRule, please see Unit Test - Jenkins - Jenkins Wiki.

Add <repositories> and <pluginRepositories> to pom.xml

To pass build on buildhive, we need to add both of them to pom.xml.

Gitbook v2.0.0で日本語書籍を書くときの落とし穴と回避策

Gitbookの多言語対応はまだ弱く、日本語で書籍を書く際はいくつか対応が必要です。 しかし文字化け等はないため、Markdownに慣れている人であれば充分に活用できる製品になっていると思います。

文中の意図せぬ空白

文中の改行が空白に変換されてしまうため、段落をすべて1行で書ききる必要があります。

下記プラグインで対応可能のようですが、利用時に警告が表示されます。折り返し表示可能なエディタを利用したほうが良いかもしれません。

github.com

GLOSSARY

用語集は半角空白で区切る言語のために設計されています。つまり半角空白で区切られた単位を「単語」として認識し、自動的にリンクを追加するような仕組みになっています。

このため、日本語のような単語間に空白が入らない言語の場合は、分かち書きをしないと使えません。 例えば「りんご」という言葉を用語集に追加する場合、本文には

りんごの木があり、りんごの実が3つなっていました。

ではなく、以下のように半角空白(あるいは改行)で単語を挟んで記述しなければなりません。単語が句読点の後に来る場合も、半角空白(または改行)が必要です。

# 半角空白で「りんご」を挟む
りんご の木があり、 りんご の実が3つなっていました。
# 改行でも良い
りんご の木があり、
りんご の実が3つなっていました。