mike-neckのブログ

Java or Groovy or Swift or Golang

Java Day Tokyo 2017 参加メモ

Java Day Tokyo 2017に数年ぶりに参加しました。そのメモです。僕が参加したのは次のセッションです。

  • 基調講演
  • Java 9 and Beyond: Java Renaissance in the Cloud
  • Modular Development with JDK 9
  • Tuning G1GC
  • Java SE 9のすすめ
  • 緊急開催!Java技術メモ三銃士が語るエンジニア道
  • スペシャルパネルセッション - 海外Javaコミュニティ・エンジニアは今どんな活動をしているのか?

基調講演

Javaの現状と今後についてのポジショントーク。Java9/10についていろいろと情報がありましたが特に目新しい情報はありませんでした。目新しい情報がないということはJigsawがRejectされたことについても特に言及なしでした。Java9は7月にリリースできるのでしょうか…???

まあ、僕のような平凡なエンジニアができるのは

というところでしょう。これは別にJEPの実装をやれというわけではなく、early accessJDKを触ってフィードバックするなどでよいということです。

Java EE8 は7月にリリースされるということでしたが…


Java 9 and Beyond: Java Renaissance in the Cloud

Java9の概要とOracleが提供するツール類、Java10以降の説明。ざっと説明された内容は以下の通り。

  • Jigsaw
  • jlinker
    • カスタムランタイムや実行バイナリを作るツール
  • AOTコンパイラ
  • GC
    • G1GCがデフォルトになる
  • オラクルの提供するツール類
    • Flight Recorder/Mission Control/Advanced Management Console
  • Varhara
    • メモリ効率の向上
  • Panama

Modular Development with JDK 9

Jigsawについての説明。前から疑問に思ってたことが解決できた。

前からの疑問:既存のjarに対してどうやってモジュールに組み込んでいくか?

  • オートマティックモジュールという仕組みを利用して組み込む
    • jarの名前をそのままモジュール名に変換する(例: spring-boot-starter-web なら spring.boot.starter.web モジュール)
    • jarファイルをモジュールのあるディレクトリーに配置して -m オプションで指定する

なお、移行に関してもアドバイスが有りました。

  • jdk.unsupported にあるクラス(例えば sun.misc.Unsafe など)についてはモジュールで使う宣言をすれば利用できる
  • JDK内部のクラスを利用しているもの (sun.misc.Base64Encoder を利用しているなど) はもれなくアプリケーションが動かなくなるので、代替のクラスを利用すること
  • ClassLoader を使ってクラスの読み込みをカスタマイズしているものについても壊れる可能性があるので早めに対策すること
  • rt.jar などのJDKのjarの名前、パスに依存しているアプリケーションも死ぬ

Tuning G1GC

あまりにGCのことがわかってなくて、ちょっと理解できませんでした。実際英語もよく聞き取れなかったし、通訳さんもつらそうでした。また説明の途中で時間切れになって終わりました…

Java SE 9のすすめ

またもやJava9の話。もっとJava EEの話を聞くとかすればよかったかなとも思ってる。

  • Breaking Changes
    • _ が変数名としては使えなくなる
    • LogManager#addPropertyChangeListener などの一部のメソッドが使えなくなる
    • win-x86のclientがなくなる
    • Java DBが同梱されなくなる(Derbyが欲しければjarを落としてくる必要がある)
    • hprof/jhatがなくなる
    • JREの構造が変わるので rt.jar のパスに依存しているともれなく壊れる
    • 起動オプション -Xbootclasspath がなくなってクラスを差し替えて…(非推奨)
  • 新しい機能など
    • java.util.concurrent.Flow のインターフェース(リアクティブストリーム用)
    • jdk.incubator モジュールのhttp/2クライアント
  • コンパイラーの改善
    • tey-with-resourceの改善(下記1参照)
    • 匿名クラスのインスタンス生成時に型パラメーターをダイヤモンドで省略可能になる(下記2参照)
// 1. try-with-resource
// 従来
final Reader reader = ...
try (final Reader anotherVariable = reader) {
  // do something
}
// Java9 or later
final Reader reader = ...
try (reader) {
  // do something
}

// 2. anonymous class
// 従来
final Function<String, Integer> length = new Function<String, Integer>() {
  // ...
}
// Java9 or later
final Function<String, Integer> length = new Function<>() {
  // ...
}
  • APIの改善
    • Stream#ofNullable(x) / Stream#iterate(seed,hasNext,next)
    • Collectors#flatMapping / Collectors#filtering
    • Optional#stream - OptionalFoldable っぽくなる / Optional#or - Optional の合成 / Optional#ifPresentOrElse 男らしいメソッド…
    • List#of / Set#of / Map#of それぞれのスタティックファクトリーメソッド(やっと今頃)
    • Enumeration#asIterator - 生サーブレットを触っている人にはおなじみの Enumeration にやっと(10年ごしくらい) Iterator にできるメソッドが追加

緊急開催!Java技術メモ三銃士が語るエンジニア道

Q なぜメモを取り始めたか?

みな、誰かに読まれることというよりは自分のためにメモを取るという感じですね。

Q やっててよかったこと/やらなければよかったこと

書き続けることでセルフブランドが向上するということですね。

Q メモを続けるコツ

全員共通しているのは無理をしないということでした。

Q 技術情報の調べ方

ひしだまさん以外は基本的には公式のドキュメントにあたることが多いようです。ひしだまさんは使える・動くを主軸に考えて調べているようです。

質問コーナー

これは多分、質問の意図が理解できてなかったっぽい…

スペシャルパネルセッション - 海外Javaコミュニティ・エンジニアは今どんな活動をしているのか?

疲れてて、実はあまり覚えてない…

という感じでJava9をかなり多めに聞いてきましたが、この内容を元に今後も考えていきたいです。

Java9(ea163)でHttpClientを使ってみたノート

ディレクトリ構成やmodule-info.javaで少々ハマったので(10分)、ノート。


Java SE9から公式のやっと面倒くさくないHttp Clientが出るので試してみた。

試してみたのは jdk.incubator.httpclient モジュールの jdk.incubator.http.HttpClient とその関連クラス。

1. ディレクトリー構成

Java9からはモジュールを定義しておかないと、使いたいクラスがうまく利用できない。したがって、まずモジュール名を決定した後にモジュール名と同じ名前のディレクトリーを作り、その下に src ディレクトリーを作る。

まずモジュール名は com.example とした。

ディレクトリーを次のように作る。

root/
└── com.example
    └── src

2. モジュールの定義

src ディレクトリーの下に module-info.java を作る。ここには、公開するパッケージの定義と利用するモジュールを記入する。詳しい話は IT Proの連載記事 などを参考にした。なお、今回作るプログラムを配置するパッケージを com.example.ex とした。また、利用するモジュールは上述のとおり jdk.incubator.httpclient である。

module com.example {
  exports com.example.ex;
  requires jdk.incubator.httpclient;
}

現在のディレクトリー構成

root/
└── no.lib
    └── src
        └── module-info.java

3. プログラムを書く

適当に書く。

package com.example.ex;

import jdk.incubator.http.HttpClient;
import jdk.incubator.http.HttpRequest;
import jdk.incubator.http.HttpResponse;

import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class HttpClientTest {

    public static void main(String[] args) {
        final ExecutorService executor = Executors.newFixedThreadPool(1);
        final HttpClient client = HttpClient
                .newBuilder()
                .version(HttpClient.Version.HTTP_1_1)
                .executor(executor)
                .followRedirects(HttpClient.Redirect.SAME_PROTOCOL)
                .build();
        final HttpRequest request = HttpRequest.newBuilder(URI.create("https://www.google.com/teapot"))
                .GET()
                .build();
        client.sendAsync(request,
                HttpResponse.BodyHandler.asString(StandardCharsets.UTF_8))
                .thenApply(HttpResponse::body)
                .thenApply(s -> String.format("[%s] - %s", Thread.currentThread().getName(), s))
                .thenAccept(System.out::println)
                .join();
        executor.shutdown();
    }
}

実行結果

WARNING: Using incubator modules: jdk.incubator.httpclient
[pool-1-thread-1] - <!doctype html><html class="google" lang="en"> <script>(function(H){H.className=H.className.replace(/\bgoogle\b/,'google-js')})(document.documentElement)</script> <meta charset="utf-8"> <meta content="initial-scale=1, minimum-scale=1, width=device-width" name="viewport"> <title>Error 418 (I&#8217;m a teapot)!?</title> <link href="//www.gstatic.com/teapot/teapot.min.css" rel="stylesheet"> <a href="//www.google.com/"><span aria-label="Google" id="logo"></span></a> <p><b>418.</b> <ins>I&#8217;m a teapot.</ins></p> <p>The requested entity body is short and stout. <ins>Tip me over and pour me out.</ins></p> <div id="teaset"><div id="teabot"></div><div id="teacup"></div></div> <script src="//www.gstatic.com/teapot/teapot.min.js"></script> </html>

Process finished with exit code 0

現在のディレクトリー構成

└── com.example
    └── src
        ├── com
        │   └── example
        │       └── ex
        │            └── HttpClientTest.java
        └── module-info.java

たまにモジュール内のパッケージの export 先が決まっていることがあったりするので、気をつけたい。

JSUG勉強会 2017 - 3 〜ドメイン駆動設計 powered by Spring のメモ

JSUGの勉強会に参加したので、そのメモ。

jsug.doorkeeper.jp

資料は公開されるだろうから、ここでしか聞けないことを中心にメモ(ツイート)したつもりだが、資料に盛り込まれている可能性は十分にある。なお、資料は以下の通り。

www.slideshare.net


個人的な感想

  • ドメイン駆動のセッションや話は「ドメイン駆動はいいぞ」という感じで抽象的な話になりがちなことが多いのだが、今回はフレームワークが限定されたこともあってどのようなオブジェクトをどのように作っていくという具体的な話が聞けて満足だった

  • ビジネスルールとドメインロジック
    • ビジネスルール(契約・法令・明文化されていない商習慣)などがソフトウェア開発の分析対象(もちろん、ビジネスルールがゲームのルールだったりサービスのルールだったりもする)
    • その分析結果をプログラミング言語で表現したものがドメインロジック

  • ソフトウェア開発のプロセス
    • いわゆるウォーターフォールのプロセス(情報収集・分析・設計・実装・テスト・リリース・運用)に加えてモデリングをおこなう
    • モデリングすると無理・無駄・ムラが減る
    • しかしモデリングするから仕様を決めなくてよいというわけではない
    • これらのプロセスをすべて毎日やる
  • Spring Frameworkドメイン駆動
  • いわゆるウォーターフォール(個人の所感を含む)

    • 一般的な文脈で言うSIerウォーターフォールは「伝言ゲーム」
    • 「伝言ゲーム」 = 顧客へのヒアリングする人と設計する人と開発する人が違うような開発
      • まあ、規模が大きいからと言って数百人とか用意しているようなプロジェクトだと、数百人で顧客のところへ押しかけても顧客が迷惑するだけですけどね…
    • もちろんフレームワークを何を選定するかはプロジェクトの自由なので、Spring Bootで「伝言ゲーム」開発も可能
  • ソフトウェアの構成

トランザクションスクリプト = ドメインモデルを構築しない手続きだけを書いたソフトウェア

トランザクションスクリプト型のSpringアプリケーションの構成

f:id:mike_neck:20170329221918p:plain

ドメイン駆動設計によるSpringアプリケーションの構成

f:id:mike_neck:20170329222009p:plain

ドメイン駆動でアプリケーションを作ると、各層とは別にドメインモデルの層を用意して、ここをインクリメンタルに成長させていく

  • ドメインモデル
    • ビジネスロジックの要素は次のものしかない
      • 数値
      • 日付
      • 文字列
    • オブジェクトの種類は次の3パターン
      • 値オブジェクト(数値/日付/文字列をラップしただけのオブジェクト、いわゆるValue Object)
      • 区分オブジェクト(振る舞いをもった enum)
      • コレクションオブジェクト(ListSet をラップしたオブジェクト(ListSet には直接触れさせないで、必要な操作だけを提供する))
  • モジュールの単位
  • ドメインオブジェクトとその他の層
  • ソースコードの文書化

    • メソッド名、クラス名だけでなく、メソッドの返す型、引数の型にはJava APIが出てこないようにして、ソースコードが自然とドメインを語るようにする
  • 具体的なドメインモデルによるSpringアプリケーションの構成

    • HTML ⇔ Controller ⇔ ドメインオブジェクト(プレゼンテーション層)
      • コントローラーはドメインオブジェクトを引数に取るようにする
      • 表示処理(〜の場合には表示する/しない)の演算をプレゼンテーション層には書かない(すべてドメインモデルにておこなう)
      • ドメインオブジェクトにはgetter/setterを設けず、 DirectFieldAccess を有効化してフィールドアクセスする
    • サービス層(アプリケーション層)
      • サービス層(アプリケーション層)には @Validated を引数のドメインオブジェクトにつけておいて、契約による設計を実現させる
    • データソース層
      • データベース層とドメインオブジェクトは別物ゆえ、マッピングを作っている(MyBatis使用)
      • ドメインオブジェクトはロジックの置き場なので、テーブルの論理を持ち込まない
      • データベース層も更新が楽になる、かつデータベースの論理を徹底できるように、きっちり正規化する

後半のトークセッション

ドメインモデルの用語はどこから取り入れているのかという質問に対して

同じく名前についてわたびきさんのエピソード

ロジックの順序について

既存コードが有る状態でのドメイン駆動の取り込み方 : 少しずつ入れていく