Quantcast
Channel: Kengo's blog
Viewing all 157 articles
Browse latest View live

CI用語を使わないJenkins入門

$
0
0

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

アジェンダ

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

省力化

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

コミュニケーション促進

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

JavaのStreamで末尾再帰

$
0
0

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

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

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

追記

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

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

$
0
0

一時期はメソッド名は動詞で始まらなければならないと言われていましたが、昨今では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なしの命名のほうが多いので、基本的にはそちらに合わせるとよいでしょう。

How to track state of operand stack by FindBugs 3.0.1

$
0
0

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

Is OKR included in MBO?

$
0
0

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

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

$
0
0

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:そもそも私の関心は「技術者の個性に左右されないテストメッセージの生成」にあるので

How I find and learn new technical things

$
0
0

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.

Mirror repositories for developer in China mainland


SLF4Jの使い方をfindbugsで自動検証する

$
0
0

今日、拙作findbugs-slf4jGitHub Pageを作りました。このブログではこのプロジェクトについて日本語で紹介したいと思います。

概要

  • 拙作PMDプラグインをもとに、2012年8月から実装を開始したfindbugsプラグイン
  • SLF4J利用時のよくあるトラブルを未然に防ぎ、コードの品質を担保する
  • 全自動なので、開発者各々の個性に影響されずに品質の底上を実現できる

既存の課題:SLF4Jの直感的ではないインタフェース

SLF4J(Simple Logging Facade for Java)はJava向けに開発された、ログ用のFacadeです。開発者はSLF4Jが提供するインタフェースを利用することで、「高パフォーマンスなログ処理」と「利用者に好きなログ基盤を選ばせる自由」を提供することができます。例えばLog4j 2のような新しいログ基盤でも、プログラムがSLF4Jを使っていれば、プログラムには手を加えること無く利用が可能です。

ただしSLF4Jのインタフェースはやや独特で、学習と慣れが必要です。例えば下記に挙げる例ではexample 1のほうが直感的ですが、SLF4Jではexample 2の方を推奨しています。この方法はパフォーマンス上有利なのですが、コードに長年手が加えられていくとプレースホルダとパラメータ数の不一致などが容易に発生するため、ログに残すべき値が残せていなかったなどのトラブルに繋がります。

// example 1: not good, because JVM will concat strings even if debug log is needless
logger.debug("User id is: " + userId);

// example 2: better, because it will not generate needless string if debug log is needless
logger.debug("User id is: {}", userId);

また例外のstacktraceを出力するためのメソッドinfo(String format, Object... arguments)だというのもわかりにくい点です。以下の例のように可変長配列の最後の要素がThrowableであればstacktraceを出力してくれるのですが、これはドキュメントを読むか人に聞くかしなければわからないでしょう。

// example 3: not good, because stacktrace and log messages are separated into two log records.// And user cannot configure how to log stacktrace.
logger.warn("Exception ({}) occurred when userId is {}", e.getMessage(), userId);
e.printStacktrace();

// example 4: better, it's configurable and not separated into multiple log records.
logger.warn("Exception occurred when userId is {}", userId, e);

SLF4Jは現在のJava開発でデファクトスタンダードと言えるログ用ライブラリですが、このような難しさがあるため利用時は経験ある開発者からのサポートやレビューが欠かせません。ただし、アプリケーションコードのどこにでも書かれうるログ処理のすべてを人力でレビューし品質を担保するのは至難の業です。

提案する解決:静的解析による自動的かつ横断的な検証

私が開発したfindbugsプラグインの発想はごくシンプルなもので、上記で挙げた問題を機械による検証によって解決するというものです。 個人の経験と尽力によって回避するのではなく、検証を機械化し自動化することでコストの削減とスケーラビリティの向上、抜け漏れ防止を実現します。

技術的な特徴

主な技術としては、findbugsが提供するオペランドスタック解析を主に使用しています。これによりプレースホルダとパラメータの数の不一致を検出したり、e.getMessage()をパラメータとして使っているコードを検出したり、LoggerFactory.getLogger(Class)メソッドの引数を検証したりしています。また.classファイルに書かれた定数文字列を解析することで、簡易ではあるもののログフォーマットの人間にとっての可読性を検証するといったことも取り入れています。

findbugsプロジェクトは息が長いということもあり、コードが非常に難解です。またテストも困難です。 このプラグイン開発では統合テストを重視テストパターンを増やすことで、TDDを可能にしつつエンバグを減らすことに努めています。またバグ修正時はまず再現テストを書く、ということを徹底しています。

またTravis CIが提供する機能により、Java 7&8SLF4J 1.6&1.7の2軸でビルドマトリックスを組んでいます。これも多くの環境をサポートする上で非常に役立っています。

どのくらい使われているか

OSSプロジェクトでの利用実績はほとんど無いと認識していますが、クローズドなプロジェクトではそこそこ使われているようです。2012年11月にいただいたIssueをはじめとして、今でもバグ報告・新規機能要望などをいただきます。「このコードを解析するとエラーになる」と、.javaファイルや.classファイルをメールでいただくこともあります。

特にこの5月ごろから月あたりのDL数が平均40から1,700(ユニークIPアドレスベースでの計数)へと大幅に上がったのですが、どこかの大きなプロジェクトで使っていただいているのでしょうか。

f:id:eller:20150920134539p:plain

以上です。 もし皆さんのプロジェクトでSLF4Jを使っていたら、ぜひ当findbugsプラグインの利用を検討してみてください。Mavenで使う方法はこちらに書いてあります

関連する記事

Guava Release19がそろそろ来そう

$
0
0

現時点でRC2まで出ています。

個人的に興味深いのはCharMatcherにファクトリメソッドが導入された理由。staticフィールドだとクラス初期化時に初期化されなければならないが、ファクトリメソッドならメソッド実行時までインスタンス生成を遅延できるためと説明されています。

// beforepublicstaticfinal CharMatcher WHITESPACE =
      new NamedFastMatcher("WHITESPACE") {
          :
          :
          :
      };
// afterpublicstatic CharMatcher whitespace() {
    return Whitespace.INSTANCE;
  }

  @VisibleForTestingstaticfinalclass Whitespace extends NamedFastMatcher {
    staticfinal Whitespace INSTANCE = new Whitespace();
    :
    :
    :
  }

なおこうした内部クラスを利用する方法*1はマルチスレッド環境でもsynchronizedや明示的なロックが必要ないことで知られています*2。 Stringでもprimitive型でもない定数、特に正規表現のような初期化処理が重いものは、積極的にファクトリメソッドで置き換えると良さそうです。

*1:このページのlazy initialization holder class idiom

*2:だからこういう問題も起こるのですが

(メモ)クラスタ管理関連

$
0
0
  • etcd
    • KVS
    • Leader/Follower
    • Raft
  • fleet
    • Deploy
    • Service Discovery
  • Hashicorp Consul
    • CP
    • needs several nodes as server per Datacenter
    • each nodes in Datacenter installs Consul agent
  • Hashicorp Serf
    • AP
    • is used by Consul
  • Docker Compose
    • Define set of container instances
  • Docker Swarm
  • Docker Machine
    • Create and initialise instance to deploy Docker container
    • Supports both remote and local
  • Registrator
    • Hook for docker command, to register/unregister container instances
  • Netflix Eureka
    • Service Discovery
  • SkyDNS2
    • CP
    • DNS but not only address but also ports
    • Depends on etcd
  • Hashicorp Terraform
    • Deployment
  • Hashicorp Otto
  • Hashicorp Packer
  • Netflix Asgard
  • systemd
  • Sensu

コード内コメントとJavadocの書き方

$
0
0

社内勉強会向けに作成したコード内コメントとJavadocの書き方についてのスライドを、Speaker DeckとSliDeckで公開しました。

このスライドは概要とメリットについてざっくり説明し理解と学習の動機を作ることを目的としていますが、これは日本ないし中国の大学ではコメントについてそこまで扱わないらしい*1という前提に基づいたものです。

ここに記載のない発展的な内容としては以下が挙げられますが、これらについて学ぶのはまず手を動かした後で良いと考えています。

プレゼン後に「publicでないクラスやメソッドJavadocを書くべきか?」という質問を受けましたが、私の答えは「書くべき」です。自分自身の理解を深め、備忘にもなり、将来のメンテナンスも助けてくれます。少しでも直感的でないコードがあるならば、時間を取って書きたいです。 まぁ書くべきものは厳密には対外的なAPI Specではなく、内部実装方針や歴史的経緯等になるかもしれませんので、Javadocを書くべきというよりは開発者向けドキュメントを書くべきと言うべきなのかもしれません。

また、ドキュメンテーションコメントはOSS contributionの良い題材になるとも話しました。typo修正くらいなら敷居は低いですし、多くのOSSでは喜ばれるはずです。自分の経験上、リジェクトされることはほとんどありませんでした:

なお自分のJavadocに関する理解は、Oracle公式ドキュメントに加えて「エンジニアのためのJavadoc再入門講座」に依るところが多いです。英語の解説書でこのくらい幅広く丁寧に説明したものが欲しい……。

エンジニアのためのJavadoc再入門講座 現場で使えるAPI仕様書の作り方

エンジニアのためのJavadoc再入門講座 現場で使えるAPI仕様書の作り方

*1:共同開発ないし保守については優先度が低い印象を受ける

docker-composeで開発環境を配布する

$
0
0

上海Microsoftで行われたShanghai Docker MeetupのLTにて発表した、docker-composeを使って開発環境をContributorに対して配布するというユースケースに関するスライドをSpeaker Deckに公開しました。

Partake開発の際はVagrantで開発環境を配布していたのですが、今ならdocker-composeの方がシンプルかつ幅広く使われているのではと思います*1。中国からだとToolboxのダウンロードやDocker registryからのダウンロードが安定しないという問題があるのですが、中国Microsoftでミラー等の公開を検討しているそうです。

なおこのスライドを作るときにdocker-compose.ymlフォーマットのバージョン2が公開されている事に気づいたのですが、残念ながらnginx-proxyが未対応だったのでまだ自分のプロダクトでは使えていません。


追記:nginx-proxyがdocker-compose.ymlフォーマットのバージョン2に対応したそうです。

*1:VagrantからDockerを使う必要性はあまり感じていません

エラーログと例外の扱いについて

$
0
0

社内勉強会向けに作成したエラーログと例外の扱いについて説明したスライドを、Speakerdeckで公開しました。一部社内特化部分(ログレベルポリシーやMSA向けMDC使用法 など)を削除して、口頭で補足した部分を補っています。

これらの理想的な使い方はシステムを設計から運用までひととおり経験してみないとわかりにくいものですが、それなりの規模のシステム企業における業務開発でその経験を得ることはかなり難しいのではないでしょうか。結果、何の意味もなさないログが量産されてシステム運用の邪魔になってしまいます。きちんとポリシーを組んで統一していくか、各開発者が運用を知り納得して良いログを書けるようにしていく必要があります。

マネジメントとは挑戦と成長のための環境づくりだと考えている私にとって、ポリシー策定よりは「きちんと運用を知り自発的に支えになれる開発者」になれるための情報伝達こそがManagerとしてやるべきだと考えており、そのためのアクションがこのスライドというわけです。前回もそうでしたが、しばらくは非機能要件について考えるきっかけと大まかな方向性を提示していければと思っています。

関連する投稿

Impact of error-prone

$
0
0

Findbugs is really good solution to improve quality of code

As an author of findbugs-slf4j, I really love Findbugs. It lets us find problems by static bytecode analysis. This tool improves quality of each module, reduce reproducing known bug, and point problem quickly in IDE. We do not have to use code review to find known problems and/or antipatterns, Findbugs will do it before developer sends pull-request. This 'push notification' is really cool, we can point problem even if developer has no motivation to find it.

It is really ideal solution also for large scale development team. Even if your team has hundreds developers, they can get help from Findbugs from the beginning of working day. Even though some of them have less experience and knowledge about our depending framework, module and language, Findbugs can help them to catch up quickly.

Findbugs is constructed based on both academic and practical experience, and now it's OSS so not only limited contributors but also everyone who wants to improve documentation comment, message translation, new detectors and so on.

Problems in Findbugs

But I have a dream to implement Findbugs alternative, to replace Findbugs with better implementation. In my personal opinion, it has some problems:

  • Difficult to maintain: Less documentation comment to describe usage*1, Less fresh document to describe (e.g. how to implement plugin), Too wide scope,
  • Slow performance: Not ready to use multi-thread so efficiently. No support for incremental analysis provided by build tools.
  • Difficult to test: To test Findbugs plugin, test-driven-detectors4findbugs was good solution but it doesn't work with Findbugs 3.0.1 due to internal implementation change. We also need a hack to test by Maven.

Yes Findbugs is OSS, so in theory we can solve them by own. But recently this project is not so active, and there is no popular fork for now. It would be problem to solve.

New alternative: error-prone

Last week I found an interesting static analysis tool, named error-prone.

github.com

This does not check bytecode, it applies hack to javac so it handles AST under com.sun.source.tree package. In my understanding, it has many good points:

  • Providing automated correction.
  • Providing simple but enough guideline, so we can write unit test to test rules to detect bug pattern.
  • It's product from Google so it has detailed documentation comment.
  • Using Annotation Processor to manage metadata of bug pattern, so we do not have to maintain XML files,

I haven't tried it with large amount of code, so I cannot compare its performance with Findbugs yet. I hope it's better than Findbugs. About openness and activeness in its community, I'm not sure yet. I've sent a pull-request to add bug pattern, I hope it's open even to non Google developers.

Do we need to switch to error-prone?

In my understanding, problem in error-prone is as follows:

So if you're using Findbugs, I think you do not have to switch to error-prone for now, its merit is really limited and almost all of them are not for users but for contributors.

But if you're author of Findbugs plugin, I think error-prone has value to keep watching on it. If its agility and resource is enough, it might grow and replace other solution later.

*1:I've sent some patches and pulll-requests but it's not enough yet


RxJavaはVert.x 3でSQL書くのに便利

$
0
0

自分にとっての新技術を試すための個人プロジェクトでVert.xを使っているのだが、PostgresクライアントがTechnical Previewになったのでオンメモリに乗せていたデータをpostgresに乗せるようにしたところ、2重3重のネストがコードに現れるようになった。

そこでRxJavaを利用することでコードの短縮化を図った。以前利用したReactive Streamsとは別物とのこと。

結果

Handlerベースの実装だとClassがだいたい100行だが、Observableベースの実装だと40行強で済んだ。ネスト数も抑えられている。

何が効果的だったのか

コードの見通しを良くしたのは例外処理。 Handler(コールバック)内で処理が失敗したかどうか毎回確認していたのが、Stream API同様のmap処理に置き換えられた。

サービスを書いているとよくある「getConnectionしてトランザクションを開始してSELECTしてINSERTしてCOMMITする」という処理が、Handlerで書くと5重ネストと5回の例外処理に化けてしまう。ネストをメソッドチェーンに置き換えたうえで例外処理を一本化(主にSubscriber側の処理になる)できるのは非常に見通しが良い。

// before
        postgreSQLClient.getConnection(connected -> {
            if (connected.failed()) {
                future.fail(connected.cause());
                handler.handle(future);
            } else {
                SQLConnection con = connected.result();
// afterreturn postgreSQLClient.getConnectionObservable()
            .flatMap(con -> {

使用感:DB操作をObservableとしてを扱うコードを書く上での課題

postgresクライアントのInstantの扱いにバグがある模様。現時点ではStringとして取り出す必要がある。Technical Previewだし仕方ない。

非同期APIなのでリソースの解放にtry-with-resourcesやLoanパターンが使えない点に注意が必要。例えばDB接続を使い終わった時点で接続を閉じるには、以下のように Observable#doAfterTerminate(Action0)を使う必要がある。これなら処理が正常終了した時も異常終了した時も実行される。

return postgreSQLClient.getConnectionObservable().flatMap(con -> {
            return con.queryObservable(
                    "SELECT id, uploaded_file_name, resolutions, generated FROM task")
                    .doAfterTerminate(con::close);
        }).flatMap(selected -> {

なおリソース解放用に用意されているObservable#using()を律儀に使おうとすると以下のようになってしまい、EclipseJavaコンパイラだとうまくコンパイルできないことがある。第一引数にFunction0(Resource)ではなくFunction0(Observable<Resource>)を使えるなら、() -> conなどという無意味なコードを書かなくて済んだのだが……。

実装を見るとusing()doAfterTerminate()とは全く違う複雑な処理をしているので、doAfterTerminate()で完全な代替になるとは思わないほうが良さそうだ。Observable#using()を自然に使えるような書き方を探す必要があるが、Vert.xのサンプルプロジェクトには現状usingを使ったサンプルは無い。

return postgreSQLClient.getConnectionObservable().flatMap(con -> {
                return Observable.using(
                        () -> con,
                        connection -> connection.queryWithParamsObservable("SELECT uploaded_file_name, resolutions, generated FROM task WHERE id = ?", params),
                        connection -> connection.close());
        }).flatMap(selected -> {

もっと利用できそうな機能

今のところ更新系など「値を返す必要はないけど正常終了したかどうかだけ確認したい」場合にObservable<Void>を返しているが、Single<Void>を使うほうがシンプルかもしれない。複数の結果が帰ってくることがないとわかっている以上、それを型として明示したほうが何かと混乱がなさそう。

現在のプロジェクトではSchedulerを一切使っていないが、Vert.xと組み合わせて使う以上その必要性は薄そうなので、GUIアプリで試す必要があるかも。

まとめ:RxJavaは何に便利か?

自分が想像できるのは非同期I/Oを多く持つサーバで、多数のI/Oをマージしてクライアントにレスポンスを返すような処理を書くこと。もちろんブロッキングI/Oも混ぜることも可能(Vert.xの機能に寄せるかSchedulerを利用する)。Stream APIとほぼ同じ感覚で扱える。

またObserverSubscriber利用するスレッドを指定できるので、UI Threadを極力あけたい&イベントベースで書きたいAndroidのようなGUIアプリにおいても活躍が期待されているように見える。もうずっとSwingに触れていないがおそらくSwingでも使えるだろうし、JavaFxバインディングは公式に存在するようだ。

MSAキャッチアップ用プロジェクトを作りました

$
0
0

MSAは理屈が多く、手を動かさないとわからないことが多すぎるので作りました。

ついでに非同期I/OとサーバサイドReactiveを学ぶためにVert.xRxJavaを採用しています。Spring Framework 5は別で学ぶ機会があるので一旦除外。ひとまず試行錯誤できる環境が用意できた状態です。

できていること

  • マイクロサービスごとに独立したMavenプロジェクト
  • docker-composeですべてのマイクロサービスを起動・リンクしての動作確認
  • docker-compose scaleでのマイクロサービスごとのスケールイン・スケールアウト
  • 非同期I/O主体のWEBサーバ開発
  • マイクロサービス間のHTTP通信
  • フロントエンド(UI生成とリクエスト受け付け)とバックエンド(FFmpegによる変換)の分離
  • マイクロサービスごとに個別のDB(postgres)を用意
  • Hashicorp Consulによるサービスディスカバリ
  • Hazelcastをメッセージキューとしたマイクロサービス間でのイベントのやり取り
  • nginx-proxyによるAPサーバ数増減への追随

認識できている課題

  • 共通ライブラリ(common)がある。メッセージキューに突っ込むエンティティ(イベント)クラスを共有したり、UUID生成方法を統一したりするためだが、各マイクロサービスがライブラリのバージョンに対するコントロールを失う可能性がある。エンティティはJsonObjectのような汎用クラスで置き換えるべきかも。
  • マイクロサービス間の通信に非効率なJSON&REST on HTTPを使っている。HTTP/2を入れたりgRPCに切り替えることでどの程度性能に影響があるのか見てみたい。
  • メッセージキュー(Vert.xデフォルトのEvent Bus)がメッセージの伝達を保障しない。解消のために使い慣れたApache Kafkaに置き換えるか、Yahoo! Pulsarを試す機会にしたい。
  • メッセージキューがグループをサポートしない。1つのイベントを複数の異なる種類のコンシューマが受け取るという、コレオグラフィ採用においてわりと重要なことがやりにくい。上述のKafkaかPulsarで解消できる。
  • サーキットブレーカが無い。対象マイクロサービスが動いていないと、サービスディスカバリがNPEで落ちる。Vert.xがコンポーネントを提供しているが、インタフェースがいまいちっぽい。
  • ユーザ認証がない。OAuthくらいは組み込みたい。Vert.xがコンポーネントを提供している
  • 監視の経験を積みたい。Vert.xはHawkular連携用のコンポーネントを提供している
  • REST APIのバージョン管理。HTTPヘッダかURLでバージョンを指定する手法が採れる。
  • 本当にReactiveの利点が出ているか確信がない。特にback pressureについてはできていないのでは、Pumpだけでファイル-HTTP間ないしHTTP-HTTP間のback pressureが実現できているのだろうか。

FindBugsコミュニティにおける例の件の顛末、そしてSpotBugsとは何か

$
0
0

先週、FindBugsのメーリスに興味深い宣言が流れました。今のFindBugsはメンテ困難であり現体制での継続保守が難しいとするものです。

 ただこれをもってFindBugsはおしまいだ、としてしまうのはちょっと違います。コミュニティ自体はまだ活発で、プロジェクトのあるべき姿について話し合っています。私はコミッタでもなんでもないのですが、1週間経ったこともあり日本語で簡単に経緯を紹介したいと思います。

出典明示のため細かくリンクを張りますが、リンク先を見ずとも本エントリだけで理解できるよう努めます。

 

現体制最大の問題はプロジェクトリーダーの不在

1年以上前から、プロジェクトリーダーのBill Pugh氏はコミュニティ開発者からの連絡に返信しなくなりました。メールもそうですがGitHubTwitterでのmentionにも返信しません。私もこの5月にTwitterで連絡を取ろうとしましたがやはり返信はありませんでした。

彼だけがSourceForgeGitHubの管理者権限を持っているので、彼の協力なしにはウェブサイトの更新も新バージョンのリリースもTravis CIの導入もできません。これがプロジェクトを停滞させている最大の問題です。

 

なお上記のメールが流れた今でも返信がなく、Hacker Newsに「1週間時間をくれ」と一方的に声明を出しただけです。そしてその1週間が経過した今でも連絡はありません。コミュニティオフィシャルの場に現れないこの姿勢は、本当に戻ってくるつもりがあるのか不安にさせるものです。

 

分断を最大限防ごうとしているコミュニティ

このような状態ではプロジェクトのフォークが検討されると思いますが、上記メールではフォークは推奨されていません。確かにSpotBugsというフォークがありますが、これはFindBugsと決別したものではなく、プロジェクトリーダー不在でも開発を続けるための最後の手段です。今後のプロジェクトリーダーの行動次第では、FindBugsにマージされる可能性があります。

FindBugsにはプラグイン機構があり、その上にfb-contribfind-sec-bugsなどの素晴らしいプロダクトが作られています。またビルドツールやIDEとの高い親和性もあり、幅広いユーザに利用されてもいます。互換を考慮した上でJava9対応などの新機能を入れ、バグやドキュメントの不備を直していければ理想的です。

 

以上のように、現行のFindBugsユーザはまだ静観して構わない状況と考えます。このままSpotBugsがFindBugsにマージされなくても、JARファイルの名前が変わる程度の影響で当面は利用できるはずです。むしろドキュメントの不備が直りやすくなったり、修正リリースがより頻繁になったりと恩恵のほうが大きいのではないでしょうか。

 

FindBugs以外のバイトコード静的解析手段を検討したい場合

それでもFindBugs以外の選択肢を検討したい場合は、当該スレッドで言及されたHuntBugsを試してみてください。FindBugsの機能の40%がカバーされているそうです。もちろんHuntBugsには別の課題があることには留意してください。

他にはIntelliJ IDEAも推奨されています。IDEAはIDEですが、バッチ(CI)に組み込んでXMLを出力させることも可能とのことです。

また個人的にはGoogleの開発しているError Proneに期待しています。Eclipse統合はだいぶ難しそうですが、動作が軽いですしテスタブルなプラグイン開発が可能です。Google社内でも使われているそうですし、今後しばらくは改善されていくと期待できます。

 

まとめ

以上、 簡単に経緯と現状をまとめました。

コントリビュートに関心のある方は、FindBugsではなくSpotBugsのリポジトリをご覧ください。ドキュメントを更新するなかで、英語→日本語の翻訳は今後求められるはずです。単にFindBugsを使いたいという方は、ひとまず従来通りで大丈夫です。

JJUG CCC 2017 SpringにてSpotBugsの話をします

$
0
0

最近ブログ熱が下がっていたのと、SpotBugsの中の人になってドキュメントとかいろいろ触っていたのとで更新が途絶えていました。 そろそろSpotBugs 3.1.0−RC2を出せるのではと思いますので、そのうち試してください。
なおJava8対応強化だけであればリリース済みのRC1でも試せます。RC2ではEclipse Plugin周りの強化が入る予定です。

さてFindBugsのフォークであるSpotBugsについて、今週土曜日に開催されるJJUG CCC 2017 Springでセッションをします。

勤め先がスポンサーをしている縁での参加となるため、SpotBugsの中の人としてのPRだけでなく、SpotBugsを業務利用している立場としての工夫や注意点、運用についても話す予定です。日本での発表はかなり久々ですが、面白い話ができればと思います。

ご参考:過去の発表内容

お前誰?という方のために、過去の発表資料を載せておきます。最近やっているのはJavaJavaScriptとDockerとMSAが多いです。

JJUG CCC 2017 Springでセッション&LT参加してきました

$
0
0

前回のエントリでの宣言通り、本日のJJUG CCCでセッション発表してきました。発表のスライドと動画が後日、下記会社のアカウントから共有されると思います。公開されたらこの記事で紹介します。

昼休み明けすぐの発表でしたが、だいたい140名ほど参加いただけたようです。全日程では1,032名の参加があったそうですが、セッション発表時点では700名近く参加されていたらしいので、全体の2割近い方が参加されていたことになりますでしょうか。FindBugs知名度を改めて感じました。

静的解析ツール初心者の聴講者はゼロだったので、最初の方の静的解析ツールのメリットについてはかなり端折り、突っ込んだ内容を厚めに話しました。プラグイン開発デモができなかったのは残念でしたが、spotbugs-archetypeを使っていただければある程度は伝わる……といいなぁと思います。

また懇親会でのLTでも2分ほど話してきました。こちらは純粋にSpotBugsの中の人としての参加です。SpotBugs 3.1.0 RC2はわりと安定していますので、皆さんも使えるところで試してフィードバックいただければと思います。

追記(2017/05/24)

セッションのスライドが公開されました。

www.slideshare.net
Viewing all 157 articles
Browse latest View live