読書会(APIデザインの極意)第3回議事録

[ 戻る ]


=====================================================================================
Java読書会BOF 「APIデザインの極意 Java/NetBeansアーキテクト探究ノート」を読む会 第3回
=====================================================================================

.. csv-table:: 開催概要

   "日時", "2014年12月27日 10:00 * 17:00"
   "場所", "川崎市教育文化会館 第3会議室"
   "出席者(敬称略)", "高橋(徹)、高橋(智)、門脇、根本、岩室、松永、平山、今井、村山、小棚木、中澤(書記)"

議事
====

5.6 オブジェクトの作成者に多くの権利を与える
----------------------------------------
* "パッケージプライベート"がカタカナ表記なのは、キーワードでないためではないか
* Javaのメモリにアクセスできるか?
  * ヒープダンプの解析は可能
  * GCでEden・Survivor・Old領域間を移動したり、compactionしたりするため、ヒープダンプの差分解析は難しい
  * JVMTIを使えばよい
  * JNIの部分は、Javaのセキュリティ管理の範疇外

NetBeansファイルシステムAPI
----------------------------------------
* JavaBeans仕様でデフォルトコンストラクタが必須なため、immutableにできない
* PropertyVetoException: プロパティに対して受け入れられない値を指定された場合にスローする

Mutexと特権アクセス
----------------------------------------
* ここでは何がしたいのか?
* 正確なことはNetBeansのコードを見ないとわからないが、おそらくは
  * API使用者側では、単にロック取得・開放だけをさせたい(Mutex)
  * API作成者側では、より細かい操作をさせたい(Mutex.Privileged)
  * API使用者にはMutexを渡して、使用できる操作を限定させる
* Javaでのロック機構は文法レベルのもの(synchronized)や、ライブラリ提供のもの(セマフォなど?)がある

5.7 深い階層を公開しない
----------------------------------------
* abstractクラスは、abstractメソッドを実装すればいいだけであるのは楽だが、結局、それがsuperクラスでどのように利用しているかを把握しなければいけないことがある
  * AbstractMap#EntrySet?: 実装方法によっては、パフォーマンスが悪化することがあるため、それを理解して実装する必要あり
* サブクラス化は内蔵をさらすようなもの、意図していないメソッドがサブクラスで使われることがある
* クラスの不変条件は守らなければならない
  * 結局superクラスのことを知らないと、不変条件がわからないことがある
  * Object#equalsをオーバーライドするときは、hashCodeも要オーバーライド
* Mapのinterfaceが大きすぎる: 使いたいのはgetとputなのに、他のメソッドの実装も必要
  * interfaceを分割しておいてあれば、多少楽だったはず
  * ScalaのStructural Type: interfaceが一致しなくても、定められたシグネチャのメソッドが定義されているオブジェクトなら引数として受け取れる
  * 動的なチェックでよければ、Javaでもリフレクションでがんばれなくもない


第6章 実装ではなく、インタフェースに対してコーディングする
----------------------------------------
* 「コードをインタフェースと実装に分離して...」はGOLFのデザインパターン本で言われている言葉で、この本は基本的にC++をベースに書かれている
* 公開すべきAPIとそれ以外を、パッケージレベルで分けるとわかりやすい
* 公開したくないクラスは非publicにしたいが、フレンドレベルのアクセス制御をしたいこともある(パッケージをまたぐアクセス)
* C/C++では、ヘッダファイルを公開することがAPI公開に相当するが、公開用と非公開用に分けるような運用方法がある

NetBeansオープンAPIの作成
----------------------------------------

6.1 メソッドやフィールドの削除
----------------------------------------

6.2 クラスやインタフェースの削除や追加
----------------------------------------

6.3 既存の階層へのインタフェースやクラスの追加
----------------------------------------
* Hello型は、HelloClassのClassが型に翻訳された?

6.4 メソッドやフィールドの追加
----------------------------------------

新たなメソッドと新たな型の追加
----------------------------------------
* C++なら、新しい型の引数を受け取る新メソッドを追加して、それをデフォルト引数にしておけば、サブクラスの既存メソッドのシグネチャと重複することなく、加えて新メソッドを引数なしで呼べる?
  * サブクラスに元々引数なしで同名のメソッドがあるとコンパイルエラーになる?

6.5 JavaインタフェースとJavaクラスの比較
----------------------------------------

6.6 弱さの中に強さがある
----------------------------------------
* String.class.isAssignableFrom: Stringフィールドに代入可能なクラスかを判定している
* 中段あたり: 「メモリへロードすることを避ける...」とあるが、問題は頻繁にアクセスされることだったのでは? => よく意味がわからない

6.7 メソッド追加愛好者の天国
----------------------------------------
* コード例: classがfinalなので、サブクラスのことを気にせず、メソッド追加が可能
* 言いたいことは、「パフォーマンス向上のために、API作成者がisInstanceOfメソッドを追加するだけよい」「既存のサブクラス実装者は修正不要である」ということ

6.8 抽象クラスは役立つのか
----------------------------------------
* p.101のコード例のインデントが誤っている(if)

6.9 パラメータの増加に備える
----------------------------------------
* p.102の下段コード例: 「...残りはフレンドコード用に隠蔽されている」とあるため、コードが省略されている

6.10 インタフェースとクラス
----------------------------------------


第7章 モジュール方式アーキテクチャの使用
----------------------------------------
* スパゲッティコードは作成者も理解できないだろう
* プロジェクトJigsaw: 必要な最小パッケージの組み合わせであるプロファイルを定義する => Java9に導入予定(2016年)
  * やりたいこと: 組み込み用(IOTなど)に、不要なパッケージを除去できるようにしたい
  * NetBeansでは、compactプロファイルという設定が利用可能で、アクセス不可能なクラスを参照するとエラー表示してくれる
  * 標準のパッケージはスパゲッティになっていて、プロファイルの分割が難しい?

NetBeansでのスパゲッティ設計
----------------------------------------

7.1 モジュール方式設計の種類
----------------------------------------
* 複数ベンダが作成したライブラリをそれぞれ参照するには、それぞれをロードしたクラスローダを辿ってアクセスするしかない

NetBeansランタイムコンテナを通しての間接依存性
----------------------------------------
* 「org.w3c.dom.v2を追加するか...」の箇所: 必要なモジュールバージョンを記載しおくと、そのモジュールがロードされていない時にエラーがでる?

7.2 コンポーネント間検索とコミュニケーション
----------------------------------------
* newInstanceは可変長引数

ジェネリックレジストリ
----------------------------------------
* Object[]で定義しているのは、Mapのkeyに対して初期化されていないのか、それともnullがputさたのかを区別するため?
* Bean定義に実装クラス名を書くということは、実装の部分が公開APIとなってしまう

最も純粋なコンポーネント注入
----------------------------------------
* 「Luxと言えば電気掃除機...」: ElectroLuxヨーロッパの家電メーカーのこと
* コード例: @Servive("ui") => uiという名称は短すぎて、重複しそう
* @Serviveがついているクラスをどのように収集しているのか?
  * リフレクションを利用している?
  * クラスのロードは必要?

注入技術
----------------------------------------
* 最近のJavaOneではモジュラーという単語がよくでていた => バズワードか

コンポーネント注入、もしくは、サービスロケータ
----------------------------------------

SpringとLookup
----------------------------------------

7.3 拡張ポイントの作成
----------------------------------------

7.4 循環依存の必要性
----------------------------------------

7.5 どこにでもLookup
----------------------------------------
* コード例: Boolaenを使用しているのは、そもそもisCatで判断できない場合にnullを返したいためか?
* テレインタフェース: p.83に説明あり

7.6 Lookupの乱用
----------------------------------------
* 累積ファクトリパターン: 見た目はBuilderパターンに似ている
  * ビルダと違い、毎回、インスタンス生成が必要
  * ビルダの生成と、最後のインスタンス生成の手間が不要


.. note:: 次回は、p.137の第8章から。


[ 戻る ]