Slide 1

Slide 1 text

גࣜձࣾΧέϋγɹ໦ଜজ޺ /FTU+4ͷ%*ίϯςφͰ࡞ΔΫϦʔϯͳϨ ΠϠʔڥք /FTU+4NFFUVQ0OMJOFɹ

Slide 2

Slide 2 text

ࢹௌऀ૚ɾಡऀ૚ͷ૝ఆ w ҎԼͷ͍ͣΕ͔ʹ֘౰ w /FTU+4Ͱ8FCΞϓϦέʔγϣϯΛ૊Μͩ͜ͱ͕͋Δ w /FTU+4ͷ1SPWJEFS.PEVMFΛ৮ͬͨ͜ͱ͕͋Δ w ΦϒδΣΫτࢦ޲Ͱͷઃܭɾ։ൃܦݧ͕͋Δ

Slide 3

Slide 3 text

ࣗݾ঺հ w גࣜձࣾΧέϋγ d w ҩྍ඼ൃ஫ɾ؅ཧ࠷దԽྖҬͷ৽نࣄۀͷ্ཱͪ͛Λ୲౰த w ιϑτ΢ΣΞΤϯδχΞσʔλΤϯδχΞΞʔΩςΫτ w Χέϋγͱ5ZQF4DSJQU w גࣜձࣾΧέϋγY5ZQF4DSJQU"EWFOU$BMFOEBS w ͳͥόοΫΤϯυ5ZQF4DSJQU͔ʁٕज़બఆഎܠͱ࣮ફྫΛ঺հ͠·͢ ໦ଜজ޺ ͖ΉΒ͖͋ͻΖ ˞ܦྺͷৄࡉ͸/FTU+4.FFUVQ0OMJOFͷΠϕϯτϖʔδʹهࡌ͍ͯ͠·͢

Slide 4

Slide 4 text

5XJUUFSIUUQTUXJUUFSDPNLJNVUZBN .FEJVNIUUQTLJNVUZBNNFEJVNDPN 4QFBLFS%FDLIUUQTTQFBLFSEFDLDPNLJNVUZBN (JUIVCIUUQTHJUIVCDPNLJNVUZBN 'PMMPX.F

Slide 5

Slide 5 text

ΞδΣϯμ ΫϦʔϯͳϨΠϠʔڥքΛ૊ΉͨΊͷߟ͑ํ /FTU+4ͷ%*ίϯςφͷ࢓૊Έ ϨΠϠʔڥքΛߏ੒͢Δ औΓѻΘͳ͍͜ͱ w ΫϦʔϯΞʔΩςΫνϟͷਂ͍આ໌ w υϝΠϯϞσϦϯάͷ࢓ํ ηΫγϣϯ

Slide 6

Slide 6 text

ΫϦʔϯͳϨΠϠʔڥքΛ૊ΉͨΊͷߟ ͑ํ ηΫγϣϯ

Slide 7

Slide 7 text

w ΫϦʔϯΞʔΩςΫνϟͰ༗໊ͳਤͰ͢ɻ w ͜ΕΒͷಉ৺ԁͷ಺ଆʹ͍͘΄Ͳιϑτ΢ΣΞͱ ্ͯ͠ҐϞδϡʔϧʹͳΔ͜ͱ͕ࣔ͞Ε͍ͯ·͢ɻ w υϝΠϯۦಈઃܭͷจ຺ͩͱɺ&OUJUJFT͸ศ্ٓυ ϝΠϯϞσϧͱදݱ͢Δ৔߹͕͋Γ·͢ɻ w ಉ৺ԁͷ࿮ΛϨΠϠʔڥքͱݺͼ·͢ɻ w ಉ৺ԁͷ࿮Λԣஅ͢Δʮˠʯ͸ґଘؔ܎Ͱ͢ɻ ΫϦʔϯͳϨΠϠʔڥքΛ૊ΉͨΊͷߟ͑ํ ΫϦʔϯΞʔΩςΫνϟ IUUQTCMPHDMFBODPEFSDPNVODMFCPCUIFDMFBOBSDIJUFDUVSFIUNM

Slide 8

Slide 8 text

ΫϦʔϯͳϨΠϠʔڥքΛ૊ΉͨΊͷߟ͑ํ ґଘؔ܎ٯసͷݪଇ %FQFOEFODZ*OWFSTJPO1SJODJQMF l্ҐϞδϡʔϧ͸͍͔ͳΔ΋ͷ΋ԼҐϞδϡʔϧ ͔Β࣋ͪࠐΜͰ͸ͳΒͳ͍ɻ૒ํͱ΋ந৅ʢྫͱ͠ ͯΠϯλʔϑΣʔεʣʹґଘ͢Δ΂͖Ͱ͋Δɻz˞ lந৅͸ৄࡉʹґଘͯ͠͸ͳΒͳ͍ɻৄࡉʢ۩৅త ͳ࣮૷಺༰ʣ͕ந৅ʹґଘ͢Δ΂͖Ͱ͋Δɻz˞ ґଘؔ܎ٯసύλʔϯͰ͸ɺΠϯλʔϑΣʔεΛ஥հ ͤ͞Δ͜ͱͰ্ҐϞδϡʔϧͷґଘΛճආ͍ͯ͠· ͢ɻ ,MPES౤ߘऀࣗ਎ʹΑΔஶ࡞෺ $$දࣔܧঝ IUUQTDPNNPOTXJLJNFEJBPSHXJOEFYQIQ DVSJEʹΑΔ ,MPES౤ߘऀࣗ਎ʹΑΔஶ࡞෺ $$දࣔܧঝ IUUQTDPNNPOTXJLJNFEJBPSHXJOEFYQIQ DVSJEʹΑΔ ӈ্ը૾ ӈԼը૾ ˞ IUUQTKBXJLJQFEJBPSHXJLJґଘੑٯసͷݪଇ ैདྷͷϨΠϠʔύλʔϯ ґଘؔ܎ٯసύλʔϯ

Slide 9

Slide 9 text

w ґଘؔ܎ٯసͷݪଇʹैͬͨઃܭΛ͢Δͱɺ࠷ऴ తʹΠϯλʔϑΣʔεͷ࣮૷Λඥ෇͚Δඞཁ͕ग़ͯ ͖·͢ɻͦ͜Ͱɺґଘੑͷ஫ೖ %* Λߦ͍·͢ɻ w ্ͷίʔυ͸ɺίϯετϥΫλͰґଘੑΛ஫ೖ͢ ΔྫͰ͢ ίϯετϥΫλ%* ɻ w %*ͱ͸ɺґଘؔ܎ΛΫϥεؔ਺ͷ֎͔Β౉͢͜ͱ Ͱ͢ɻ w ͳ͓ɺԼͷίʔυ͸ɺ.FDIBOJTN಺෦Ͱ1PMJDZͷ ۩৅Ϋϥε͕ґଘͯ͠ɺґଘੑͷz஫ೖzʹ͸ͳͬͯ ͍·ͤΜɻ ΫϦʔϯͳϨΠϠʔڥքΛ૊ΉͨΊͷߟ͑ํ ґଘੑͷ஫ೖ %FQFOEFODZ*OKFDUJPO export class MechanismService { constructor(private policyService: IPolicyService) { } // ུ } export class MechanismService { private policyService: IPolicyService = new PolicyService( ) // ུ }

Slide 10

Slide 10 text

w %*Λ࢖ͬͨΫϥεઃܭΛਐΊΔͱɺґଘؔ܎Λղ ܾ͢ΔӈͷΑ͏ͳίʔυ͕ੜ·Ε·͢ɻ w Ϋϥε͕গͳ͍͏ͪ͸໰୊ʹͳΓ·ͤΜ͕ɺ૿͑ ͖ͯͨ࣌͸ෆཁͳෳࡶੑΛੜΉ৔߹͕͋Γ·͢ɻ w %*ίϯςφ͸ӈͷίʔυΛॻ͔ͣʹґଘؔ܎ͷϏ δωεϩδοΫͷ֎ଆͰ؅ཧ͢Δ͜ͱ͕Ͱ͖· ͢ɻ w ͦͯ͠ɺ%*ίϯςφ͸/FTU+4ͷओཁͳػೳͷͭ Ͱ͢ɻ ΫϦʔϯͳϨΠϠʔڥքΛ૊ΉͨΊͷߟ͑ํ %*ίϯςφ͸ԿΛղܾ͢Δ͔ʁ new UtilityService ( new MechanismService ( new PolicyService( ) ) )

Slide 11

Slide 11 text

/FTU+4ͷ%*ίϯςφͷ࢓૊Έ ηΫγϣϯ

Slide 12

Slide 12 text

w ·ͣ͸؆୯ͳྫ͔Βɻ w $BUT4FSWJDFͷґଘؔ܎͸ɺ!.PEVMFΛӈͷΑ͏ ʹఆٛ͢Ε͹%*Ͱ͖·͢ɻ w ͜ͷྫ͸ɺ$BUT4FSWJDFzΫϥεzΛ$BUT$POUSPMMFS ͰίϯετϥΫλ%*͍ͯ͠·͢ɻ /FTU+4ͷ%*ίϯςφͷ࢓૊Έ 1SPWJEFS @Controlle r class CatsService { } @Controller("cats") class CatsController { constructor(private catsService: CatsService) { } // ུ } @Module( { controllers: [CatsController] , providers: [CatsService] , } ) export class AppModule {}

Slide 13

Slide 13 text

w ΠϯλʔϑΣʔεͷ৔߹͸ɺ޻෉͕ඞཁͰ͢ɻ w +BWB4DSJQU͸ΠϯλʔϑΣʔεΛαϙʔτͯ͠ ͍ͳ͍ͨΊɺ5ZQF4DSJQUΛ+BWB4DSJQUʹίϯ ύΠϧ͢ΔͱɺΠϯλʔϑΣʔεͷఆٛ͸ফࣦ ͠·͢ɻ w τʔΫϯ ྫͰ͸$"54@4&37*$&@50,&/ Ͱ /FTU+4ͷ*OKFDUFSͰࣝผՄೳͳঢ়ଶʹ͢Δඞཁ͕ ͋Γ·͢ɻ /FTU+4ͷ%*ίϯςφͷ࢓૊Έ 1SPWJEFS interface ICatsService { } class CatsService implements ICatsService { } const CATS_SERVICE_TOKEN = "CATS_SERVICE_TOKEN" ; class CatsController { constructor ( @Inject(CATS_SERVICE_TOKEN ) private catsService: ICatsServic e ) { } // ུ } export const CatServiceProvider: Provider = { provide: CAT_SERVICE_TOKEN , useClass: CatsService , } ; @Module( { controllers: [CatsController] , providers: [CatServiceProvider] , } ) export class AppModule { }

Slide 14

Slide 14 text

/FTU+4ͷ%*ίϯςφͷ࢓૊Έ !.PEVMFͱ͸Կ͔ʁ .PEVMF# .PEVMF" FYQPSUT JNQPSUT JNQPSUT 1SPWJEFS 1SPWJEFS $POUSPMMFS QSPWJEFST /FTU+4ͷΠϯδΣΫλʹΑͬͯΠϯελϯ εԽ͞Εɺগͳ͘ͱ΋Ϟδϡʔϧ಺Ͱڞ༗ ͞ΕΔ DPOUSPMMFST .PEVMF಺ͷΠϯελϯεԽ͢Δඞཁ͕͋Δ $POUSPMMFSҰཡ JNQPSUT ͜ͷϞδϡʔϧʹFYQPSU͢ΔผͷϞδϡʔ ϧͷҰཡ FYQPSUT ผͷϞδϡʔϧͰ͜ͷϞδϡʔϧΛJNQPSU ͢ΔͨΊͷɺެ։͢ΔϓϩόΠμٴͼτʔ ΫϯͷϦετ

Slide 15

Slide 15 text

ϨΠϠʔڥքΛߏ੒͢Δ ηΫγϣϯ

Slide 16

Slide 16 text

ϨΠϠʔڥքΛߏ੒͢Δ IUUQTCMPHDMFBODPEFSDPNVODMFCPCUIFDMFBOBSDIJUFDUVSFIUNM ߏ੒͢ΔΫϥεਤ

Slide 17

Slide 17 text

ϨΠϠʔڥքΛߏ੒͢Δ ߏ੒͢ΔΫϥεਤ w ֤ϨΠϠʔຖ EPNBJOVTF$BTF QSJNBSZ"EBQUPSTFDPOEBSZ"EBQUPS ʹͦΕͧ Ε.PEVMFΛ࡞੒͠·͢ w ͦΕΒΛ࠷ऴతʹ.PEVMFΛଋͶ·͢ɻ w <ิ଍>QSJNBSZͱTFDPOEBSZͱ͸ʁ w ΫϦʔϯΞʔΩςΫνϟͷલਐͱͳͬͨ 1PSUT"EBQUPSTΞʔΩςΫνϟͷ༻ޠͰ ͢ɻ w QSJNBSZ͸ʮۦಈ͢ΔʯΞμϓλ w TFDPOEBSZ͸ʮۦಈ͞ΕΔʯΞμϓλ

Slide 18

Slide 18 text

w 3FQPTJUPSZ΍3FRVFTUFS͸*'ͷΈͰ͢ɻ w ۩ମతͳ࣮૷Λ͢ΔͱΞμϓλ૚ٴͼͦΕΑ Γ΋֎ͷԁʹґଘͯ͠͠·͏ͨΊͰ͢ɻ w Ұ൪্ҐϞδϡʔϧʹͳΔͨΊz஫ೖz͢Δґଘ͸ ͳ͍ͨΊɺ.PEVMF͸͋Γ·ͤΜɻ w ͳ͓ɺτʔΫϯ͸Ϣʔεέʔε૚ͷ࣮૷Ͱ࢖͏ͨ Ίɺ͜͜ʹ഑ஔ͍ͯ͠·͢ɻ ϨΠϠʔڥքΛߏ੒͢Δ υϝΠϯ૚ EPNBJO export type Cat = Readonly< { id: CatId ; name: CatName ; age: CatAge ; }> ; export const CAT_REPOSITORY_TOKEN = 'CAT_REPOSITORY_TOKEN' ; export interface ICatRepository { store(cat: Cat): Promise ; } export const CAT_REQUESTER_TOKEN = 'CAT_REQUESTER_TOKEN' ; export interface ICatRequester { get(catId: CatId): Promise ; }

Slide 19

Slide 19 text

w ʮೣΛड͚औΔʯͱ͍͏ϢʔεέʔεΛ૝ఆͨ͠ ࣮૷Ͱ͢ɻ w 6TF$BTF͸*'Ͱɺͦͷ࣮૷Ϋϥε͸*OUFSBDUPS Ͱ͢ɻ w *OUFSBDUPSͰ͸υϝΠϯ૚Ͱఆٛͨ͠*'Λίϯε τϥΫλͷҾ਺ʹఆ͍ٛͯ͠·͢ɻ ϨΠϠʔڥքΛߏ੒͢Δ Ϣʔεέʔε૚ 6TF$BTF export interface UseCase { run(input: In): Promise ; } export type Input = Readonly< { catId: CatId ; }> ; export type Output = Omit ; export type ReceiveCatUseCase = UseCase ; export const RECEIVE_CAT_USECASE_TOKEN = 'RECEIVE_CAT_USECASE_TOKEN' ; @Injectable( ) export class ReceiveCatInteractor implements ReceiveCatUseCase { constructor ( @Inject(CAT_REPOSITORY_TOKEN ) private catRepository: ICatRepository , @Inject(CAT_REQUESTER_TOKEN ) private catRequester: ICatRequester , ) { } async run({ catId }: Input): Promise { const cat = await this.catRequester.get(catId); // ུ } }

Slide 20

Slide 20 text

ϨΠϠʔڥքΛߏ੒͢Δ Ϣʔεέʔε૚ 6TF$BTF w ηΧϯμϦʔΞμϓλͷΫϥε ྘ Λ࣮૷ͱͯ͠ ࠾༻͢Δ͜ͱʹ͢Δ৔߹͸ɺηΧϯμϦΞμϓλ ͷ.PEVMFΛJNQPSU͠·͢ɻ w ͜ΕΛ౿·͑ͯ࣍ͷϖʔδͰ͸.PEVMFΛ࡞੒͠ ·͢ɻ

Slide 21

Slide 21 text

w ηΧϯμϦʔΞμϓλͷ.PEVMF ޙड़ ΛJNQPSU ͍ͯ͠·͢ w ϢʔεέʔεΛଞͷ.PEVMFͰར༻Ͱ͖ΔΑ͏ʹ ϓϩόΠμΛFYQPSU͍ͯ͠·͢ w ϓϥΠϚϦΞμϓλͷ.PEVMF ޙड़ ͰJNQPSU ͠·͢ɻ w <ิ଍>6TF$BTF.PEVMF͸ΠϯλʔϑΣʔεΞμ ϓλʹґଘ͍ͯ͠·͕͢ɺϩδοΫ͕ґଘ͍ͯ͠ ΔΘ͚Ͱ͸͋Γ·ͤΜɻ ϨΠϠʔڥքΛߏ੒͢Δ Ϣʔεέʔε૚ 6TF$BTF export const ReceiveCatUseCaseProvider: Provider = { provide: RECEIVE_CAT_USECASE_TOKEN , useClass: ReceiveCatInteractor , } ; @Module( { imports: [AdaptorMemoryStoreModule, AdaptorPetShopApiModule] , providers: [ReceiveCatUseCaseProvider] , exports: [ReceiveCatUseCaseProvider] , } ) export class UseCaseModule { }

Slide 22

Slide 22 text

w υϝΠϯ૚ͷϦϙδτϦͷ*'Λ࣮૷͍ͯ͠·͢ɻ w ϦϙδτϦͷϓϩόΠμΛଞͷ.PEVMFͰ׆༻Ͱ ͖ΔΑ͏ʹFYQPSU͍ͯ͠·͢ɻ w Ϣʔεέʔεͷ.PEVMFͰJNQPSU͠·͢ɻ ϨΠϠʔڥքΛߏ੒͢Δ ΠϯλʔϑΣʔεΞμϓλ૚ 4FDPOEBSZ"EBQUPS @Injectable( ) export class CatRepository implements ICatRepository { store(cat: Cat): Promise { // ུ } } export const CatRepositoryProvider: Provider = { provide: CAT_REPOSITORY_TOKEN , useClass: CatRepository , } ; @Module( { providers: [CatRepositoryProvider] , exports: [CatRepositoryProvider] , } ) export class AdaptorMemoryStoreModule { }

Slide 23

Slide 23 text

w $BU$POUSPMMFSͷ࣮૷Ͱ͢ɻ w 6TF$BTF͸*'ͱ1SFTFOUFSͷΫϥεΛίϯετ ϥΫλͰఆ͍ٛͯ͠·͢ɻ ϨΠϠʔڥքΛߏ੒͢Δ ΠϯλʔϑΣʔεΞμϓλ૚ 1SJNBSZ"EBQUPS @Injector( ) export class CatPresenter { } @Controller('/cat' ) export class CatController { constructor ( @Inject(RECEIVE_CAT_USECASE_TOKEN ) private receiveCatUseCase: ReceiveCatUseCase , private catPresenter: CatPresenter , ) { } @Put(':id' ) async receive(@Param('id') id: string): Promise { // ུ } }

Slide 24

Slide 24 text

ϨΠϠʔڥքΛߏ੒͢Δ ΠϯλʔϑΣʔεΞμϓλ૚ 1SJNBSZ"EBQUPS w $POUSPMMFS ੨ ͷґଘؔ܎Λղܾ͢ΔͨΊʹɺ *OUFSBDUPSͷϓϩόΠμʔΛؚΉϢʔεέʔεͷ .PEVMF͕ඞཁʹͳΓ·͢ɻ w ·ͨɺ͜ͷྫͰ͸1SFTFOUFSͷґଘؔ܎΋ղܾ͢ Δඞཁ͕͋Γ·͢ɻ w ͜ΕΛ౿·͑ͯ࣍ͷϖʔδͰ͸.PEVMFΛ࡞੒͠ ·͢ɻ

Slide 25

Slide 25 text

w Ϣʔεέʔεͷ.PEVMFΛJNQPSUͯ͠ɺ $POUSPMMFSͷίϯετϥΫλ%*͍ͯ͠·͢ɻ w DPOUSPMMFSTʹίϯτϩʔϥʔͷࢦఆΛ͍ͯ͠· ͢ɻ w 1SFTFOUFSΫϥεΛQSPWJEFSTʹࢦఆ͍͠·͢ɻ w <ิ଍>͜͜Ͱ͸Ϣʔεέʔεͷ*'ʹґଘ͍ͯ͠· ͕͢ɺϢʔεέʔεͷ*'Λ੾Βͣʹ۩৅Ϋϥεͷ ࢦఆͰ΋໰୊͋Γ·ͤΜɻ w *'ʹґଘ͍ͤͯ͞Δͷ͸$POUSPMMFSͷςελ ϏϦςΟΛ޲্ͤ͞ΔͨΊͰ͢ɻ ϨΠϠʔڥքΛߏ੒͢Δ ΠϯλʔϑΣʔεΞμϓλ૚ 1SJNBSZ"EBQUPS @Module( { imports: [UseCaseModule] , controllers: [CatController] , providers: [CatPresenter] , } ) export class AdaptorWebApiModule { }

Slide 26

Slide 26 text

w ࠷ऴతʹ"QQ.PEVMFͰࠓ·Ͱ࡞੒ͨ͠.PEVMF ΛJNQPSU͠·͢ w ηΧϯμϦʔΞμϓλ͸6TF$BTF.PEVMFͰ JNQPSU͞Ε͍ͯΔͨΊ͜͜Ͱ͸ෆཁͰ͢ɻ w "QQ.PEVMFΛ/FTU'BDUPSZDSFBUFʹ౉ͯ͠׬ ੒Ͱ͢ɻ ϨΠϠʔڥքΛߏ੒͢Δ "QQ.PEVMF @Module( { imports: [UseCaseModule, AdaptorWebApiModule] , } ) export class AppModule { } export async function main() { const app = await NestFactory.create(AppModule) ; await app.listen(80, '0.0.0.0') ; }

Slide 27

Slide 27 text

࠷ޙʹ

Slide 28

Slide 28 text

࠷ޙʹ w ΫϦʔϯͳϨΠϠʔڥքΛ࡞ΔͨΊʹɺґଘؔ܎ٯసͷݪଇΛ׆༻͠ґଘؔ܎Λ஫ೖ͠·͢ɻ w %*ίϯςφΛ࢖͏ͱɺ࣮૷ͱઃఆΛ෼͚ͯґଘؔ܎ͷ഑ઢ͕Ͱ͖·͢ɻ w /FTU+4ͷ.PEVMFTΛ࢖͑͹ґଘؔ܎ͷ஫ೖͷ෼ׂ౷࣏͕ՄೳͰ͢ɻ w ࠓճ͸ϨΠϠʔผʹ഑ઢͷ෼ׂ౷࣏Λ͠·ͨ͠ɻ w αϯϓϧίʔυ͸ҎԼ w IUUQTHJUIVCDPNLJNVUZBNOFTUKTDMFBOBSDIJUFDUVSFUSFF ·ͱΊ

Slide 29

Slide 29 text

࠷ޙʹ w ૊Έํͷߟ͑ํ͸ಉ͡Ͱ͕͢ɺ͜͜Ͱઆ໌ͨ͠ͷ͸ύλʔϯͰ͢ɻ w ϓϩδΣΫτͷঢ়گ΍ϓϩμΫτͷಛ௃ʹΑͬͯͲ͏͍͏ߏ੒ʹ͢Δ͔͸ݕ౼͠·͠ΐ͏ɻ w ͨͩ͠ɺߏ੒Λ૊Ή্Ͱͷߟ͑ํ͸ಉ͡Ͱ͢ɻ w lΞʔΩςΫνϟͷϧʔϧ͸ͲΕ΋ಉ͡Ͱ͋Δʂz˞ ஫ҙॻ͖ ˞3PCFSU$.BSUJO ʰ$MFBO"SDIJUFDUVSFୡਓʹֶͿιϑτ΢ΣΞͷߏ଄ͱઃܭʱʮংจʯΑΓ

Slide 30

Slide 30 text

࠷ޙʹ 8FBSF)JSJOH w ΤϯδχΞʹؔͯ͠ଟ͘ͷٻਓ͕͍͟͝·͢ɻ˞ w όοΫΤϯυʹؔͯ͠΋5ZQF4DSJQUΛओཁݴޠͱ ͨ͠ืू࿮΋͋Γ·͢ɻ˞ w 8FCͷϑϩϯτΤϯυ͸5ZQF4DSJQUΛར༻͍ͯ͠ ·͢ɻ˞ IUUQTIFSQDBSFFSTWLBLFIBTIJ ˞ొஃ࣌఺Ͱͷٻਓ৘ใͰ͢ɻ