ひだまりソケットは壊れない

ソフトウェア開発に関する話を書きます。 最近は主に Android アプリ、Windows アプリ (UWP アプリ)、Java 関係です。

まじめなことを書くつもりでやっています。 適当なことは 「一角獣は夜に啼く」 に書いています。

読んだ : JUnit 実践入門 〜 体系的に学ぶユニットテストの技法

JUnit実践入門 ~体系的に学ぶユニットテストの技法 (WEB+DB PRESS plus)

JUnit実践入門 ~体系的に学ぶユニットテストの技法 (WEB+DB PRESS plus)

既に JUnit 5 が出ているし今更感はある (本書は JUnit 4 を題材にしている) けど、テストの全体的な話も学べるかなって思って読んだ。 JUnit 4 の話もありつつテスト全般に関する知見も書かれているので、(類書も少ないので) 読む機会がある人はさらっと読んでみるといいかもしれない。

新しく学んだこと

テスト全般

  • テストフィクスチャ (test fixtures) : テストの対象やテストの入力値や検証用の値、外部リソースなどの実行環境やテストの実行前に必要なオブジェクトの操作などのこと。
    • 狭義にはテストデータだけを指して 「テストフィクスチャ」 と呼ぶこともあるらしい。
  • 振舞駆動開発 (behavior driven development; BDD) : ソフトウェアの相互作用に着目してソフトウェアがどのように振る舞うかを定義することを起点とした開発技法
    • テスト駆動開発と似ている部分もあるが、ソフトウェア全体がテスト対象で、ユースケースシナリオのシナリオの粒度でシステムをテストするという違いがある。
    • 語彙として、Given (前提) / When (条件) / Then (ならば) というものが使われる。 それぞれテスト駆動開発の arrange (set up) / act (exercise) / assert (verify) に対応する。

JUnit 4 について

docker build 時の apt install が遅い問題 (docker build の --add-host オプションを使って APT のパッケージリポジトリを国内ミラーに設定できる)

こんにちは、Docker ビルドおじさんです。

ubuntu:18.04 ベースで Dockerfile を書いてビルドしまくってるのですが、apt install がとにかく遅い!!! なぜなら日本に住んでいるから!! archive.ubuntu.com が遠い!!!


解決方法

調べてみたらいろいろ解決策がありそうだった。

解決策 その 1

日本を出る。 archive.ubuntu.com の近くに行きましょう。

解決策 その 2

Dockerfile をいじって (一時的にでも) APT のパッケージリポジトリの URL を国内ミラーに変更する。 「apt docker 遅い」 みたいなキーワードで検索するとこの方法がひっかかる。

解決策 その 3

apt-cacher みたいなやつでキャッシュしたり、Squid による透過型プロキシでキャッシュしたりする。 わりとこれが素直な方法な気もするが、ちょっと大変そうな気もする。

解決策 その 4

この記事で共有したいのはこの方法。 docker build コマンドの --add-host オプションを使って APT のリポジトリのホスト名に対応する IP アドレスを書き換えちゃう方法。

例えば ubuntu:18.04 をベースとするイメージの場合、リポジトリのホスト名として archive.ubuntu.com などが使われていて、国内ミラーは jp.archive.ubuntu.com となっているので、nslookup jp.archive.ubuntu.com で国内ミラーの IP アドレスを調べて、docker build --add-host="archive.ubuntu.com:xxx.xxx.xx.xx" . という感じで国内ミラーの IP アドレスを指定してやると良さそう。

セキュリティ的なところはちょっと気になる。

Ubuntu では ca-certificates パッケージで CA 証明書をインストールできるぞ

1 行まとめ

Ubuntu ベースの Docker コンテナSSL 接続をするために ca-certificates パッケージをインストールしましょう。

エラー内容

Ubuntu 18.04 (ubuntu:18.04) ベースの Docker コンテナで HTTPS 接続ができなくて npm install に失敗した。

root@068c8e545fca:/# npm install -g carto
npm ERR! Linux 4.9.125-linuxkit
npm ERR! argv "/usr/bin/node" "/usr/bin/npm" "install" "-g" "carto"
npm ERR! node v8.10.0
npm ERR! npm  v3.5.2
npm ERR! code UNABLE_TO_GET_ISSUER_CERT_LOCALLY

npm ERR! unable to get local issuer certificate
npm ERR!
npm ERR! If you need help, you may report this error at:
npm ERR!     <https://github.com/npm/npm/issues>

npm ERR! Please include the following file with any support request:
npm ERR!     /npm-debug.log

見るからに CA 証明書のエラーっぽい。 /npm-debug.log の中身を見ると以下のような感じ。

0 info it worked if it ends with ok
1 verbose cli [ '/usr/bin/node', '/usr/bin/npm', 'install', '-g', 'carto' ]
(略)
15 info attempt registry request try #1 at 10:34:44 AM
16 verbose request id 454780186dc942d1
17 http request GET https://registry.npmjs.org/carto
18 info retry will retry, error on last attempt: Error: unable to get local issuer certificate
19 info attempt registry request try #2 at 10:34:54 AM
20 http request GET https://registry.npmjs.org/carto
21 info retry will retry, error on last attempt: Error: unable to get local issuer certificate
22 info attempt registry request try #3 at 10:35:54 AM
23 http request GET https://registry.npmjs.org/carto
24 silly fetchPackageMetaData Error: unable to get local issuer certificate
24 silly fetchPackageMetaData at TLSSocket. (_tls_wrap.js:1105:38)
24 silly fetchPackageMetaData at emitNone (events.js:106:13)
24 silly fetchPackageMetaData at TLSSocket.emit (events.js:208:7)
24 silly fetchPackageMetaData at TLSSocket._finishInit (_tls_wrap.js:639:8)
24 silly fetchPackageMetaData at TLSWrap.ssl.onhandshakedone (_tls_wrap.js:469:38)
24 silly fetchPackageMetaData error for carto { Error: unable to get local issuer certificate
24 silly fetchPackageMetaData at TLSSocket. (_tls_wrap.js:1105:38)
24 silly fetchPackageMetaData at emitNone (events.js:106:13)
24 silly fetchPackageMetaData at TLSSocket.emit (events.js:208:7)
24 silly fetchPackageMetaData at TLSSocket._finishInit (_tls_wrap.js:639:8)
24 silly fetchPackageMetaData at TLSWrap.ssl.onhandshakedone (_tls_wrap.js:469:38) code: 'UNABLE_TO_GET_ISSUER_CERT_LOCALLY' }
(略)
30 verbose stack Error: unable to get local issuer certificate
30 verbose stack at TLSSocket. (_tls_wrap.js:1105:38)
30 verbose stack at emitNone (events.js:106:13)
30 verbose stack at TLSSocket.emit (events.js:208:7)
30 verbose stack at TLSSocket._finishInit (_tls_wrap.js:639:8)
30 verbose stack at TLSWrap.ssl.onhandshakedone (_tls_wrap.js:469:38)
31 verbose cwd /
32 error Linux 4.9.125-linuxkit
33 error argv "/usr/bin/node" "/usr/bin/npm" "install" "-g" "carto"
34 error node v8.10.0
35 error npm v3.5.2
36 error code UNABLE_TO_GET_ISSUER_CERT_LOCALLY
37 error unable to get local issuer certificate
38 error If you need help, you may report this error at:
38 error <https://github.com/npm/npm/issues>
39 verbose exit [ 1, true ]

curl コマンドを試してみるも、当然ながらこちらも CA 証明書のエラー。

root@068c8e545fca:/# curl https://google.com/
curl: (77) error setting certificate verify locations:
  CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: /etc/ssl/certs

原因と対応

Ubuntu では基本的な CA 証明書が ca-certificates パッケージで提供されている。 これがインストールされていない状態で npm install コマンドや curl コマンドで HTTPS 通信しようとすると CA 証明書のエラーが発生する。 curl パッケージなどをインストールする際に、デフォルトでは推奨パッケージとして ca-certificates パッケージもインストールされるのでこのエラーには遭遇しづらいが、Docker イメージをビルドする際に apt install -y --no-install-recommends curl という感じで --no-install-recommends オプションを付けていると ca-certificates パッケージがインストールされずに、上記の状態になる。

対策としては、単純に ca-certificates パッケージをインストールすれば良い。

Java EE 技術から EE4J (Jakarta EE) 技術に移行する

2017 年に発表された Java EE の Eclipse Foundation への移管。 移管されたプロジェクトをまとめるルートプロジェクトの名前は Eclipse Enterprise for Java (EE4J) で、Java EE に相当するプラットフォームの名前は Jakarta EE となっている *1

EE4J には JAX-RSJSON Processing (JSON-P) などの Java EE の一部として使われていたプロジェクトも移管されている。 これらを単体で使う場合も今後は EE4J のものを使っていくべきだろう。 (古いリポジトリの方は更新されないだろうので。)

EE4J 傘下になってからの最初のリリースがぼちぼちなされていたりして、そろそろ EE4J の方に移行できるようになってきているので、移行について調べたことをまとめておく。

EE4J の各プロジェクト

EE4J 傘下のプロジェクトについては EE4J プロジェクトページ からリンクがあるので、それを辿ると見つけられる。 例えば JAX-RS のページや JSON-P のページは下記である。

EE4J 各プロジェクトの Maven リポジトリ

EE4J への移管に伴って、多くのプロジェクトの API や参照実装 (Reference Implementation; RI) の Maven リポジトリのグループ ID やアーティファクト ID が変更されている。 API については下記ページにまとめられている。

見た感じでは、javax という部分が jakarta に変更されている模様 *2

参照実装についてはプロジェクトごとに異なるようである。

例えば、JSON-P の参照実装については下記のように書かれており、org.glassfish:javax.json から org.glassfish:jakarta.json に変更されていることがわかる。

The main API jar file is now located at jakarta.json:jakarta.json-api and the main RI jar file is now located at org.glassfish:jakarta.json.

JSON Processing (JSON-P)

一方で、JAX-RS の参照実装である Jersery については、バージョン 2.28 が最初の Jakarta EE 実装としてリリースされているが、特にグループ ID やアーティファクト ID の変更はないようである。

ソースコードの変更は必要か?

Maven アーティファクトの名前が変わってはいつつも、API 自体に変更はない。 Java EE 時代の最後の API を使っているソースコードであれば、そのまま EE4J の最初のリリースに移行できるはず。

This is common for every Jakarta EE project this release: it was required not to provide any changes in API and functionality to ensure the compatibility between last Java EE and initial Jakarta EE releases.

Jersey 2.28 has been released | Jan's Blog

*1:EE4J と Jakarta EE の名前の使い方などは Jakarta EE の FAQ に書かれている。 が、これを読んでも正直なところ EE4J と Jakarta EE の使い分けがいまいちわからない……。

*2:正式な名前変更のルールについてはどこかで言及されているのかもわからないが、見つけられていない。

読んだ : What Is An Engineering Manager?

最近エンジニアリングマネージャという言葉をよく聞くようになった気がするのだけど、自分の思っているエンジニアリングマネージャ像 *1 と全然違うエンジニアリングマネージャ像を語っている人もいる *2 ので、何かしら文献があったりしないのかなーと思って調べたところ、1997 年の paper を見つけた。

peer.asee.org

修士課程のエンジニアリングマネジメントのカリキュラムで使えることを目的とした paper らしく、なかなか興味深かった。 ので、面白かった点などを書き残しておく。

面白かった点とか気になった点とか共感した点とか

エンジニアリングマネージャは優秀なエンジニアでなければならない

There are two kinds of engineers in industry: individual contributors and managers. The managers must be competent engineers first on the ground that you can't manage what you don't understand. Ideally these people should be educated in two professions: engineering and management.

自分が理解してないものをマネジメントできるわけがない。 ド正論。

プロジェクト軸と機能軸

In this paper we will be discussing engineers and managers in the engineering department. These people may be employed on three kinds of engineering work (as viewed by engineering managers):

  • Projects
  • Programs (groups of related projects)
  • Functions (work that supports the projects, e.g., materials engineering, testing, failure analysis, etc.)

大きく分けて、プロジェクト軸と機能軸があるという話。 これに関することを最近よく考えていて、高いレベルの専門性の維持のためには機能組織がないと難しいのではないか、と思っている。 「Definition of a Function」 にて、マネージャの責務として以下のことが書かれている。

A manager responsible for

  • Maintaining a high level of personnel competence in the specialty
  • Equipment relevant to the specialty
  • Investigating new technology

今のうちの開発組織には開発支援 G という機能組織がある *3 のだけど、逆に言うとエンジニアリングの機能組織はそれだけしかなくて、開発支援 G が受け持つ分野以外について高いレベルで専門性を維持するための責任を持つエンジニアリングマネージャが (明確な役割としては) 存在しない *4。 プロダクト開発組織としてより強くなっていくためには、より高いレベルで専門能力の維持向上を図っていく必要があると思っていて、そのためには機能組織が大きな役割を果たすのではないか、と思っている。 (考え中。)

(こういう話に興味がある方が居たらぜひお話したいです! お気軽にお声がけください!!)

エンジニアとエンジニアリングマネージャのキャリアパス

f:id:nobuoka:20190221020749p:plain
Career Progressions

ざっくりとは 「まあそうだよね」 って感じの図ではあるけど、engineering management の先に general management があることや、マネジメントの梯子の最初が program management と function management である点が、なるほどー、という感じ。

マネジメントの梯子の方に project management がないのは、多分 (本 paper における) project management は、通常の (マネージャでない) エンジニアにも求められることだからなのかなー、と思った。

マネージャのおしごと

仕事の計画から体制づくり、プロセスの構築と組織への装着、結果の評価、それをもとにした再計画など。

f:id:nobuoka:20190221023419p:plain
General Tasks of Managers

この中で、エンジニアリングマネージャについての議論で話題にあがりやすいのは体制づくり (人の育成や組織マネジメント) についてだと感じている。 おそらく、仕事の計画などの点は他のマネージャとも共通の要素であるが、人の採用や育成、評価などはエンジニア固有の事情が多いからなのかな、と思う。 また、チームビルディングが難しい、ということも理由の一つなのかもしれない。

本 paper でも、エンジニアリングマネージャが扱わなければならない組織内部の複雑な点として、tiger team *5 の形成について多くの点 (採用や育成など) が挙げられている。

  • Building tiger teams
    • Recruiting the best people
    • Training them
      • Planning and providing engineering experience
      • Continuing their formal education
    • Providing facilities and tools
    • Demanding performance

Time-related thinking

11 の思考のモードが挙げられており、その中で特に Time-related thinking とそれが Innovation のプロセスで求められたときのエンジニアリングマネージャの義務についてなども書かれている。

最近社内で新規プロジェクトの進め方などを議論するときに、よく 「時間」 について話をしていたりするし、本 paper の内容もわかりがあるものだった。

おわり

エンジニアリングマネージャと一口に言っても、対象となるエンジニアリングの領域はいろいろあって、組織や人によってどういう役割を担うのかはだいぶ違ってくるんだろうなー、と思った。 また、エンジニアリングマネージャが担う役割のうち、仕事の計画と推進、結果の評価などの部分はプロジェクトマネージャ、人員配置などはラインマネージャ、という感じで役割を分割したりもできるのだろう。 GREE のブログにもそういうことが書かれていた。

*1:エンジニアリングマネージャとはエンジニアリングのマネジメントをする人である、という認識。

*2:単なるエンジニア組織のラインマネージャをエンジニアリングマネージャって呼んでるような人もいる。 「エンジニアリングマネージャーはエンジニアリングがわからなくてもよいのか」 というブログ記事とか。

*3:エンジニアをサポートするエンジニア~RMP内製開発の強さ・魅力~【前編】」 参照。

*4:同じ技術分野のエンジニア同士の勉強会などは行われてはいるが。

*5:特定のゴールに向かう専門家集団のことらしい。