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

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

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.

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

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

Avatar for かとじゅん

かとじゅん

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. ϢʔεέʔεϞσϦϯά • ϢʔεέʔεϞσϦϯά • υϝΠϯϞσϧΛݩʹϢʔ εέʔεΛهड़͢Δɻ • υϝΠϯϞσϦϯάͷ ༻ޠΛ࢖ͬͯɺϢʔβͷ ཁٻΛ໌֬ʹ͢Δɻ

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