システム開発で思うところ

Javaで主にシステム開発をしながら思うところをツラツラを綴る。主に自分向けのメモ。EE関連の情報が少なく自分自身がそういう情報があったら良いなぁということで他の人の参考になれば幸い

勉強会の情報

自分が参加したことがある勉強会・カンファレンス・セミナーの情報です。
私が参加しているものは無料のものばかりです。ちなみに、私はヘタレなので複数人によるワークショップではなく、セミナー型の聴講タイプのものにしか参加していません(意図せず、ワークショップになることもありましたが)。
ハンズオンや参加人数が少ないものも基本的に参加していません。私は「その他大勢の一人」でいたいので(ヘタレです)。逆に言えば、私のようなタイプの人でも参加できそうなものを紹介しているともいえます。良い意味で敷居が低いと思いますので 興味を持たれたら まず参加してみてはいかがでしょうか?

UMTP

セミナー・イベント情報 Archives - UMTP 特定非営利活動法人UMLモデリング推進協議会

  • 今はアジャイルのワークショップもやっているみたいですね(未参加)。モデリングだけでなく、DDDやスクラムなどモダンと言われる開発手法全般に守備範囲を広げているとは思っていませんでした。
    UMLの勉強会の内容は書籍だけで黙々とやるのとは違って人の話として聞くのは刺激も含めて参加して良かったと記憶してます。オブジェクト指向UML(DDDも?)に興味があって有識者の話を聞いてみようと思うのでしたら、是非参加されることをお勧めしたいです。講師の方は皆さん質問のしやすそうな方ばかりだったと記憶しています。

  • モデリングについては基本的に固定の内容で実施しているようなので、レベル毎のものを一度参加されれば良いと思います。

OSS-DB

http://www.oss-db.jp/news/event/

  • PostgreSQLの勉強会です。基本的なSQLの書き方というのも多少はありますが、メインはDBの仕組みなどの技術的な話です。私はそちらの方が聞けたので非常に良かったです。ログの話などバックアップ&リカバリーに関係する話もありました。たしか、こちらは勉強会の後、質問させていただいた記憶があります。丁寧に答えていただけたと思います。PostgreSQLは使わないから、という理由だけで聞かないのは勿体ないと個人的には思います。DBも広い意味ではファイルシステム(オンメモリ―でも)だということを理解できましたし、それは多分、本質的には他のDBでも類似だと思います。

  • 基本的に固定の内容で実施しているようなので、レベル毎のものを一度参加されれば良いと思います。

JJUG

日本Javaユーザーグループ

  • Java全般の事を学べる場所です。JavaSE、JavaEEJVM言語、DDDなどの設計関連など多岐にわたります。個人的には一番知りたい情報を収集できる場です。
    ナイトセミナー(月1回)は情報公開当日にほぼキャンセル待ちになるくらい人気。
    JJUG CCC(年2回)で技術動向が分かったり、他の開発現場の話を聞けたり、書籍を執筆者やアクセス数の多いブログの中の人に出会える場でもあります。私は懇親会に参加したことはありませんが、参加すれば より面白いかもしれませんね(人によっては)。

  • 内容はイベント毎に異なります。

2017/10/21 追記

動画

www.youtube.com

JSUG

日本Springユーザ会 | Doorkeeper

  • Springは使っていませんがJavaEEとの違いや技術動向を知っておきたいという意図で参加しました。JavaEEは技術標準として、SpringはOSSの代表という感じと個人的には思っています。どちらが良いというのではなく、どちらも大切だと思います。一応、なんでもかんでも参加はしていませんが、私のようなアプローチはキャンセル待ちになってしまった人からすれば迷惑かもしれませんね。。とはいえ、JavaEEから離れるとしたらOSSとしてのスタンダードだと思われるSpringは選択肢になるので情報取集はしておきたいんですよね。
    (でも正直、JavaEEって そんなに悪くないと思うんだけどなぁ。)

  • 内容はイベント毎に異なります。

Java Day Tokyo

  • 個人的にはJJUGの延長的な位置づけです。Oralceが主催をしているということもあると思いますが、Java標準(JSR的な)の情報を知ることが出来ます。今後のJavaSEやJavaEEのリリース情報なども、このカンファレンスならではなのかもしれません。

Google Atmosphere Tokyo

  • Googleの情報収集。便利な機能や技術動向を収集するために参加しています。年に1回なので定期イベントというと語弊があるかもしれませんね。 Googleを採用しなくとも、類似のクラウドプラットフォームはあります(マイクロソフトとか)。情報システム部の方であれば技術要素よりも仕事改善の手法という意味で、聞くだけでも価値はあるのではないでしょうか。
    また、すでにGoogleAppsを導入している方であれば、より便利な活用方法の情報を入手できる機会になるのでお勧めです。

Developers Summit

  • デブサミ2017から参加しました。技術者の集いという感じでしょうか。ただ紹介される技術範囲が広いので逆に薄いという印象にも。普段自分が関わってこなかった情報を入手できるという意味では良かったと思います。

POStudy

POStudy - プロダクトオーナーシップ研究会 - | Doorkeeper

  • 言語を固定しない、アジャイル開発のプロセスに関する勉強会です。私が参加したものは「その他大勢の一人」でいられたものでしたが、基本的にスクラムなどの実践やワークショップというのが多いみたいです。コミュニティの目的を考えるとそちらが正しいと思います*1

勉強会・イベント

connpass - エンジニアをつなぐIT勉強会支援プラットフォーム

情報システムセミナー、勉強会、イベント情報 | Doorkeeper

リンク

日本の技術系カンファレンスまとめ - Qiita

あとがき

基礎技術としてUMTPOSS-DBはお勧めです。私が技術的に聞きたいことをバランスよく聞かせてもらっていると思うのはJJUGです。
とりあえず、どんなことをしているのかな?というのは全てではないですが過去の資料が公開されているので、それらを読むところから始めても良いかと思います。

*1:ですが、いかんせん私はワークショップ系は得意ではないので。。。

Java EE・Jakarta EE のメモ

全般

オープンソースソフトウェアへの取り組み: 勉強会資料アーカイブス | SCSK株式会社

www.slideshare.net


Java EE 8で何が変わったのか? – Mushagaeshi.com


www.slideshare.net

GitHub - chiroito/weblogic-jee-quickstart


www.slideshare.net


GitHub - javaee/tutorial: The Java EE Tutorial

www.slideshare.net

Concurrency Utilities for Java EEをつかってみる #JavaEE - Qiita

マイクロサービス | 豆蔵デベロッパーサイト

OpenAPI

MicroProfile OpenAPI 3.0の新機能と既存機能の比較 | 豆蔵デベロッパーサイト

msa-rms-platform/platform-fw/src/main/java/io/extact/msa/rms/platform/fw/webapi/openapi/CommonOpenApiModelReader.java at 844516120363c0447fe349f384738db30870ef6a · extact-io/msa-rms-platform · GitHub

APサーバー

www.slideshare.net

https://blog.ik.am/entries/427

[Java]Payara MicroProfileでぱやぱやする - プログラマのはしくれダイアリー

認証


Java アプリケーションコンテナに依存しないユーザー認証 : まだプログラマーですが何か?


www.slideshare.net

Payara

Payara Documentation :: Payara Enterprise Documentation

とりあえずおさえておきたいGlassfishのチューニングリスト #Java - Qiita

JavaEEだけでここまで出来る!GlassFish+Eclipseで高速Webアプリ開発【環境構築編】 - 技術ブログ | 株式会社クラウディア

JavaEE7の環境構築 #glassfish - Qiita

GlassFishにリソースを追加する方法4つまとめてみた - なにか作る

glassfish へのリソース設定はリソースファイルを使うべし その1 - A Memorandum

glassfish へのリソース設定はリソースファイルを使うべし その2 - A Memorandum

glassfish へのリソース設定はリソースファイルを使うべし その3 - A Memorandum

https://donow.jp/skillup/?p=135

Loading...

Payara(GlassFish)でMariaDBのJDBC接続プールが作成できない - 行きあたりばったりエンジニアの日記

商用環境向けPayara サーバで行うべき設定 - A Memorandum

Jakarta EE

https://jakarta.ee/specifications/cdi/2.0/cdi-spec-2.0.html

その他

データベースのメモ

基本


「理論から学ぶデータベース実践入門」読んだ - $shibayu36->blog;

多分、この資料の勉強会(?)は、直接聴講したと思う。


RDBとNoSQLにみるDB近現代史 データベースに破壊的イノベーションは二度起きるか? - エンジニアHub|若手Webエンジニアのキャリアを考える!


設計

データベースオブジェクトの命名規約 - Qiita

DB スキーマ設計のガイドライン - Qiita

しょぼちむにデータモデル設計について教えてくださいの会 #syoboben - 資料一覧 - connpass

H2

毛嫌いされる今だからこそ、Java! --- JPA編 ---- - Qiita

h2 databaseをリカバリする - Qiita

H2をインメモリで動かすときの注意 - Yamkazu's Blog

GitHub - vasouv/jpa-h2-payara: Demonstration of the embedded H2 database in Payara 5

JavaEE7の環境構築 - Qiita

リファクタリング

マイクロサービスの最難関、どうするDB分割? | 日経 xTECH(クロステック)

ロック

JavaでRDBデッドロック検出 - Qiita

データベース - Webアプリケーションのデータ更新で楽観ロックを使う理由について|teratail

i am BEST : 楽観的ロックに必要な悲観的コーディング(2)

排他制御のあれこれ - Qiita

他の人にも勧められる書籍

[rakuten:book:12782740:detail]

その他

MongoDBの様なNoSQLに勢いがあるのは何故ですか?SQLと比べてどんな利点や欠点がありますか?

www.slideshare.net

テストのメモ

考え方

- JUnit 実践講座

http://jstqb.jp/dl/JSTQB-Syllabus.Advanced_TM_Version2012.J03.pdf

これだけは覚えたい、ユニットテストを書くための4つのデザイン - Qiita

実践テスト駆動開発(GOOS)読んだ - Qiita

ユースケースからテストケースへの追跡可能性

【初心者向け】テストコードの方針を考える(何をテストすべきか?どんなテストを書くべきか?) - Qiita

speakerdeck.com

speakerdeck.com

www.slideshare.net

アサーション

JUnitの新しいアサーション assertThat - A Memorandum

標準出力のテスト

標準出力に結果を出すプログラムをJUnit 4.1でテストする方法 - 結城浩のはてなブログ

検証

http://tomoyamkung.net/2013/08/26/java-junit-list-assert/

JUnitでの例外テストの書き方 - Qiita

JUnit のテストメソッドを複数スレッドで実行する - 日々常々

テスト管理ツール

www.slideshare.net

www.slideshare.net

JUnit

JUnit5で変わるテストの書き方 - きしだのHatena

Spock

www.slideshare.net

Spockのドキュメントを読んだよ - Mitsuyuki.Shiiba

JavaのユニットテストにSpockを適用する - Qiita

Spockでデータベースが絡むテストを書くためにやるべきこと その1 - Qiita

Spockの知られざる機能 - うさぎ組

Spock1.1の新機能紹介 - うさぎ組

mike、mikeなるままに…: Spockで例外のテスト

その他

Ansibleのテストで使いたい8つのServerspec | DevelopersIO

Commits · bufferings/tdd · GitHub

www.slideshare.net

リファクタリングのメモ

自分向け。
過去に作ったものは、この考えに則っていないものは多々あるが、あくまで「今」の考え。多分今後も変わり続けると思う。

継承か委譲か

継承にするか、委譲にするか迷った時の判断基準

継承しているクラスのメソッドを拡張していないんだったら委譲にする

継承を使ったらコード量は減るけど、機能追加をするときに継承元のクラスの実装とかフィールドを見ないといけない。見ること自体はどっちにしても見るべきとは思うけど、数日経ってから「なんだっけ、このthis.hogeって?、となったりする。
もっとちゃんとした理由は調べれば色々あったりするけれど、こんな理由もあるというメモ。

委譲とインターフェースで余計な操作は公開しない

実装もありつつ統一操作も持たせたい時には委譲したクラスの操作で共有したい操作のみインターフェースで定義する。 それって抽象クラスと同じで、単に委譲実装をするから手間は増えるだけに感じるけど似て非なる実装。 なお、委譲の実装はIDEの機能を使えば そこまで大変ではない。

抽象クラスを使用しないことにムキになっているなっているわけではなくて、抽象クラスは基本的にテンプレートパターンのような「拡張」を前提とするものに限定しておいた方が良いのではないかな、というのが現時点の整理。

インフラやシステム環境のAPIにはラッパーを準備する

インフラやシステム環境は、後々、横断的な対応をしたくなることはよくある。テストの時にもモック化しやすい。過去の経験では日付や時間は操作できるようにしておく方が良い。少なくとも営業経過日のテストや日替わりの時刻変更をしなくて良かったケースは皆無だった。

継承を疑う条件

methane.hatenablog.jp

継承したクラスが継承元にはないpublicなメソッドを持っている時点で、一回疑うべきである。

カプセル化

カプセルは多少緩くても良い気がする

カプセル化としてフィールドやメソッドをprivateにする作法がある。むやみに拡張をさせたくないときに、そのようにしましょう、という作法という理解。意識せず機械的に作法的にそうしているケースもある。
ただ最近、多少緩くても良い気がするように段々となってきた。勝手に使用したり、拡張されてほしくないケースもあると思うが、それを開発時にすべて想定するのは難しく、だからカプセルに閉じ込める、というのは利便性が下がるように思い始めているから。 ということで、最近のメソッドにはprivateではなくdefault(無印)を使うようにしている。一応、フィールドは更新をされると想定外の挙動になる可能性があるのでfinalで更新不可にはしている。 おそらく正しい作法としてはインターフェースと実装をペアにしてコンポジションなりを出来るようにしておけば、それが一番良いのだろうとは思う。でも、ちょっと全部にそれをするのはシンドイ。。
内部実装が漏れるのは良くない、というのは分かるけど、特にフレームワークなど基底層の場合「デバッグなどで必要としている情報をクラスが保持しているのは分かったけど、アクセッサが無くて参照できない」ということに何度か遭遇すると「更新はしないから参照はさせて・・」と言いたくなることが多々あった経験から。当然だけれど、そういう操作については、ドメイン層のクラスから直接参照するのはNGだと思うので何かしらのラッパークラスを設けて必要最低限の操作のみを開放するという作法は実施する。
インフラ層(フレームワーク含む)をドメイン層から直接使用しないようにするのは、実装による使用不可にするというよりも、動的・静的解析によって使用禁止喚起することをプロジェクト毎の基準を持って実施するのが良い塩梅では無いかな、と思う。
実際の現場はカオスなので、少しでも開放すると既得権益となってしまって済し崩しで設計思想が破壊されてしまう可能性が十分あるので、なかなかそうもいかないというのは分かるけど、とりあえず自分の開発では多少緩くするのが現在の指針。

不変の作法

フィールドの不変の作法

  • プリミティブ系:final
  • List系:Collections.unmodifiableList()
  • Map系:Collections.unmodifiableMap()

インスタンス構築

newよりもstatic factory

構築するインスタンスの確定を遅れさせることが出来るので、newよりもstatic factory。緩いカプセル化と同じく、どういう要件で拡張をしたくなるのか未来は分からない。未来に対しては寛容でいた方が、後々幸せな事が多い気がする。
実装時の注意としてはコンストラクタはprotectedにすること。そうしないとサブクラスが作成できないから。

参考

いぬごやねっと

補足として、決して new が嫌いという訳ではない。作成するインスタンスを確定させておきたい強い意志がある場合は、newの方が良いと思っている。例えば独自の実行時例外。

パラメータ、必須はstatic factory、任意はbuilder

newよりもstatic factoryにする延長で、static factoryは必須項目、builderで任意項目という整理をしておくと使用時に分かりやすい気がする。
ただし、builderパターンは、パラメータの相反については表現しづらいので、任意項目だけれどstatic factoryが全くない訳ではない。static factoryであれば、相反は表現できる。

Builderパターン

2017/8/27追記

Effective Java の Builderパターンとその拡張 - がくぞーのメモ

私の認識が間違っていたかも。

命名

パッケージ名

パッケージ名は、単数形?複数形? - Qiita

クラス名

うまくクラス名を付けるための参考情報 - Qiita

オブジェクト指向

おすすめオブジェクト指向練習方法 | サイバーエージェント 公式エンジニアブログ

リーンなコードを書こう:実践的なオブジェクト指向設計

コーディング

Null

2017/8/18 追記

  • 戻り値がNullかもしれない場合にはOptional

Java 8 "Optional" ~ これからのnullとの付き合い方 ~ - Qiita

セキュアなコーディング

www.slideshare.net

例外

段階的に理解する Java 例外処理 - Qiita

その他

DBリファクタリングの勘所と所感 - そーだいなるらくがき帳

パッケージの循環依存の対処

一般的にプログラムにおいて循環依存は良くないことと言われています*1

とはいえ、Javaは循環依存をしていてもコンパイルエラーになることはありません。
なので気が付かない間に循環依存をしてしまっているケースはあるように思います。

とりあえず、パッケージの循環依存については、チェックするやり方がありますので、それを活用するのが良いと思います。 (本記事はmavenjdepend-maven-pluginの使用例でもあります。)

blog.guildworks.jp

ところで、私もチェックを実施したところ、ちょこちょこと循環依存をしてました。

これからも同じように気がつけば循環依存をしてしまっているケースが発生すると思います。反省も含めて、どういう循環依存の実装をしてしまって、それをどういう風に対処したのか、というのを記しておきたいと思います。

コマンドパターンのような実装をしたい

デザインパターンのコマンドパターンのようなことをしたいと思って実装したら循環依存エラーになりました。

やりたかったこと

  • HogeController:共通の呼出窓口となるクラス。
  • FugaCommandHandler:Commandを実行するクラス。
  • FugaCommandManager:Commandを管理するクラス。
  • Piyo1CommandPiyo2Command:Commandクラス。

FugaCommandManagerで、Commandクラス(Piyo1CommandPiyo2Command)を登録して、 各CommandクラスはCommandInterfaceを実装して統一的な操作が出来るようにします。
また各Commandは個別機能ということでパッケージにまとめておきます。

機能としては、HogeControllerから呼び出したFugaCommandHandlerFugaCommandManagerに登録した各Commandを実行します。

この例ではクラスが少ないので同一パッケージにしても良いかもしれないのですが、各Commandについては複数のクラスを使用しているので、個別のパッケージを設けることにしました。

循環参照あり

GitHub

GitHub - vermeer-blog-circular-reference/sample1-error: 循環参照サンプル1(循環参照エラー)

パス構成

org
└─vermeer1977
   └─sample
       └─circular_reference
           │  CommandInterface.java
           │  EnvironmentItem.java
           │  FugaCommandHandler.java
           │  FugaCommandManager.java
           │  HogeController.java
           │  Main.java
           │  
           └─command
               ├─piyo1
               │      Piyo1Command.java
               │      
               └─piyo2
                       Piyo2Command.java

ぱっと見た感じだと問題なさそうな構成に思っていましたが循環依存が発生しました。

循環依存になったと思われる理由

HogeControllerにて取得した実行環境情報EnvironmentItemを各Commandで使用するのですが、それが原因だと思われます。

対処例

FugaCommandManagerを独立したパッケージに分割しました。 こうすることで、HogeControllerのパッケージとPiyo1Commandのパッケージが直接依存する関係が、仲介するパッケージを経由する状態になり循環依存のエラーがなくなりました。
発想としては、UMLの関連クラスを緩衝材として実装するイメージ、もしくはDTOを仲介させることで直接参照をしないようにするイメージです。

GitHub

GitHub - vermeer-blog-circular-reference/sample1-ok: 循環参照サンプル1(循環参照エラーの解消)

パス構成

org
└─vermeer1977
    └─sample
        └─circular_reference
            │  CommandInterface.java
            │  EnvironmentItem.java
            │  FugaCommandHandler.java
            │  HogeController.java
            │  Main.java
            │  
            └─command
                │  FugaCommandManager.java
                │  
                ├─piyo1
                │      Piyo1Command.java
                │      
                └─piyo2
                        Piyo2Command.java

副産物

分割したことで、今後、Commandクラスを増やした時に改修するクラスがパッケージレベルで整理されているので見通しも良くなった気がします。

呼出元のクラスを引数にしたい

やりたかったこと

呼出元の情報を元に呼出先で編集処理をしたい。

循環参照あり

GitHub

GitHub - vermeer-blog-circular-reference/sample2-error: 循環参照サンプル2(循環参照エラー)

パス構成

org
└─vermeer1977
    └─sample
        └─circular_reference
            │  Main.java
            │  
            ├─callee
            │      Callee.java
            │      
            └─caller
                    Caller.java

循環参照になった理由

説明の余地のないくらい、しっかりした循環依存です。

対処例

呼出先のクラスCalleeで実際に操作したい機能を満たすインターフェースを作成して、引数の型を変更しました。

修正前は呼出元クラスCallerインスタンスを呼出先クラスCalleeで参照したため循環依存になります。
修正後は呼出先クラスCalleeで必要となる振舞いを定義したインターフェースを呼出元クラスCallerに実装することで循環依存が解消されます。
参照する向きを変更したイメージです。
(ちょっと今回の例だと、何のどの概念をインターフェースとしたのか分かりにくいのが難点ですが・・)

GitHub

GitHub - vermeer-blog-circular-reference/sample2-ok: 循環参照サンプル2(循環参照エラーの解消)

パス構成

org
└─vermeer1977
    └─sample
        └─circular_reference
            │  Main.java
            │  
            ├─callee
            │      Callee.java
            │      CalleeInterface.java
            │      
            └─caller
                    Caller.java

実装の抜粋

  • Callee

calleeパッケージにCalleeクラスのメソッドの仮引数の型をCallerクラスからCalleeInterfaceに変更する

<修正前>

    public Callee(Caller caller) {
        this.caller = caller;
    }

<修正後>

    public Callee(CalleeInterface caller) {
        this.caller = caller;
    }
  • Caller

CallerCalleeInterfaceimplementsする

public class Caller implements CalleeInterface {

・・・

}

副産物

インターフェースを介することで、どのようなメソッド(振舞い)が呼出先として必要であるのか見通しが良くなりました。クラスのままだと、どのメソッドが使われているのか使用箇所の調査をしないと判別できません。

とはいえ、呼出元が呼出先の抽象概念の一部である、というのは少々宜しくないような気もします。基本的には素直に循環依存を解消するのであれば1つ目の例のように仲介するクラスを設けて、呼出元で中継するクラスを作成して呼出先に渡す、というのが良さそうに思います。可読性が落ちない程度で、仲介パッケージを作らなくても問題ないくらいの複雑度であれば、こういうやり方もありそうだ、という例にはなるように思います。

さいごに

正直なところ、始めは自分の作成した自分だけが想定される開発者なので循環参照の対応は無理しなくても良いかなと思っていました。ですが、実際、改修することで、見通しが良くなったように思います。

むかーしの話ですが、大規模SIer案件ではコードにインターフェースが使用されているものは、ほとんど*2ありませんでした。そういうこともあって「フレームワークなど抽象度の高い機能を実装しないのであればインターフェースを使うことはないだろうな」と思っていましたが、実際に自分で手を動かしてみると、そんなことは無いな、と思うようになりました。本記事もその一例のように思います。

*1:言語によってはコンパイルエラーになったりするみたいです。

*2:というか全く