Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ドメイン駆動設計基礎講座〜戦略編〜

 ドメイン駆動設計基礎講座〜戦略編〜

ChatWork社内勉強会で発表した際の資料

かとじゅん

March 17, 2017
Tweet

More Decks by かとじゅん

Other Decks in Technology

Transcript

  1. ':*ΦϒδΣΫτࢦ޲ͱ͍͏ߟ͑ํ ߏ੒͢Δ֤֓೦ΛΦϒδΣΫτͱͯ͠ɺιϑτ΢ΣΞʹ൓ө͢ ΔͨΊͷٕज़ɻͦΕͧΕͷΦϒδΣΫτ͸খ͞ͳ໰୊Λղܾ͢ Δɺ͞Βʹ༗ػతʹ࿈ܞͯ͠େ͖ͳ໰୊ղܾΛՄೳͱ͢Δɻ ं γϟʔγ λΠϠ λΠϠ λΠϠ λΠϠ

    Τϯδϯ ϋϯυϧ ϘσΟ ϖμϧ γʔτ ίϯιʔϧ DMBTT$BS CPEZ#PEZ 
 DMBTT#PEZ
 FOHJOF&OHJOF
 DIBTTJT$IBTTJT
 DMBTT$IBTTJT
 GSPOU-FGU5JFS GSPOU3JHIU5JFS
 CBDL-FGU5JFS CBDL3JHIU5JFS
 
 DMBTT&OHJOF DMBTT5JFS
  2. %%%Λ࣮ફ͢Δҙٛ w Ϗδωεͷઐ໳Ո υϝΠϯΤΩεύʔτ ͱ։ൃऀ ι ϑτ΢ΣΞΤΩεύʔτ Λಉ͡౔ඨʹ৐ͤΔ͜ͱͰɺ ։ൃऀͷࢹ఺͚ͩͰͳ͘Ϗδωεଆͷࢹ఺΋౿·͑ͨ ιϑτ΢ΣΞΛ࡞ΕΔΑ͏ʹ͢Δɻ

    w ͦͷιϑτ΢ΣΞͷ֓೦Λཧղ͍ͯ͠ΔҰ෦ͷਓ ͍ͨ ͍ͯ͸։ൃऀ ͚ͨͪͩͱ͍͏ঢ়گΛͳ͘͢ɻ w υϝΠϯΤΩεύʔτͱ։ൃऀɺιϑτ΢ΣΞͦͷ΋ ͷͱͷؒͰɺҰ੾ͷ௨༁Λෆཁͱ͢Δɻ w ઃܭ͕ίʔυͰ͋Γɺίʔυ͕ઃܭͰ΋͋Δͱ͍͏ঢ় گΛ࡞Γग़͢ɻ Θ͔ΔʂυϝΠϯۦಈઃܭʙ΋ͪ͜ΌΜͷେ๯ݥʙ͔ΒҾ༻
  3. υϝΠϯϞσϧͷྫ w νϟοτϧʔϜ͸୭ͷ΋ͷͰ΋ͳ͍ڞ༗෺Ͱ͋Δɻ୭Ͱ΋؅ ཧऀʹͳΕΔՄೳੑ͕͋Δ͕ɺطଘͷ؅ཧऀʹΑͬͯ௥Ճ· ͨ͸ڐՄ͞Εͳ͚Ε͹ͳΒͳ͍ɻ w ڞ༗෺Ͱ͸͋Δ͕ɺ؅ཧऀ͸࠷௿Ͱ΋ਓ͍ͳ͚Ε͹ͳΒͳ ͍ɻ w νϟοτʹࢀՃ͍ͯ͠ΔϢʔβ͸ϝϯόʔͱݺ͹ΕΔɻϝϯ

    όʔͰͳ͍ͱൃݴ͕Ͱ͖ͳ͍ɻ w ؅ཧऀ͸ϝϯόʔΛ௥ՃͰ͖Δɻެ։νϟοτ͸Ϣʔβ͕ࢀ ՃΛਃ੥Ͱ͖ɺ؅ཧऀʹΑͬͯڐՄ͞Εͨ৔߹ʹ ུɻ w ౤ߘ͞Εͨϝοηʔδ͸ɺνϟοτϧʔϜ͕ॴ༗͠ɺϝϯόʔ ͸୭Ͱ΋ಡΉ͜ͱ͕Ͱ͖Δɻ
  4. υϝΠϯϞσϧͷ༗༻ੑ w υϝΠϯϞσϧ ໰୊ʹର͢Δߟ͑ํ ͱઃܭ͸ ڧ͍૬ޓิ׬ؔ܎ʹ͋Δɻ w υϝΠϯϞσϧ͸ར֐ؔ܎ऀશһͰར༻Ͱ͖Δ ڞ௨ݴޠج൫ɻ w

    υϝΠϯϞσϧʹ͸༻ޠͷબ୒΍֓೦ಉ࢜ͷؔ ࿈͔Βબ୒͕͋ΓɺͦΕࣗମ͕໰୊ղܾͷͨΊ ͷઓུΛද͍ͯ͠Δɻ w ίϯλΫτ͸Ϣʔβͷͭͳ͕ΓΛ͕ࣔ͢ɺϑΝ Πϧ΍λεΫͱ͸௚઀ؔ܎͕ͳ͍ͳͲɻ
  5. ιϑτ΢ΣΞͷίΞ w ιϑτ΢ΣΞͷ֩৺͸ɺυϝΠϯʹ͋Δɻ w υϝΠϯ্ͷ໰୊ղܾʹ͸ɺϞσϦϯάεΩϧʹਫ਼௨͢Δ ͜ͱ͕ٻΊΒΕΔɻ͔͠͠ɺҰൠతʹ΄ͱΜͲͷ։ൃऀ͕ ϞσϦϯάεΩϧΑΓٕज़ࢦ޲Ͱ͋Γɺٕज़ͰυϝΠϯ্ ͷ໰୊Λղܾ͢ΔͷͰ͏·͍͔͘ͳ͍ɻ w Ұൠతʹɺ଎͍ͯ҆͘༌ૹۀऀͷίΞͱͳΔυϝΠϯͰ

    ͸ɺٕज़తͳܦ࿏ܭࢉΞϧΰϦζϜ άϥϑΞϧΰϦζϜ ࣗମʹڝ૪ྗͷݯઘͱͳΔՁ஋͕͋ΔΘ͚Ͱ͸ͳ͍ ڝ߹ ΋ಉ͡ΞϧΰϦζϜΛ࢖͏Մೳੑ͕͋ΔͨΊ ɻͦΕΛར ༻ͯ͠༌ૹۀऀͱͯ͠ͷ໨తΛ͍͔ʹୡ੒͢Δ͔ͷํ๏ ͷํ͕Ձ஋͕ߴ͍ɻ w ෳࡶ͞ʹཱͪ޲͔͏ʹ͸ɺυϝΠϯʹ໨Λ޲͚Δ͜ͱɻ
  6. Πϕϯτ ໰୊Λղ͘ߟ͑ํ ʹυϝΠϯϞσϧ "1* */ %# */ "1* 065 %#

    065 ͢΂͕ͯυϝΠϯϞσϧʹΑͬͯۦಈ͢Δߟ͑ํ ར֐ؔ܎ऀ ར֐ؔ܎ऀ
  7. ϢϏΩλεݴޠ ղܾ w ޡղͷϦεΫΛ཈͑ΔͨΊʹɺڞ௨ݴޠΛج൫ͱ͢Δɻ ͜ͷݴޠ͸νʔϜͷ࡞ۀͷ͍ͨΔͱ͜Ζʹଘࡏ͢Δɻ w ϢϏΩλεݴޠʹ͸ɺΫϥε΍ϝιουɺϓϩύςΟ ͷ໊લ΍ϧʔϧؚ͕·ΕΔɻ։ൃऀؒͰར༻͞Εɺγ εςϜ͚ͩͰ͸ͳ͘ɺλεΫ΍ػೳΛهड़͢ΔͨΊʹ ΋ར༻͞ΕΔɻ

    w ։ൃऀͱυϝΠϯΤΩεύʔτ͕͓ޓ͍ʹҙࢥૄ௨Λ ͢Δࡍʹ΋ར༻͞ΕΔɻυϝΠϯΤΩεύʔτಉ͕࢜ ཁ݅΍։ൃܭըɺ͋Δ͍͸ػೳΛ఻͑߹͏ࡍʹ΋ར༻ ͞ΕΔɻ w Ұ੾ͷ௨༁Λෆཁ͠ɺυϝΠϯʹର͢ΔཧղΛΑΓε Ϝʔζͳ΋ͷͱ͢Δɻ
  8. ༧໿ ઐ༻୺຤෦໳ͷ෦ॺɾऔҾઌ ཱྀఔ࡞੒ ཱྀఔ ঎඼ ݟੵ ސ٬ ܦཧ ސ٬ ৼࠐ

    ૊৫ͱΞʔΩςΫνϟͷத֩ʹ͸ υϝΠϯϞσϧ͕ଉͮ͘ ίϯςΩετϚοϓ Ұ෦ͷ৘ใΛ ఏڙ ม׵
  9. Ϟσϧͷछྨ w υϝΠϯϞσϧ ෼ੳ ʹυϝΠϯͷߟ͑ํ ֓೦ Λ൓ө ͨ͠΋ͷɻ໰୊ͷղ͘ߟ͑ํͦͷ΋ͷΛࢦ͢ɻϢϏΩ λεݴޠͰදݱ͞ΕΔɻ w

    ιϑτ΢ΣΞϞσϧ ઃܭ ʹιϑτ΢ΣΞ্ͰυϝΠϯ ϞσϧΛදݱͨ͠΋ͷɻ w ΦϒδΣΫτϞσϧ ࣮૷ ʹιϑτ΢ΣΞϞσϧΛίʔ υ্ʹ࣮૷ͨ͠΋ͷɻϓϩάϥϛϯάݴޠΛ࢖ͬͯද ݱ͞ΕΔɻ
  10. Ϟσϧͷछྨ w υϝΠϯϞσϧ ෼ੳ ʹυϝΠϯͷߟ͑ํ ֓೦ Λ൓ө ͨ͠΋ͷɻ໰୊ͷղ͘ߟ͑ํͦͷ΋ͷΛࢦ͢ɻϢϏΩ λεݴޠͰදݱ͞ΕΔɻ w

    ιϑτ΢ΣΞϞσϧ ઃܭ ʹιϑτ΢ΣΞ্ͰυϝΠϯ ϞσϧΛදݱͨ͠΋ͷɻ w ΦϒδΣΫτϞσϧ ࣮૷ ʹιϑτ΢ΣΞϞσϧΛίʔ υ্ʹ࣮૷ͨ͠΋ͷɻϓϩάϥϛϯάݴޠΛ࢖ͬͯද ݱ͞ΕΔɻ ϞσϧۦಈઃܭͰ͸ɺυϝΠϯ ϞσϧͱίʔυΛ෼཭ͤͣʹ ୯ҰͷϞσϧͰදݱ͢Δ
  11. Ϟσϧۦಈઃܭ ղܾ w ෼ੳɾઃܭɾ࣮૷͸୯ҰͷϞσϧʹΑͬͯۦಈ͢ Δɻͭ·Γɺઃܭ͕ίʔυͰ͋Γɺίʔυ͕ઃܭͰ ͋Δͱ͍͏ঢ়ଶΛ࡞Γग़͢ɻ͜ΕʹΑͬͯɺઃܭͷ ؒҧ͍Λൃݟ͢Δ͜ͱ͕Ͱ͖Δɻ w ࣮૷ΛϞσϧʹ݁ͼ͚ͭΔͨΊʹɺ௨ৗɺΦϒδΣ Ϋτࢦ޲ϓϩάϥϛϯάͷΑ͏ͳύϥμΠϜΛར༻

    ͢Δɻ w ؔ਺ܕ΍࿦ཧܕͳͲΛࠞ߹ͨ͠ύϥμΠϜͰ΋Α ͍͕ɺओ࣠͸001ɻͦΕ͸։ൃऀͷ਺΍҆ఆͨ͠ ։ൃ؀ڥʹґଘ͍ͯ͠Δɻͦ͏͍͏ҙຯͰ͸ɺ 4DBMB͸001ͱ'1ͷ྆ํͰϞσϦϯάͷબ୒ࢶΛ ޿͛ΒΕΔɺݱ࣮తͳϓϥοτϑΥʔϜͱ͍͑Δɻ
  12. ޱ࠲ͷϢϏΩλεݴޠͷྫ w ޱ࠲ʹݱۚͰೖग़ۚͰ͖Δ w ͨͩ͠ɺ࢒ߴ͸θϩະຬʹͳͬͯ͸ͳΒͳ͍ɻ w ޱ࠲͸ଞͷޱ࠲ʹग़ۚɺ΋͘͠͸ଞͷޱ࠲͔Β ೖۚͰ͖Δɻ w ޱ࠲ͷ࢒ߴΛ֬ೝͰ͖Δ

    w ͓ۚ͸ଞͷ͓ۚΛՃݮࢉͰ͖Δɻݮࢉ͸ෛͷྔ ΛՃࢉ͢ΔҙຯͰ΋Α͍ɻ w ͨͩ͠ɺಉҰޱ࠲ͳ͍Ͱ͸ɺಉ͡௨՟୯ҐͷΈ Λѻ͏
  13. ޱ࠲υϝΠϯΦϒδΣΫτͷఆٛ @Value
 public final class BankAccount {
 @NonNull
 private Long

    id;
 @NonNull
 private List<BankAccountEvent> events;
 
 
 public BankAccount depositCash(Money money) {
 return addBankAccountEvent(id, null, money);
 }
 
 public BankAccount withdrawCash(Money money) {
 return addBankAccountEvent(null, id, money.negated());
 }
 
 public BankAccount depositFrom(BankAccount from, Money money) {
 return addBankAccountEvent(id, from.getId(), money);
 }
 
 public BankAccount withdrawTo(BankAccount to, Money money) {
 return addBankAccountEvent(to.getId(), id, money.negated());
 }
 
 public Money getTotalAmount() {
 return getTotalAmountByEvents(events);
 } private BankAccount addBankAccountEvent(Long toBankAccountId, 
 Long fromBankAccountId, Money money) {
 Long eventId = IdGenerator.generateId();
 return addBankAccountEvent(BankAccountEvent.of(eventId, id, null, money));
 }
 
 private BankAccount addBankAccountEvent(BankAccountEvent event) {
 List<BankAccountEvent> result = Lists.newArrayList(events);
 result.add(event);
 return of(id, result);
 }
 } ݱۚೖۚ ݱۚग़ۚ ଞͷޱ࠲ʹग़ۚ ଞͷޱ࠲͔Βೖۚ ೖग़ۚΠϕϯτ͔Β࢒ߴΛฦ͢ ॏཁͳ͜ͱϝιουΛ ϢϏΩλεݴޠʹඥ෇͚Δ
  14. ޱ࠲υϝΠϯΦϒδΣΫτͷ੍໿ @Value
 public final class BankAccount { // தུ public

    static BankAccount of(Long id, List<BankAccountEvent> events) {
 if (getTotalAmountByEvents(events).isLessThan(Money.zero())) {
 throw new IllegalArgumentException("total amount is less than zero!");
 }
 return new BankAccount(id, events);
 } // தུ } ޱ࠲ͷ࢒ߴ͸θϩະຬʹͳͬͯ͸ͳΒͳ͍
  15. ޱ࠲υϝΠϯΦϒδΣΫτͷ࢖͍ํ Money baseMoney = Money.of(10000);
 BankAccount bankAccount1 = BankAccount.of(IdGenerator.generateId())
 .addIncrementAmount(baseMoney);

    ӳޠͬΆ͘ͳΔ͕ɺϏδωεαΠυͷਓ͕ͨͪ શ͘ཧղͰ͖ͳ͍Θ͚Ͱ͸ͳ͍ʁʁ ӳޠͬΆ͘ͳΔ͕ɺϏδωεαΠυͷਓ͕ͨͪ શ͘ཧղͰ͖ͳ͍Θ͚Ͱ͸ͳ͍ʁʁ
  16. ශ݂঱ޱ࠲ΦϒδΣΫτͷఆٛ public class BankAccount { 
 private Long id;
 private

    List<BankAccountEvent> events;
 
 public BankAccount() {
 }
 
 public Long getId() {
 return this.id;
 }
 
 public List<BankAccountEvent> getEvents() {
 return this.events;
 }
 
 public void setId(Long id) {
 this.id = id;
 }
 
 public void setEvents(List<BankAccountEvent> events) {
 this.events = events;
 }
 
 } w HFUUFSTFUUFS͔͠ͳ͍ͨ ͩͷσʔλͷೖΕ෺ w υϝΠϯϞσϧͱ࣮૷͕ ෼཭͞Ε͓ͯΓɺॏཁͳ ֓೦Λ఻͑ΒΕ͍ͯͳ ͍ɻͦ΋ͦ΋͜ΕͰ͸֓ ೦ͷཧղ͕͕ͨ͘͠ό άͷԹচʹ΋ͳΓ΍͢ ͍ɻ·ͨɺϏδωεͷ ઓུมߋʹ΋௥ै͠ʹ ͍͘ɻ w ΋ͬͱίʔυʹ֓೦Λ ޠΒͤΔ΂͖Ͱ͋Δɻ
  17. ශ݂঱ޱ࠲ΦϒδΣΫτͷ࢖͍ํ Money baseMoney = new Money();
 baseMoney.setCurrency(Currency.getInstance("JPY"));
 baseMoney.setAmount(BigDecimal.valueOf(10000));
 BankAccount bankAccount1

    = new BankAccount();
 bankAccount1.setId(IdGenerator.generateId());
 List<BankAccountEvent> events1 = Lists.newArrayList();
 BankAccountEvent incrementEvent1 = new BankAccountEvent();
 incrementEvent1.setId(IdGenerator.generateId());
 incrementEvent1.setToBankAccountId(bankAccount1.getId());
 incrementEvent1.setFromBankAccountId(null);
 incrementEvent1.setAmount(baseMoney);
 incrementEvent1.setOccurredAt(ZonedDateTime.now());
 events1.add(incrementEvent1);
 bankAccount1.setEvents(events1); ͯ͞ɺ༰қʹཧղͰ͖ΔίʔυͰ͠ΐ͏͔ʁ ޱ࠲࢒ߴ͕θϩະຬʹͳΒͳ͍ͱ͍͏ ߟ͑ํΛ࣮ࣔͨ͠૷Ͱ͠ΐ͏͔ʁ
  18. ͓ۚͷϢϏΩλεݴޠͷྫ w ͓ۚ͸୯ͳΔ਺஋ʁ-POH  w Ճݮࢉ͸਺஋ ਺஋ ਺஋਺஋  w

    ݫີʹ͸ɺ਺஋ʹ͓ۚͰ͸ͳ͍ͷͰ͸ʁ࣮ࡍʹίʔυ Ͱ-POHΛΈͯ΋͓͔ۚͲ͏͔͸Θ͔Βͳ͍ɻυϝΠϯ ্ͷ֓೦Λ࣮૷ʹඥ෇͚ΒΕ͍ͯͳ͍Մೳੑ͕͋Δɻ w ྫ͑͹ɺl͓ۚͱ͸ɺ௨՟ͷ୯ҐͱྔΛද͢΋ͷͰ͋Δz ͱ͍͏ϢϏΩλεݴޠΛ࡞Γ্͛Δɻ͓ۚͷྔ͸਺஋ Ͱ΋Α͍ͱ͢Δɻ
  19. ͓ۚυϝΠϯΦϒδΣΫτͷఆٛ @Value
 public final class Money {
 @NonNull
 private BigDecimal

    amount;
 @NonNull
 private Currency currency;
 
 
 public Money negated() {
 return of(amount.negate(), currency);
 }
 
 public Money plus(Money other) {
 Validate.notNull(other);
 Validate.isTrue(currency.equals(other.currency));
 return of(amount.add(other.amount), currency);
 }
 
 public Money minus(Money other) {
 return plus(other.negated());
 }
 
 public static Money sum(List<Money> monies) {
 if (monies.isEmpty()) {
 return zero(Money.DefaultCurrency);
 } else {
 Currency currency = monies.get(0).getCurrency();
 Money result = zero(currency);
 for (Money money : monies) {
 result = result.plus(money);
 }
 return result;
 }
 }
 
 public boolean isLessThan(Money other) { return isLessThan(other.amount); }
 
 public boolean isLessThan(BigDecimal amount) { return amount.compareTo(amount) < 0; }
 
 } ࢒ֹ͸ɺෳ਺ͷ͓ۚΛ߹ࢉ ͍ͯ͠Δɻ͓ۚࣗ਎͕Ճࢉ ϝιουΛ͓࣋ͬͯΓɺͦ ͷޠኮΛཧղͰ͖Ε͹߹ࢉ ࣗମͷཧղ΋͠΍͍͢ εέʔ ϥϒϧͳίʔυ Ճࢉͱ͍͏ϢϏΩλεݴޠ ͕Θ͔Ε͹ɺݮࢉࣗମ΋ཧ ղ͕ൺֱత༰қ
  20. ͓ۚυϝΠϯΦϒδΣΫτͷ࢖͍ํ Money money1 = Money.of(10000);
 Money money2 = Money.of(10000);
 Money

    result = money1.plus(money2);
 if (result.isLessThan(Money.zero())) {
 System.out.println("result is less than zero!");
 }
 System.out.println(result);
  21. ශ݂঱͓ۚΦϒδΣΫτͷఆٛ public class Money {
 
 private BigDecimal amount;
 private

    Currency currency;
 
 public Money() {
 }
 
 public BigDecimal getAmount() {
 return this.amount;
 }
 
 public Currency getCurrency() {
 return this.currency;
 }
 
 public void setAmount(BigDecimal amount) {
 this.amount = amount;
 }
 
 public void setCurrency(Currency currency) {
 this.currency = currency;
 }
 
 }
  22. ශ݂঱͓ۚΦϒδΣΫτͷ࢖͍ํ Money money1 = new Money();
 money1.setCurrency(Currency.getInstance("JPY"));
 money1.setAmount(BigDecimal.valueOf(10000));
 
 Money

    money2 = new Money();
 money2.setCurrency(Currency.getInstance("JPY"));
 money2.setAmount(BigDecimal.valueOf(10000));
 
 BigDecimal total = money1.getAmount().add(money2.getAmount());
 
 Money result = new Money();
 result.setCurrency(money1.getCurrency());
 result.setAmount(total); ؒҧ͍Ͱ͸ͳ͍͕ɺΘ͔Γʹ͍͘ɻ ΦϒδΣΫτࢦ޲ͷྑ͕͞ࡴ͞ΕΔ
  23. ޱ࠲ؒૹۚυϝΠϯαʔϏεͷఆٛ public final class BankAccountService {
 
 @Value
 public static

    class Result {
 private BankAccount to;
 private BankAccount from;
 }
 
 public static Result transfer(BankAccount to, BankAccount from, Money amount) {
 BankAccount updatedFrom = from.addDecrementEvent(to, amount);
 BankAccount updatedTo = to.addIncrementEvent(from, amount);
 return new Result(updatedTo, updatedFrom);
 }
 
 }
 ೋͭͷϞσϧঢ়ଶ͕׬શͳঢ়ଶͳΒͳ ͍ͱ͍͚ͳ͍ͷͰαʔϏεͰखଓ͖Խ ͢Δ͜ͱ͕͋Δɻ ͜ͷ৔߹Ͱ΋ɺϢϏΩλεݴޠΛ࢖ͬ ͨεΫϦϓτͷΑ͏ʹͳΔͷͰɺԿ͕ ى͜Δ͔ཧղ͠΍͍͢ɻ े෼ʹந৅Խ͞Ε͍ͯΔͷͰཧղ͠΍͍͢
  24. ޱ࠲ؒૹۚυϝΠϯαʔϏεͷ࢖͍ํ Money baseMoney = Money.of(10000);
 // ޱ࠲Λએݴ͠ɺॳظೖۚΛߦ͏
 BankAccount bankAccount1 =

    BankAccount.of(IdGenerator.generateId())
 .addIncrementAmount(baseMoney);
 BankAccount bankAccount2 = BankAccount.of(IdGenerator.generateId())
 .addIncrementAmount(baseMoney);
 
 System.out.println("bankAccount1 = " + bankAccount1.getTotalAmount());
 System.out.println("bankAccount2 = " + bankAccount2.getTotalAmount());
 
 // ޱ࠲ؒૹۚΛߦ͏
 BankAccountService.Result result = BankAccountService.transfer(
 bankAccount1,
 bankAccount2,
 Money.of(10000)
 );
 
 System.out.println("to = " + result.getTo().getTotalAmount());
 System.out.println("from = " + result.getFrom().getTotalAmount()); νʔϜͰ࡞ͬͨɺݴޠʹΑͬͯϩδοΫ͕ߏ੒͞ΕΔɻ
  25. ශ݂঱ޱ࠲ؒૹۚαʔϏε public class BankAccountService {
 @Data
 public static class Result

    {
 private BankAccount to;
 private BankAccount from;
 }
 
 public static Result moveData(BankAccount to, BankAccount from, Money amount) {
 BigDecimal totalAmount = BigDecimal.ZERO;
 for(BankAccountEvent event : to.getEvents()) {
 totalAmount = totalAmount.add(event.getAmount().getAmount());
 }
 if (totalAmount.compareTo(amount.getAmount()) < 0) {
 throw new IllegalArgumentException("total amount is less than zero!");
 }
 BankAccountEvent decrementEvent = new BankAccountEvent();
 decrementEvent.setId(IdGenerator.generateId());
 decrementEvent.setFromBankAccountId(from.getId());
 decrementEvent.setToBankAccountId(to.getId());
 Money negated = new Money();
 negated.setCurrency(amount.getCurrency());
 negated.setAmount(amount.getAmount().negate());
 decrementEvent.setAmount(negated);
 decrementEvent.setOccurredAt(ZonedDateTime.now());
 BankAccount newFrom = new BankAccount();
 List<BankAccountEvent> newFromEvent = Lists.newArrayList(from.getEvents());
 newFromEvent.add(decrementEvent);
 newFrom.setId(from.getId());
 newFrom.setEvents(newFromEvent);
 
 BankAccountEvent incrementEvent = new BankAccountEvent();
 incrementEvent.setId(IdGenerator.generateId());
 incrementEvent.setFromBankAccountId(from.getId());
 incrementEvent.setToBankAccountId(to.getId());
 incrementEvent.setAmount(amount);
 incrementEvent.setOccurredAt(ZonedDateTime.now());
 BankAccount newTo = new BankAccount();
 List<BankAccountEvent> newToEvent = Lists.newArrayList(to.getEvents());
 newToEvent.add(incrementEvent);
 newTo.setId(to.getId());
 newTo.setEvents(newToEvent);
 
 Result result = new Result();
 result.setFrom(newFrom);
 result.setTo(newTo);
 return result;
 
 }
 
 } ޱ࠲࢒ߴͷνΣοΫ͸ ޱ࠲ࣗ৴Ͱ͸ͳ͘ ϩδοΫͰؤுΔ ۩ମతա͗Δৄࡉʹ ѹ౗͞Εͯ͠·͏ʜɻ ػೳ͕ଟ͍ͱ໰୊͕ ͞ΒʹෳࡶʹͳΔɻ ίʔυͷॏෳʹ΋ؾ͖ͮʹ͍͘ɻ ͜ΕͰ͸υϝΠϯΤΩεύʔτ ͱͷؒʹ௨༁͕ඞཁʹͳΔ ݮࢉͷ֓೦͕҉໧஌Ͱ ཧղ͠ʹ͍͘
  26. ශ݂঱ޱ࠲ؒૹۚαʔϏεͷ࢖͍ํ Money baseMoney = new Money();
 baseMoney.setCurrency(Currency.getInstance("JPY"));
 baseMoney.setAmount(10000);
 // ޱ࠲Λએݴ͠ɺॳظೖۚΛߦ͏


    BankAccount bankAccount1 = new BankAccount();
 bankAccount1.setId(IdGenerator.generateId());
 List<BankAccountEvent> events1 = Lists.newArrayList();
 BankAccountEvent incrementEvent1 = new BankAccountEvent();
 incrementEvent1.setId(IdGenerator.generateId());
 incrementEvent1.setToBankAccountId(bankAccount1.getId());
 incrementEvent1.setFromBankAccountId(null);
 incrementEvent1.setAmount(baseMoney);
 incrementEvent1.setOccurredAt(ZonedDateTime.now());
 events1.add(incrementEvent1);
 bankAccount1.setEvents(events1);
 
 
 BankAccount bankAccount2 = new BankAccount();
 bankAccount2.setId(IdGenerator.generateId());
 List<BankAccountEvent> events2 = Lists.newArrayList();
 BankAccountEvent incrementEvent2 = new BankAccountEvent();
 incrementEvent2.setId(IdGenerator.generateId());
 incrementEvent2.setToBankAccountId(bankAccount1.getId());
 incrementEvent2.setFromBankAccountId(null);
 incrementEvent2.setAmount(baseMoney);
 incrementEvent2.setOccurredAt(ZonedDateTime.now());
 events2.add(incrementEvent2);
 bankAccount2.setEvents(events2);
 
 Money totalAmount1 = getTotal(bankAccount1);
 Money totalAmount2 = getTotal(bankAccount2);
 
 System.out.println("bankAccount1 = " + totalAmount1);
 System.out.println("bankAccount2 = " + totalAmount2);
 
 Money data = new Money();
 data.setCurrency(bankAccount1.getEvents().get(0).getAmount().getCurrency());
 data.setAmount(BigDecimal.valueOf(10000));
 // ޱ࠲ؒૹۚΛߦ͏
 BankAccountService.Result result = BankAccountService.moveData(
 bankAccount1,
 bankAccount2,
 data
 );
 
 Money newTotalAmount1 = getTotal(result.getTo());
 Money newTotalAmount2 = getTotal(result.getFrom());
 
 System.out.println("toTotalAmount = " + newTotalAmount1);
 System.out.println("fromTotalAmount = " + newTotalAmount2); ΋͸΍ίʔυΛಡΉؾʹͳΒ ͳ͍ɻυϝΠϯϞσϧ͕ࣔ͢ ߟ͑ํ͕े෼ʹ൓ө͞Ε͍ͯ ͳ͍ͨΊɺ͜ͷ࣮૷Λίϛϡ χέʔγϣϯʹ࢖͏͜ͱ͸೉ ͍͠ɻ
  27. *$0/*9ϓϩηεͱϢʔβετʔϦϚοϐϯά w શһ νʔϜͰϢʔβετʔϦϚοϐϯάˠϥϑͳυϝΠϯϞσϧ ˠϥϑͳϢʔεέʔεϞσϧΛ࡞Γͳ͕ΒɺॳظͷϢϏΩλεݴޠ Λ࡞Δ ඞཁʹԠͯ͡ΠϯελϯτͳࢴࣳډΛ࡞Δ ɻ w υϝΠϯϞσϧෆࡏͰϢʔεέʔεΛ࡞Δͱٕज़తৄࡉʹཱͪೖͬ

    ͯ͠·͍͕ͪͰɺϢϏΩλεݴޠ͕࡞Γʹ͍͘ɻϢʔεέʔεΛߟ ͍͑ͯ͘ͱ৽͍͠ݴ༿Λൃݟ͢Δ͜ͱ͕͋ΔˠυϝΠϯϞσϧΛվ గ͢Δɻ w ΤϯδχΞͷΈ ϩόετωε෼ੳ΍γʔέϯεਤ͸ෳࡶͳͱ͜Ζ ͚ͩʹߜΔ
  28. ϢʔεέʔεϞσϦϯά • ϢʔεέʔεϞσϦϯά • υϝΠϯϞσϧΛݩʹϢʔ εέʔεΛهड़͢Δɻ • υϝΠϯϞσϦϯάͷ ༻ޠΛ࢖ͬͯɺϢʔβͷ ཁٻΛ໌֬ʹ͢Δɻ

    • υϝΠϯϞσϧʹͳ͍ݴ ༿͕ൃݟ͞ΕͨυϝΠ ϯϞσϧਤΛߋ৽͢Δɻ • ͨͩ͠ɺֆʹͩ͜ΘΔඞཁ ͸ͳ͍ɺҰཡදͰ΋Α͍ɻ