しゃべぶろ

気になった技術の備忘録を残します。

【TypeScript】【React】react-scripts-tsは何をしているのか?

概要

TypeScriptでReactを開発する時にcreate-react-appを使用してプロジェクトを作成すると、以下のようなpackage.jsonが作成される。

{
  /** 一部省略 */
  "scripts": {
    "start": "react-scripts-ts start",
    "build": "react-scripts-ts build",
    "test": "react-scripts-ts test --env=jsdom",
    "eject": "react-scripts-ts eject"
  },
}

毎回何となくraect-script-ts startをしてReact Appを起動させているので、今回調べた上で理解して動かすようにしたい。

恐らくwebpackts-loaderなどが設定されて良い感じに動くようになっているはず。。。

解剖してみる

まずnpm run ejectを実行して、react-script-tsを展開する。

実行すると以下のようなログが出力される。

ログを展開する

ts-react-practice-simple-app shabe$ npm run eject

> ts-react-practice-simple-app@0.1.0 eject /Users/shabe/Desktop/MyApp/practice/ts-react-practice-simple-app
> react-scripts-ts eject

? Are you sure you want to eject? This action is permanent. Yes
Ejecting...

Copying files into /Users/shabe/Desktop/MyApp/practice/ts-react-practice-simple-app
  Adding /config/env.js to the project
  Adding /config/paths.js to the project
  Adding /config/polyfills.js to the project
  Adding /config/webpack.config.dev.js to the project
  Adding /config/webpack.config.prod.js to the project
  Adding /config/webpackDevServer.config.js to the project
  Adding /config/jest/cssTransform.js to the project
  Adding /config/jest/fileTransform.js to the project
  Adding /config/jest/typescriptTransform.js to the project
  Adding /scripts/build.js to the project
  Adding /scripts/start.js to the project
  Adding /scripts/test.js to the project

Updating the dependencies
  Removing react-scripts-ts from dependencies
  Adding autoprefixer to dependencies
  Adding babel-jest to dependencies
  Adding babel-loader to dependencies
  Adding babel-preset-react-app to dependencies
  Adding case-sensitive-paths-webpack-plugin to dependencies
  Adding chalk to dependencies
  Adding css-loader to dependencies
  Adding dotenv to dependencies
  Adding dotenv-expand to dependencies
  Adding extract-text-webpack-plugin to dependencies
  Adding file-loader to dependencies
  Adding fork-ts-checker-webpack-plugin to dependencies
  Adding fs-extra to dependencies
  Adding html-webpack-plugin to dependencies
  Adding jest to dependencies
  Adding object-assign to dependencies
  Adding postcss-flexbugs-fixes to dependencies
  Adding postcss-loader to dependencies
  Adding promise to dependencies
  Adding raf to dependencies
  Adding react-dev-utils to dependencies
  Adding resolve to dependencies
  Adding source-map-loader to dependencies
  Adding style-loader to dependencies
  Adding sw-precache-webpack-plugin to dependencies
  Adding ts-jest to dependencies
  Adding ts-loader to dependencies
  Adding tsconfig-paths-webpack-plugin to dependencies
  Adding tslint to dependencies
  Adding tslint-config-prettier to dependencies
  Adding tslint-react to dependencies
  Adding uglifyjs-webpack-plugin to dependencies
  Adding url-loader to dependencies
  Adding webpack to dependencies
  Adding webpack-dev-server to dependencies
  Adding webpack-manifest-plugin to dependencies
  Adding whatwg-fetch to dependencies

Updating the scripts
  Replacing "react-scripts-ts start" with "node scripts/start.js"
  Replacing "react-scripts-ts build" with "node scripts/build.js"
  Replacing "react-scripts-ts test" with "node scripts/test.js"

Configuring package.json
  Adding Jest configuration
  Adding Babel preset

Running npm install...
up to date in 4.623s
Ejected successfully!

Please consider sharing why you ejected in this survey:
  http://goo.gl/forms/Bi6CZjk1EqsdelXk1

  • ログ見るとconfigscripts系のファイルが追加されている。
  • package.jsonに依存関係が追加されている。
{
"dependencies": {
    /** 一部省略 */
    "babel-jest": "20.0.3",
    "babel-loader": "7.1.2",
    "babel-preset-react-app": "^3.1.2",
    "ts-loader": "^2.3.7",
    "tslint": "^5.7.0",
    "tslint-config-prettier": "^1.10.0",
    "tslint-react": "^3.2.0",
    "webpack": "3.8.1",
    "webpack-dev-server": "2.11.3",
    "webpack-manifest-plugin": "1.3.2",
  },
  "scripts": {
    "start": "node scripts/start.js",
    "build": "node scripts/build.js",
    "test": "node scripts/test.js --env=jsdom"
  },
  "babel": {
    "presets": [
      "react-app"
    ]
  }
}
  • startコマンドを実行すると、scripts/start.jsを実行するようになっている。

scripts/start.js

簡単に説明するとconfig配下のwebpack.config.dev.jsなどの設定ファイルを読み込んでwebpack-dev-serverを起動するよう実装されている。

詳しくは中身を以下のソースを参照のこと。

github.com

config/webpack.config.dev.js

webpackの設定ファイルである。自分が知っているwebpack.config.jsと大分違う(設定が複雑で分からない...)

まぁ、ts-loadertsconfig周りだけ軽く見てみる。

ts-loader

  /** 一部省略 */
  {
    test: /\.(ts|tsx)$/,
    include: paths.appSrc,
    use: [
      {
        loader: require.resolve('ts-loader'),
        options: {
          // disable type checker - we will use it in fork plugin
          transpileOnly: true,
        },
      },
    ],
  },
  • testと書いているがこれはts-loaderが対象にするファイル拡張子のこと。
  • includetestで指定したファイルの場所を限定している、この例ではsrc配下のファイルが対象となる。
  • loaderで使用するローダであるts-loaderを指定している。

    • ローダーは他にもfile-loadercss-loaderなどがある。
  • optionstranspileOnlyはトランスパイルのみで型チェックをしなくなる。

tsconfig

// Perform type checking and linting in a separate process to speed up compilation
new ForkTsCheckerWebpackPlugin({
  async: false,
  watch: paths.appSrc,
  tsconfig: paths.appTsConfig,
  tslint: paths.appTsLint,
}),
  • ForkTsCheckerWebpackPluginを使う事で、別プロセスで型チェックや静的チェックを実行するのでスピードがあがるらしい。

実際のtsconfigファイルは以下になる。

/** 一部省略 */
"compilerOptions": {
    "baseUrl": ".",
    "outDir": "build/dist",
    "module": "esnext",
    "target": "es5",
    "lib": ["es6", "dom"],
    "sourceMap": true,
    "allowJs": true,
    "jsx": "react",
    "moduleResolution": "node",
    "rootDir": "src",
    "forceConsistentCasingInFileNames": true,
    "noImplicitReturns": true,
    "noImplicitThis": true,
    "noImplicitAny": true,
    "importHelpers": true,
    "strictNullChecks": true,
    "suppressImplicitAnyIndexErrors": true,
    "noUnusedLocals": true
  },
  • moduleesnextはESモジュールの最新版と考えれば良さそう。
  • forceConsistentCasingInFileNamesはファイル名の大文字小文字のチェックを行う。
  • importHelperstslibのヘルパーをimportするかどうか。
  • 他は後々覚えていこう。

まとめ

react-scripts-tswebpackts-loaderなどの煩雑な設定を簡単にしてくれる物である。 但し、react-scripts-tsの状態では各種設定を弄る事は出来ないので、ejectする必要がある。 設定に疎いのであれば、react-scripts-tsに頼ってしまって問題ないのかなと思った。

参考

JJUG ナイトセミナー 3/28 参加してきた

概要

3/28日実施された、JJUGナイトセミナーに参加してきた。
今回のテーマは「Java 12リリース記念」ということで、
Java12の新機能および、ZGCの仕組みについて聞いてきた。

Java12の言語やAPIに関する変更 by きしだなおきさん

  • JEP 325 Switch式(プレビュー)
    • switchステートメントが式として使えるようになる。
    • caseに複数の値を指定出来るようになった。
    • プレビュー機能なのでjavac時に--enable-previewをつける必要がある。
      • 仕様変更が入りそうなのであまり取り入れない方が良い。
      • アロー構文を使うとbreak不要でswitchを使える。
  • Collectors.teeing
    • ふたつのCollectorの結果をまとめられる。
    • 3つ以上のCollerctorを使いたい場合は、teeingの中でteeingを呼べば実現出来る。
  • String.transform
    • 値→関数の順で書けるようになっている??
  • FIles.mismatch
    • ファイル違う箇所を返してくれる。
  • InputStream.skipNBytes
    • スキップするByte数を超えてしまうとExceptionを返却する。
    • skipはExceptionを返却しない。
  • Java13に入りそうなこと
    • Switch式の正式化
      • 13でpreviewが外れるかも。
      • ただし、break-withキーワードになる可能性がある。
    • JPackage
  • Default CDS Archives
    • クラスデータをあらかじめ作成して共有するという仕組み
    • JDK12からはbin/server/classes.jsaがあらかじめ含まれている。
    • Javaの起動が少し速くなったいるはず。
  • Java Flight Recorderツール
    • Javaのプロセスに入って、Javaのログを取得してくれる。

The Z Garbage Collector by Devid Buckさん

  • JDK11以降の新しいGC
    • どんなに大きいデータ量でもLow-Latencyで動作する
    • Compactionをすることが断片化を抑えることが出来る。
    • Single Generationなので1つの世代のみ管理する。
    • ヒープと生存データのサイズが停止時間に影響しない。
    • CMSやG1でStop The World起きてしまう処理が、ZGCだと一部しか起きない。
  • ZGCの仕組み
    • 最初に4TBのメモリ空間を確保する?
    • Coloerd Pointers(タグを含むポインター)
      • 利用されていないビットにメタデータを格納する
      • 32bitのJVMはサポート対象外
  • 利用方法
    • -XX:+UseZGCをつける
    • 開発中なので-XX:+UnlockExperimentalVMOptionsをつける必要がある。

参加してみて

Java12にすることで今までより、少し便利に書けるようになるという印象を受けた。
ZGCに関してはすごいの一言、ただマシンのスペックにも依存するので、適切なGCを選択するのが良いのかな。

JJUG ナイトセミナー 2/27 参加してきた

概要

2/27日実施された、JJUGナイトセミナーに参加してきた。
今回のテーマは「JVM言語を作ろう! GraalVMで遊ぼう!」ということで、
Javaというよりは、JVMや言語自体の仕組みについての発表だった。

JVM言語の動き方・動かし方 by 宮川 拓さん

  • 翻訳系
  • 実行系
  • OSの仕事
    • プログラムを使う仮想アドレス空間を確保する。
    • レジスタの元の値を退避しておく領域をスタック領域と呼ぶ。
    • スレッドごとにスタック領域を確保する。
    • 呼び出しの作業領域としてフレームを確保する。
    • 実行中のプログラムのコールで動的にメモリを確保する。
  • CPUの仕事
  • コンピューター、JVM、WebAssembly
  • JVM言語処理系
    • JavaScala、Kotlin、Groovyなど
    • JVMGCを任せられ、マルチスレッドの処理系で実用的に動くGCはとても難しい。
    • リフレクションのおかげでJava APIを使うことができる。

GraalVMで使われている、他言語をJVM上に実装する仕組みを学ぼう by 阪田 浩一さん


この辺りから業務対応が入り、セッション聞けなかった...

TruffleでPHPぽい言語を実装したら爆速だった by きしだ なおきさん

がっつり業務対応していた...

参加してみて

今回のセミナーは結構難しかったが、自分の知識が広がった気がする。

【React】React + Redux 触ってみた

概要

Reactを学ぶべく、こちらの参考書を使って学習したので、
復習を兼ねてReactとReduxについて学んだことを記載する。

React入門 React・Reduxの導入からサーバサイドレンダリングによるUXの向上まで (NEXT ONE)

React入門 React・Reduxの導入からサーバサイドレンダリングによるUXの向上まで (NEXT ONE)

Reactとは?

  • 画面表示を担当するフレームワークのこと。
  • 画面をコンポーネント(=部品)単位に分けて開発する。
  • コンポーントは基本的にJSXで記述される。
    • JSX(Javascript eXtension)はJS内でHTML構文を使えるようにしたもの。
    • 当然そのままではブラウザで表示できないので、トランスパイラというツールを使って変換される。
  • VDOM(Virtual DOM)を用いて差分のみ画面表示するので速い(らしい。
    • 今回学習した中では、VDOMの良さはよく分からなかった。

Reduxとは?

  • アプリケーションの状態を管理してくれるライブラリのこと。
  • 状態を更新をさせるにあはイベントを発生させる必要がある。
  • イベントを発生させる以外に更新方法がないので、シンプルな更新フローとなる。
  • FluxというFacebook公式ライブラリもあるため、Reduxを無理に使う必要はないかも。
    • FluxとReduxの違いはよく分からなかった。

React + Redux

表示を担当するReactと状態を管理するReduxを組み合わせる。
ここは初見殺しかと思うぐらい訳が分からなかった。
特にReactをReduxに接続する部分を理解するのに時間が掛かった。

概念

概要

自分の理解はこんな感じです。

Reactが表示している画面をユーザーが操作し、その時に発生したイベントでReduxが状態を更新、Reactは更新された状態を見て画面表示を変更する。

個人的には以下2つのポイントを理解すれば良いかと思う。

  • ReactはどのようにReduxにイベントを渡しているか。
  • Reactは更新した状態をどのように参照しているのか?


上記を実現するためにはreact-reduxというライブラリが必要になってくる。

登場人物
  • Action
    • Redux側の人物
    • 上で説明していたイベントに該当する。
    • ReactはこのActionを発行する。
  • Reducer
    • Redux側の人物
    • Actionを元に状態を更新する。
  • Store
    • Redux側の人物
    • 状態を管理している、Reudcerのみ更新可能。
  • ConnectedComponent
    • ReactとReduxを繋げる人物
    • react-reduxライブラリのconnect関数を用いて繋げる。
概念図

図で説明してみる、こちらの記事から概念図を拝借する。
qiita.com

f:id:shabe:20190106202722p:plain

ReactはどのようにReduxにイベントを渡しているか。

  • これはConnectedComponentがRedux側に渡している。
    • ConnectedComponentはdispatchという特殊な関数を保持している。
    • dispatchの引数にActionを与えることで、Reducerを呼び出すことが出来る。
  • その後Reducerでは渡ってきた引数を元に、Storeの状態を更新していく。
    • この時に前の状態をみて差分更新するのが大事。
    • 差分更新することで、React側は更新された箇所のみ描画をすることが出来る。

Reactは更新した状態をどのように参照しているのか?

  • mapStateToPropsという関数を使うことで、React側に値を渡している。
    • Store側の状態(State)をReact側の変数(Props)にマッピングすることが出来る。
    • この関数はConnectedComponent内で定義される。

感想

基本概念については大分理解してきた。
特に今回使った参考書の10章目がかなり理解を促進してくれた。

あとはComponentやStoreの設計方法などを知っていきたい。
まぁ、実践あるのみかなー、実務で使いたいなー!

JJUG Fall 2018 参加してきた

概要

JJUG Fall 2018に参加してきたので、そのレポート記載する。
てか初めて参加したのだが、人の多さにびっくりした。
ランチセッションでお弁当頂きました、有難うございました。

Java + コンテナ向けパフォーマンス分析手法の紹介と活用事例@米司伊織 さん

  • 測定ツール
    • AppDynamics
    • FlightRecorder
    • perfect-tool
      • アラウンドでタイムを測ってくれる
      • Linux標準
      • 多機能、低オーバーヘッド
    • Netflix Vector
    • Avalanche
      • ワークスアプリーケションズのOSS

思考停止しないアーキテクチャ設計@川島義隆さん

  • Software Architecture
    • Martin Flowler「重要かつ変更な意思決定である」
  • Architectural Decision Records
    • ソースリポジトリと同じところに、1つの意思決定単位に1つパターン記述に似た感じで記録する。
  • The Patterns of Stop Thinking
    • 限界意識の思考停止
    • 無意識の思考停止
    • 特別意識の思考停止
  • 検索エンジンの手法
    • リザルトキャッシュ
      • 結果を事前にキャッシュしようぜ
  • デグラデーション
    • 1機能は停止させても、メイン機能は落とさない
  • データベースでルールを定義
    • テーブルの柔軟性が低くなる
    • イレギュラーなデータが入った時良くない。
    • Application側でinterfaceを用意するぐらいで良いかなと
  • 参考文献
    • Software Architecture in Practice(3rd)
    • Design It
    • Software Architecture patterns

今こそStream API入門@櫻庭 祐一さん

  • Streamって何?
    • イテレータのこと、簡単に言うとループ
      • 外部イテレータ
        • 繰り返しの制御を自分で記述
        • for文、拡張for文
        • 繰り返し制御 + 処理を記載する。
      • 内部イテレータ
        • 繰り返しはライブラリにお任せ
        • Stream API
        • 処理のみを記載すれば良い。
    • 中間処理と終端処理に分けて考える。
      • 中間操作
        • 取捨選択する
          • filter
          • dropWhile 1引数 返り値 boolean
          • takeWhile
        • データの変換
          • map 1引数 返り値あり
            • 型を変換するときに使う。
            • flatmap 1引数 返り値Stream
              • 2次元配列を1次元配列にしたいときに使う。
              • 2次元配列をなめすで考える
      • 終端操作
        • 探す
          • findFirst/findAny ラムダ式なし
          • anyMatch/allMatch/nonMatch 1引数 返り値 boolean
        • まとめる
          • toList ラムダ式なし
          • groupingBy 1引数 返り値あり(Map)
        • 逐次処理
          • forEach 1引数 返り値なし
    • データがなければ空を返却するのでnull安全
    • 例外処理はbibherというの使う、にVにExceptionを入れる。
  • ラムダ式
    • 関数とクラスとの間
    • 関数のように記述ができて、クラスのように振舞う
    • 引数と返り値だけを決めた処理の記述法
    • 1行で書くならreturn文を省略可能
    • 1引数なら()を省略可能。
  • よく使われるラムダ式
    • 1引数 返り値あり Function
    • 1引数 返り値boolean Predicator
    • 1引数 返り値なし Consumer
    • 引数なし 返り値あり Supplier

Javaを活用したマイクロサービスのためのKubernetes@寺田佳央さん

  • Java9以降
    • カスタムJREが作成できるようになった
    • jlinkコマンドを使って行う
    • コンテナで動かすためには、小さい環境を作成するのが重要
  • Java11
    • xmlやCORBAのライブラリが抜けている。
    • xmlを扱うようなアプリケーションは動かなくなる。
    • 12以降は起動時間の短縮などかなり改善がされていく。
  • Docker
    • latest tagは使用してはいけない。
    • いつビルドしたものか分からないのでバージョンを指定した方が良い。
    • ビルドされたバージョンを追うのは大変。
    • 出来るだけ小さいサイズのイメージを作りましょう。
    • openjdkだけでも数100MB異なる。
    • Docker Hubのイメージは脆弱性を含んでいることがある。
      • なのでセキュリティをチェックする必要がある。
  • Kubernetes
    • 全ての機能をk8sを利用する必要はない。
    • 大規模k8sクラスタを構築しない。
      • アプリケーションがマイクロサービス化してるのに
      • インフラがモノシリックだと意味がないのでは?
      • クラスタが壊れたときに全サービスが消えてしまう。
    • LabelとServiceは重要なので覚えてほしい。
    • Persistence Volumeはおすすめしない。
      • スケールさせるのが結構難しい。
      • SDKを使用したファイル保存・変更をおすすめする。
      • アプリケーションに処理を依存させた方がいい。
    • DBはPodの中で扱うより、別サーバーで立てた方が良い。
      • Pod内だと管理がしにくい。
    • Version Upは慎重にやってほしい。
      • 新しいバージョンにした場合は古い設定が動かない可能性が多い。
      • yamlを修正したり、コマンド引数を変更したり。
      • 新しいクラスタ環境を作成してから、カナリアリリースした方が良い。
    • 問題は発生した時は?
      • kubectl describe pod
      • kubectl logs POD_NAME
      • kubectl exec -it POD_NAME /bin/sh
      • kubectl get events -w
      • Deploy Ubuntu pod in same NameSpace
    • Virutal Kubelet Serveless
      • サーバーレス環境でKubeを実行出来るようになった。

秒間200,000req/secをさばく広告入札システム@磯田浩靖、山崎良祐さん

  • チューニング
    • まずはホットスポットを見つける必要がある。
      • ツールやプロファイラを使う必要がある。
    • perfとFlameGraphを利用
      • FlameGragphはNetflixOSS
      • perfの結果を可視化するツール
  • FlameGragph
    • 縦軸はメソッドの実行数がわかる。
    • 横軸はメソッドの処理時間の割合があわかる。
    • 処理名で検索することができる。
    • 下がJavaのプロセス、下から追っていく。
    • まずは全体に対して幅を取っている箇所をチューニングする。
    • 改修前後で幅が異なるとデグレしている可能性がある。
  • Java以外のチューニング
    • レイテンシが劣化したからといってJVMが悪い訳ではない。
    • Looking Glassというツールでネットワークの経路をがわかる。
    • tcpdumpでnginxのレスポンンスタイムを計測する。
  • Frame Scope
    • Frame Graphを時間単位でスライスして可視化するツール
    • 濃い色になるセルはperfのバグなので無視
    • logbackがファイルをローテートするために、CPUが処理を待ってしまう。
    • ログを作成しているときはロックされてしまう。
    • CPU使用率100%となるが意外に動いていない時がある。

【Docker】コンテナと仮想マシンについて

概要

そろそろ仕事でDocker使う機会がありそうなので勉強しとく。
全部理解するのは時間かかるので概要だけ理解しよう。

仮想マシン

f:id:shabe:20181202121406p:plain:w500

  • VirtualboxやVMawreがこれに該当する。
  • アプリケーションを動かすには、ゲストOSの状態を考慮する必要がある。

コンテナ概念

f:id:shabe:20181202122113p:plain:w500

  • ゲストOS不要、これで考慮する手間が無くなった。
  • コンテナはホストOSのカーネルを使用してアプリケーションを動かす。
  • ゲストOSが担当していた制御はDocker(Docker Engine)が実施してくれる。
  • コンテナはホストOS上のプロセスとして扱われる。

何が良いの?

  • ゲストOSを挟まずにホストOSのカーネルを使うので処理が速い。
  • ゲストOSを考慮せずにアプリケーションの開発を出来るので、開発スピードが速くなる。

【ドメイン駆動設計】サンプル(iddd_agilepm)を読解く その3

概要

前回はアプリケーションサービスについて触れたので、
今回はドメインモデルについて触れてみる。
hghyk023.hatenablog.jp

ドメインモデル

業務知識(ドメイン)を表現した概念のこと(?)
ドメイン駆動設計では、ドメインモデルをエンティティ値オブジェクトドメインサービスで表現していく。
業務知識を適切に表現出来ていないドメインモデルは、ドメインモデル貧血症と呼ばれる。

ドメインモデル貧血症とは業務知識がドメインモデル以外に点在している事である。
例えば、前回説明したアプリケーションサービスが業務知識を保持しているとそれに該当する。
陥ると各所に点在する業務知識を考慮する必要があり、改修がやりづらくなってしまう。
そこで、業務知識を1箇所に纏めて改修に強くしようというのがドメイン駆動設計の考え方である。

iddd_agilepmでのドメインモデルの使い方を見てみる。

domain/modelパッケージ

  • EntityとValueObjectという抽象クラスが存在する。
  • *ed系はドメインイベントとなり、DomainEventというInterfaceを実装している。
  • RepositoryはInterfaceとして定義、DIP(依存関係逆転の法則)が適用されている。
  • productパッケージ配下にbacklogitemやreleaseパッケージが存在する。

もう少し詳しく見ていく。

エンティティ

抽象クラス
public abstract class Entity extends AssertionConcern {
    private int concurrencyVersion;
    public Entity() {
        super();
        this.setConcurrencyVersion(0);
    }
    public int concurrencyVersion() {
        return this.concurrencyVersion;
    }
    private void setConcurrencyVersion(int aConcurrencyVersion) {
        this.concurrencyVersion = aConcurrencyVersion;
    }
}
  • assertionメソッドを纏めたAssertionConcernクラスを継承している。
  • 実装クラス内ではこのメソッドを使って引数チェックをしている。
  • concurrencyVersionは使ってない??
実装クラス
public class Product extends Entity {
    /** 省略 */
    public Product(/** 省略 */) {
        /** 省略 */
        DomainEventPublisher
            .instance()
            .publish(new ProductCreated(/** 省略 */));
    }

    public void changeProductOwner(ProductOwner aProductOwner) {
        if (!this.productOwnerId().equals(aProductOwner.productOwnerId())) {
            this.setProductOwnerId(aProductOwner.productOwnerId());
        }
    }
}
  • Productはアプリケーションサービスから作成される。
  • 作成するとドメインイベントが発行され、サブスクライバーに通知される。
  • changeProductOwnerメソッドで自身の状態を変更している。

値オブジェクト

抽象クラス

AssertionConcernクラスを継承しているだけ特記事項なし。

実装クラス
public final class ProductDiscussion extends ValueObject {

    private DiscussionAvailability availability;
    private DiscussionDescriptor descriptor;

    public static ProductDiscussion fromAvailability(
            DiscussionAvailability anAvailability) {

        if (anAvailability.isReady()) {
            throw new IllegalArgumentException("Cannot be created ready.");
        }

        DiscussionDescriptor descriptor =
                new DiscussionDescriptor(DiscussionDescriptor.UNDEFINED_ID);

        return new ProductDiscussion(descriptor, anAvailability);
    }

    public ProductDiscussion(
            DiscussionDescriptor aDescriptor,
            DiscussionAvailability anAvailability) {

        super();

        this.setAvailability(anAvailability);
        this.setDescriptor(aDescriptor);
    }
}
  • エンティティとは異なり、final classとなっている。
  • 値オブジェクトは自身の状態を変えることは出来ない。
  • fromAvailabilityメソッドでは、自身を作り変えている。

ドメインサービス

見当たらない。どれが該当するのだろう??

まとめ

割と浅くしか確認してないので、もう少し詳しく調べたい。
また、集約についても取り上げたい。

参考

codezine.jp