masuda220 / business-logic-patterns Goto Github PK
View Code? Open in Web Editor NEWexperiments for business logic patterns
experiments for business logic patterns
https://keisan.casio.jp/exec/system/1245199831
この画面を参考に、
のみの簡易版のサービスを実装する
端数計算
Quantity型のオブジェクトの単位がBoxUnitの時、引数が、PieceUnitの足し算・引き算は、例外にしましょう。
ただしく変換できない可能性があるので、安全のため自動変換はしないで、例外をthrowする。
いったんは、制限付きの単純な仕様にしておく。
実際には、PieceUnitからBoxUnitへの変換も必要なので、その実現方法は、別途検討する。
(変換用の型を作ったほうが良いかも)
という方向で、以下の修正をする。
Unitの自動変換は、魅力的な機能ですが、ビジネスルールが暗黙化するイヤな臭いも感じています。
単位の変化のあるべき仕様について、別isseeで議論したいと思います。
いったんは、より型チェックを厳しくする方向で、次の変更を行う
契約による設計のスタイルにこだわってみたいと思います。
「nullを渡さない」という契約が守られる前提で、null検査のコードは削除をお願いします。
メソッド名、引数の型名/変数名、返す型名での説明力を改善のために、メソッドコメントは、書かないという方針でお願いします。
(設計ガイドラインを追加しました)
DueDate型は、基本型というよりは、基本型を組み合わせた業務モデルの要素と思われる。
typeからmodelに移動する。
isEqualTo(Amount) 以外に、以下の比較演算を追加する
isGreaterThan
isGreaterOrEqualTo
isLessThan
isLessOrEqualTo
単位の変換の仕様についての検討。
基本コンセプトの選択肢は三つ
実際に使うシーンを想定しつつ、考え方を検討したい。
<参考>
Javaのプリミティブな数値型は、short->int->long->double というより大きな数値を扱える型への変換は、暗黙の変換が行う。
ただし、long->doubleの変換では、厳密には、値が変わってしまう(もとに戻せない)
暗黙の型変換は、便利ではあるが、「暗黙」のルールであることがデメリット。
ドメインロジックを表現する型の設計では、暗黙の変換は、基本的にさけるべきではないか?
#61 で実装したゲートの状態遷移を扱うサンプルで、State が、期待するイベントの知識を持つようにする。
以下の二つのメソッドを追加する
補足:
実装:
実装は、Transitions に上記の二つのメソッドを持たせて、責任を委譲する。
開始時刻と終了時刻を表現する型
( #23 のクラス群を使って実現する)
想定ユースケース
https://keisan.casio.jp/exec/system/1245199831
この給与計算機能を実現するための部品として試作する
コードだけで説明しきれない個所がでてきている。
(桁数の扱いの考え方など)
現時点の設計ガイドラインは、コメントを書かない。
ある程度は、書いたほうがよさそうだが、できるだけ書かないほうが望ましい。
アイデア
ContainType列挙型は、DateRange#contains() の事後条件(メソッドが返す値についての契約)にあたる。
契約を表明する手段なので、DateRangeクラスの内部宣言よりは、外部に独立して宣言しておいたほうがよさそう。
domain.type は、問題領域の基本型に特化する。
price.UnitPriceは、基本型というよりは、基本型を組み合わせて問題領域固有の概念を表現する型と考えられるため。
Amount に以下の足し算を追加
Amount addAll(Amount... amounts)
Amount addAll(Collection<Amount> amounts)
static Amount from(Amount... amounts) // return new Amount(0).addAll(amounts)
static Amount from(Collection<Amount> amoutns) // 同上
LocalTime型は、23:59 までしか扱えない
String で、26:00 を渡した場合、24H + 2H であることを扱える型を作ってみる
用途としては、開始時刻と終了時刻の時間間隔の計算
#61 で次の状態は、State が持つ ( Transitionsを持つ)設計に変更した。
その結果、 Event の next() メソッドと、インスタンス変数 State nextState が不要になった。
不要になったメソッドとインスタンス変数を削除する。
Eventは、単なる定数オブジェクトになるが、いったんはそれでよしとする。
https://keisan.casio.jp/exec/system/1244792650
を参考に
以下のサービスを試作する
実装の指針
AmountTest
UnitPriceTest
QuantityTest
各テストクラスのメソッドに、@DisplayNameで、名前をつける
テストのassertが一つであれば、assertレベルの説明は不要(@DisplayNameに移動する)
設計ガイドラインを上記を追加する
これは、ひとつのissueでやるには、たぶん大きすぎるテーマです。
考えることがたくさんありそう。
もしやっていただける場合は、いくつかのissueに分解して、進めていただければと思います。
概要:小数点以下2桁の金額(円の場合は、銭単位まで)の四則演算
試作仕様は、
実装のアイデアとしては、
留意点としては、
いつもの通り、用途を限定したミニマムな仕様を重視する。
今回、想定している主なユースケースは消費税の計算。
百分率という概念を実直に表現すること。
DecimalAmountの小数点以下の桁数の扱いは、BigDecimalと同様に、桁数が多くなる方向(情報を失わない方向)にすることにした。
用途によっては、桁数が自動的に(暗黙に)変わることは好ましくない可能性がある。
桁数チェックを厳密する方法として、以下の2つを検討する
enum Unit {
ピース,
箱
}
状態タイプ
ミニマム実装
イベントタイプ(遷移タイプ)
実現イメージ:
具体的なアプリケーションとして、時給計算サービスを想定して実装してみる。
そのための骨格のクラスを用意する。
application.service.payroll.DailyPayroll
メソッド DailyPayroll#for(TimeRecord record, HuorlyWage wage) : Amount
https://keisan.casio.jp/exec/system/1245199831
この画面の簡易版
入力:勤務情報(勤務開始、終了、休憩時間)と時給
出力:日給
を実現するためのサービス
上記のサービスを実現するためのモデルクラス群(骨組みのみ)
#66 で実装された内容の追加の検討
アイデアレベルですが、#66の実装を受けて、考えたことを書き出してみます。
このクラスは、wage モデルよりも、domain/type/hour のほうがよいかもしれない。
Minuteの割り算として、実装する
type.RoundingType (enum) で RoundOff, RoundDown, RoundUp を宣言する
double で計算して、(int)でキャストしているが、言語仕様を暗黙に使っているところが、ちょっと違和感がある。
BigDecimal を使うと、冗長になるが、その分、説明的になるはず。
これは、負の数を、無限大の方向に切り捨てるための関数だったはず。
今回の文脈(正の数が前提)の意図としては、違和感がある。(通常の切り捨てでよい)
Minute クラスを、5分、10分、15分、20分、30分単位に Rounding できるメソッドがほしい
例えば、enum MinuteUnit で、上記の分刻みを宣言して、
Minute#byUnit(MiniteUnit, RoundingType) : Minute
みたいな感じ
#23のコンパイルエラー対策のコメントアウトのところを、対応する
ある日付を与えたら、期間内、期間前、期間後の判定結果を enum 型で返す
この仕様を元に試作した ContainType型、contains() メソッドの名前がしっくりこない。
よい名前が見つからないということは、たぶん、仕様か設計に改善の余地があるはず。
すぐに良い名前/設計が見つからないかもしれないが、いちおう備忘録として、issueを追加しておく。
現時点での所感:
三つのいずれかを戻す、という仕様が、不自然なのかもしれない。
例えば、次のように分解するとかも選択肢として検討したほうがよいかも。
具体的に使うシーンを考えたほうがよさそう。
机上で考えていてもしょうがないので、DateRange型を使うAggregate型(ロジックを集めて複合型)を検討してみる。
例えば、キャンペーン期間に対して、割引の適用可否とか。
hour パッケージで、時刻と時間を「時分」単位で表現する型を設計する。
概要
想定するユースケース:
https://keisan.casio.jp/exec/system/1245199831
この給与計算の機能の中で、「勤務時間の計算」をするためのクラス群を試作する
#46 給与計算試作の続き
参考ページ
https://keisan.casio.jp/exec/system/1245199831
このページの以下の入力値を扱えるようにする
日数を週単位で表現する( 内部に Daysを持って、週数または週数+日数を表現する)
前提: #8 Days型の実装が終わっていること
ミニマムな実装案
コンストラクタ
メソッド
class DueDate
boolean isOverDue(LocalDate date) // 期限切れ?
int remainingDays() 期限まであと何日か?
int daysPast() 期限からの超過日数
金額範囲(xx円からyy円)を表現する型
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.