Slide 1

Slide 1 text

ʮυϝΠϯۦಈઃܭೖ໳ʯ
 ΛಡΜͩ 2021/01/15

Slide 2

Slide 2 text

ΞδΣϯμ • υϝΠϯۦಈઃܭ:DDD ͱ͸ʁ • ͜ͷຊʢυϝΠϯۦಈઃܭೖ໳ʣͰͲ͏͍͏͜ͱ͕Θ͔Δͷ͔ʁ • ύλʔϯ • ஋ΦϒδΣΫτ • ΤϯςΟςΟ • υϝΠϯαʔϏε • ϦϙδτϦ • ΞϓϦέʔγϣϯαʔϏε • ϑΝΫτϦ • ू໿ • ࢓༷ ஌ࣝʢυϝΠϯʣΛදݱ͢Δύλʔϯ ΞϓϦέʔγϣϯΛ࣮ݱ͢ΔͨΊͷύλʔϯ ஌ࣝʢυϝΠϯʣΛදݱ͢ΔɺΑΓൃలతͳύλʔϯ

Slide 3

Slide 3 text

υϝΠϯۦಈઃܭ: DDDͱ͸ʁ “υϝΠϯۦಈઃܭʢӳ: domain-driven design, DDDʣͱ͸ιϑτ΢ΣΞͷઃܭख๏Ͱ ͋ΓɺʮෳࡶͳυϝΠϯͷઃܭ͸ɺϞσϧϕʔεͰߦ͏΂͖ʯͰ͋Γɺ·ͨʮେ൒ ͷιϑτ΢ΣΞϓϩδΣΫτͰ͸ɺγεςϜΛ࣮૷͢ΔͨΊͷಛఆͷٕज़Ͱ͸ͳ ͘ɺυϝΠϯͦͷ΋ͷͱυϝΠϯͷϩδοΫʹয఺Λஔ͘΂͖ʯͰ͋Δͱ͢Δɻ͜ ͷ໊শ͸ɺ Eric Evans ͕ಉ໊ͷஶ࡞Ͱ༻͍ͨɻ” https://ja.wikipedia.org/wiki/υϝΠϯۦಈઃܭ

Slide 4

Slide 4 text

ϢϏΩλεݴޠʁ Ϟσϧ: υϝΠϯʹ͓͚Δબ୒͞Εͨଆ໘Λهड़ ͠ɺͦͷυϝΠϯʹؔ࿈ͨ͠໰୊Λղܾ͢Δͷ ʹ࢖༻Ͱ͖Δந৅ͷମܥ 🤔🤔🤔🤔 ڞ༗Χʔωϧʁ ৠཹʁ ڥք͚ͮΒΕͨίϯςΩετʁ

Slide 5

Slide 5 text

υϝΠϯۦಈઃܭೖ໳ ϘτϜΞοϓͰΘ͔Δ! υϝΠϯۦಈઃܭͷجຊ
 https://www.amazon.co.jp/dp/479815072X

Slide 6

Slide 6 text

͜ͷຊͰͲ͏͍͏͜ͱ͕Θ͔Δͷ͔ʁ • DDD ͸ʮυϝΠϯͷϞσϦϯάʯͱʮͦΕΛ࣮૷ʹམͱ͠ࠐΉύ λʔϯʯ͕͋Δɻ͜ͷຊ͸ύλʔϯΛղઆ͍ͯ͠Δʢίʔυ෇͖Ͱʣ

Slide 7

Slide 7 text

ʢ࠶ܝʣΞδΣϯμ • υϝΠϯۦಈઃܭ:DDD ͱ͸ʁ • ͜ͷຊʢυϝΠϯۦಈઃܭೖ໳ʣͰͲ͏͍͏͜ͱ͕Θ͔Δͷ͔ʁ • ύλʔϯ • ஋ΦϒδΣΫτ • ΤϯςΟςΟ • υϝΠϯαʔϏε • ϦϙδτϦ • ΞϓϦέʔγϣϯαʔϏε • ϑΝΫτϦ • ू໿ • ࢓༷ ஌ࣝʢυϝΠϯʣΛදݱ͢Δύλʔϯ ΞϓϦέʔγϣϯΛ࣮ݱ͢ΔͨΊͷύλʔϯ ஌ࣝʢυϝΠϯʣΛදݱ͢ΔɺΑΓൃలతͳύλʔϯ

Slide 8

Slide 8 text

஋ΦϒδΣΫτ γεςϜݻ༗ͷ஋Λදݱ͢Δ • ࠷దͳ஋͕ϓϦϛςΟϒͳ஋Ͱ͋Δͱ͸ݶΒͳ͍ • ʮෆมʯʮಉ஋ੑʢ౳Ձੑʣʯʮަ׵Մೳʯͳੑ ࣭Λ࣋ͭ • Ͳ͜·Ͱ஋ΦϒδΣΫτʹ͢Δ͔ʁ • ϧʔϧ͕ଘࡏʁ୯ମͰऔΓѻ͍͍ͨʁ • ;Δ·͍Λ࣋ͯΔ • ϝϦοτ • දݱྗ͕૿͢ • ෆਖ਼ͳ஋Λଘࡏͤ͞ͳ͍ • ޡͬͨ୅ೖΛ๷͙ • ϩδοΫͷࢄࡏΛ๷͙ @Getter @RequiredArgsConstructor @EqualsAndHashCode public class FullName { private final String firstName; private final String lastName; // private final String middleName; } // ੏͚ͩΛදࣔ͢Δ String fullName = "Yoshida Tomoya"; String lastName = fullName.split(" ")[0]; System.out.println(lastName); // Yoshida // ੏͚ͩΛදࣔ͢Δʢ͏·͍͔͘ͳ͍ύλʔϯʣ String fullName = "John Smith"; String lastName = fullName.split(" ")[0]; System.out.println(lastName); // John

Slide 9

Slide 9 text

ΤϯςΟςΟ ϥΠϑαΠΫϧͷ͋ΔΦϒδΣΫτ • ଐੑͰ͸ͳ͘ಉҰੑʢidentityʣʹΑͬͯࣝผ͞Ε Δ΋ͷ • ʮՄมʯʮಉҰੑʹΑΓ۠ผ͞ΕΔʯ • ஋ΦϒδΣΫτ or ΤϯςΟςΟ • ϥΠϑαΠΫϧ͕͋Δ͔ʁʢϢʔβ͸࡞੒͞ Εɺ໊લΛมߋ͠ɺ࡟আ͞ΕΔʣ • ஋ΦϒδΣΫτͱΤϯςΟςΟͷͲͪΒʹ΋
 ͳΓ͏ΔʢλΠϠͷྫʣ @Getter public class User { private final UserId id; private String name; public User(UserId id, String name) { this.id = id; changeUserName(name); } public void changeUserName(String name) { if (name.length() > 30) { throw new IllegalArgumentException("Ϣʔβ໊͸30จࣈҎ಺ʹ͍ͯͩ͘͠͞"); } this.name = name; } @Override public int hashCode() { return new HashCodeBuilder().append(id).hashCode(); } @Override public boolean equals(Object obj) { if (obj instanceof User) { User other = (User) obj; return new EqualsBuilder().append(id, other.id).isEquals(); } else { return false; } } }

Slide 10

Slide 10 text

υϝΠϯαʔϏε υϝΠϯͷ׆ಈΛදݱ͢Δ • ஋ΦϒδΣΫτ΍ΤϯςΟςΟʹهड़͢Δͱෆࣗ વʹݟ͑Δ΋ͷ • ঢ়ଶΛ࣋ͨͳ͍ • υϝΠϯϞσϧශ݂঱ʹ஫ҙ • ՄೳͳݶΓυϝΠϯαʔϏεΛආ͚Δ // ࣗ෼ࣗ਎ʹ໰͍߹Θ͍ͤͯΔ UserId userId = new UserId("id"); UserName userName = new UserName("yoshida"); User user = new User(userId, userName); boolean existsUser = user.exists(user); // ॏෳ֬ೝઐ༻Πϯελϯεʹ໰͍߹Θ͍ͤͯΔ UserId userId = new UserId("id"); UserName userName = new UserName("yoshida"); User user = new User(userId, userName); UserId checkId = new UserId("check"); UserName checkName = new UserName("check"); User checkObject = new User(checkId, checkName); boolean existsUser = checkObject.exists(user); public class UserService { public boolean exists(User user) { // SQL Λୟ͍ͯ DB ʹଘࡏ͢Δ͔֬ೝ͢Δॲཧɻ௕͍ɻ // SQL Λୟ͍ͯ DB ʹଘࡏ͢Δ͔֬ೝ͢Δॲཧɻ௕͍ɻ // SQL Λୟ͍ͯ DB ʹଘࡏ͢Δ͔֬ೝ͢Δॲཧɻ௕͍ɻ // SQL Λୟ͍ͯ DB ʹଘࡏ͢Δ͔֬ೝ͢Δॲཧɻ௕͍ɻ return false; } }

Slide 11

Slide 11 text

ϦϙδτϦ σʔλʹ·ͭΘΔॲཧΛ෼཭͢Δ • ӬଓԽʢอଘʣͱ࠶ߏஙʢ෮ݩʣΛ୲౰͢Δ • updateName, updateEmail… Λආ͚Δɻ • ΤϯςΟςΟͷมߋ͸ΤϯςΟςΟࣗ਎ʹґ པ͢Δ • ಛఆͷٕज़ج൫ʹґଘ͠ͳ͍ͨΊʹΠϯλϑΣʔ εΛ੾Δ • ӬଓԽ૚͔Β௚઀ΤϯςΟςΟʹϚοϐϯά͢Δ ͷ͸ආ͚Δɻ • ෆཁͳ setter Λආ͚Δ @Service public class UserService { @Autowired private UserRepository userRepository; public boolean exists(User user) { User found = userRepository.find(user.getUserName()); return found != null; } public boolean exists2(User user) { // Ϣʔβ໊ʹΑΓॏෳ֬ೝΛߦ͏ɺͱ͍͏υϝΠϯ஌͕ࣦࣝΘΕ͍ͯΔ return userRepository.exists(user); } } public interface UserRepository { void save(User user); User find(UserName userName); boolean exists(User user); }

Slide 12

Slide 12 text

ΞϓϦέʔγϣϯ αʔϏε ϢʔεέʔεΛ࣮ݱ͢Δ • υϝΠϯΦϒδΣΫτΛ௚઀ެ։͠ͳ͍ • DTO Λ࡞Δ • Ҿ਺͕ଟ͘ͳΔ৔߹ • ίϚϯυΦϒδΣΫτΛ࡞Δ • υϝΠϯΦϒδΣΫτͷλεΫௐ੔ʹప͢Δ • υϝΠϯͷϧʔϧͷྲྀग़ʹؾΛ͚ͭΔ • ΞϓϦέʔγϣϯαʔϏεͷ੾Γํ • ڽू౓ͰݟͯΈΔ • ͜͜΋ΠϯλϑΣʔεʹ͓ͯ͘͠ͱςετ΍෼ۀ͕ ͠΍͍͢ • ঢ়ଶ͸࣋ͨͳ͍ @Service public class UserApplicationService { @Autowired private UserRepository userRepository; @Autowired private UserService userService; public void update(UserUpdateCommand command) { UserId targetId = new UserId(command.getId()); User user = userRepository.find(targetId); if (command.getName() != null) { user.changeName(new UserName(command.getName())); if (userService.exists(user)) { throw new RuntimeException("طʹଘࡏ͍ͯ͠·͢"); } } if (command.getEmail() != null) { user.changeEmail(new Email(command.getEmail())); } userRepository.save(user); } }

Slide 13

Slide 13 text

ϑΝΫτϦ ෳࡶͳੜ੒ॲཧΛߦ͏ • جຊ͸ίϯετϥΫλͰੜ੒ॲཧΛߦ͏΂͖ • ίϯετϥΫλ಺ͰଞͷΦϒδΣΫτΛੜ੒ ͢Δ͔Ͳ͏͔ • ͜͜΋ΠϯλϑΣʔεʹ͓ͯ͘͠ͱςετ΍෼ۀ͕ ͠΍͍͢ • ϑΝΫτϦʹ͸2छྨ͋Δ • ΫϥεͦΕࣗମ͕ϑΝΫτϦʹͳΔ • ϝιου͕ϑΝΫτϦͱͯ͠ػೳ͢Δ @Component public class UserFactory { public User create(UserName userName) { // SQL Ͱ࣍ͷ ID ΛҾͬுͬͯ͘Δॲཧɻ௕͍ // SQL Ͱ࣍ͷ ID ΛҾͬுͬͯ͘Δॲཧɻ௕͍ // SQL Ͱ࣍ͷ ID ΛҾͬுͬͯ͘Δॲཧɻ௕͍ // SQL Ͱ࣍ͷ ID ΛҾͬுͬͯ͘Δॲཧɻ௕͍ // SQL Ͱ࣍ͷ ID ΛҾͬுͬͯ͘Δॲཧɻ௕͍ UserId userId = new UserId("hoge"); return new User(userId, userName); } }

Slide 14

Slide 14 text

Domain Application Infrastructure

Slide 15

Slide 15 text

ײ૝ • Ϋϥε࡞Γա͗͌͌ɾɾɾʢDTO, ΠϯλϑΣʔε, ….ʣ • Ͳ͜ʹԿΛॻ͔͘໎͍ͦ͏ʢ૬౰܇࿅͞Εͯͳ͍ͱ೉͍͠ʣ • ·ͣɺίʔυΛॻ͖࢝ΊΔͱ͖Ϣʔεέʔε͔Βߟ͑Δ͜ͱ͕ଟ͍ͱࢥ͏ɻ
 Ϣʔβ৘ใΛมߋ͍ͨ͠ => ΞϓϦέʔγϣϯαʔϏε
 DDD Ͱ͸υϝΠϯΦϒδΣΫτʢΤϯςΟςΟɺ஋ΦϒδΣΫτɺυϝΠϯαʔϏεʣ ͔Β࡞ΔͱݴΘΕ͍ͯΔ • ֓೦΍஌ࣝʢυϝΠϯʣΛͲ͏ίʔυͰදݱ͢Δͷ͔ʁ͸͘͢͝Θ͔Γ΍͔ͬͨ͢ • ύοέʔδߏ੒ͱ͔ͷαϯϓϧ΋͋ͬͯΑ͔ͬͨ