Solet's firsttake a lookatthecleanarchitectureasitwasproposedbyUncleBob.
ではまず、ボブおじさんが提案したクリーンなアーキテクチャを見てみよう。
Soitlookssomethinglikethisandreallyitdoesn't tellusmuchwhenitcomestoFlutterbecauselikewhatis a controller, whatispresenter, gateway, whatisallofthat, itjustspitsout a bunchofabstractionsinourfaceandallinallit's a bitabstract, punintended.
Soloandbehold, becausenow I willintroducetoyoutheResocoder's Fluttercleanarchitectureproposal, yesit's anofficialthingnow, whichwilldemonstratesomething, should I saymoreimportantthanjustsomedependencyflowandtheonion, itwillshowyouthedataandcallflow.
ResocoderのFlutterクリーン・アーキテクチャの提案を紹介する。
Itmayseemlikethere's a lottocomprehendherebutdonotworry, wearegoingtogetthroughthisslowlyonebyone.
理解することがたくさんあるように見えるかもしれないが、心配しないでほしい。
Sothecorethinghereisthatthewholeapporshould I sayeverycorefeatureofanapp, likeforexamplegettingnumbertrivia, willbedividedintothreeparts, threelayers, presentation, domainanddata.
Soinsidethelibfolderwearegoingtostartoffwithcreating a featuresfolderbecauseeveryfeatureas I saidwillhaveitsownfolderwhichwillbedividedintopresentation, domainanddata.
libフォルダーの中にfeaturesフォルダーを作るところから始めましょう。
Solet's justcreatethefoldersandthen I willexplaineverythingmoreindepth.
では、フォルダーを作成してから、さらに詳しく説明しよう。
Sothefeaturenamewillbesimplynumbertrivia.
というわけで、特集名は単に数字のトリビアとなる。
Youcanhavefeaturelikeloginorregistrationorsomethinglikethat, youcanhavefeaturesettingsandsoonifyouhavethosethingsinyourapp, wehavejustonescreennumbertriviaandthat's it.
Sopresentationiscomprisedofwidgetssothisiswhereallofthepagesliveforexamplenumbertriviapageandthisisalsowhereyouwillhaveyourowncustomwidgetsandthenitalsohassomethingcalledpresentationlogicholderswhichiseither a block, a changenotifierorreallyanythingwhichyouwouldclassifyasstatemanagement.
Youcanevengothegoodoldstatefulwidgetroutebut I wouldreallyrecommendyoutoatleastgoforchangenotifierbut I reallythinkthatblockisthebeststatemanagementoptionforflutterouttherebutreallypresentationlogicholdersthey'renotallthatimportantwhichyouchoose.
Thenextlayerwearegoingtotake a lookatisthedomainlayer.
次に見ていくのはドメイン層だ。
Asyoucanseeinthiscallflowarrowthecallflowwillhappenfromtheupwardlayersopresentationdownsothispresentationlogicholderforexample a blockwilldelegateitsworkandcallusecaseswhicharefromthedomainlayer.
Itwillcontainonlythecorebusinesslogicwhichwillbeexecutedinsideusecasesandthenalsobusinessobjectswhichwearegoingtocallentitiesandbythewayusecasesareclasseswhichencapsulateallthebusinesslogicof a particularusecaseoftheappsoforexamplewewillhaveusecasesforgettingconcretenumbertriviarightherewhichwillbeexecutedwheneverwepressthesearchbuttonheresothisisgetthosewillbetwoclassesgetconcretenumbertriviaandgetrandomnumbertrivia.
Ofcourseinourappwewillnothave a lotofbusinesslogicandeventheentitywhichwillholdthenumbertriviaactuallytheyaregonnabeprettyleanclassesbecausewearenotdoingmuchinthisexampleappbutinyourownprojectswhenyouarebuildingsomethingmoresubstantialthedomainlayeriswherethebulkofthecodewillbelocatedandifyou'vebeenlisteningtomecarefully I'vesaidthatthedomainlayershouldbecompletelyindependentofeveryotherlayer.
Well I knowthatyouprobablycannottellmuchjustfromthisdiagrambutitseemsthatthedomainlayerisindependentofthepresentationlayerbuthereitgetskindoffancylookingbecausetherepositoryisseeminglyinsidethedomainlayerandalsointhedatalayerrightsowhat's upwiththathalfoftherepositoryisdomainandhalfisindatanothat's nothowitis.
I knowthatyoumaybegettingsomegoosebumpsbecausethey'rejustscarywordsbutdependencyinversionisinessenceveryverysimpleandstraightforwardit's just a fancywayofsayingthatwecreateanabstractclassrepositorywhichwilldefine a contractofwhattherepositorymustdosoforexampleinourappwewillhave a repositorywhichmustprovideuswithrandomtriviaandconcretenumbertriviathosearethetwothingswhichtherepositoryjustmustdoandthatgoesintothedomainlayer.
Thedomainlayerdoesnotcarehowthenumbertriviawillbegottenitjustcaresthatitwillbegottenrightthisisallpossiblewithaninterfaceorbecausedartdoesnotsupportinterfaceswehavetouseabstractclassesandthentheothersideofthecoinorinthiscaserepositoryisinsidethedatalayerthedatalayerwilldefinehowthedatawillbegottenandmanagedandallofthatwe'regettothatinjust a shortwhilebuttheimportantthingisthattherepositoryinthedatalayerwillimplementtheabstractclasssoitwillhavetoconformtotheso-calledcontractsothatdomaincanreallynotcarewhat's goingonbehindthescenesitjustknowswhatkindofdataitwillalwaysreceivefromtherepositoryinthiscaseitwillbethenumbertriviasolet's createthefolderstructureshallweinsideVSCodethedomainlayerwillhavethreesubfoldersentitieswhichwillbethenumbertriviaentitywhichwillsimplyholdthetextofthetriviaandthenumberofthenumbertriviathenwewillhavealsoanothersubfolderrepositoriesthisiswherethecontractortheabstractclassofrepositorywillgoandthenalsothelastfolderisusecasessousecasesaregetconcretenumbertriviaandasyoucanseetherewassomeserverfailurenowsoerrorhandlingworkscorrectlybut I don't knowwhytherewas a serverfailurebutanywaynowwehave 42 sothisistheconcreteorgetconcreteusecaseandwealsohavetherandomusecaseandlet's nowmoveontothedatalayerasyoualreadyknowitcontainsrepositorieswhichimplementtheabstractclassesfromthedomainsothattheywillhavetojustfulfillthecontractdefinedbydomainandthenitalsocontainsremotedatasourceslocaldatasourcesanykindofdatasourcesobviouslygointothedatalayerusuallyyouhaveonedatasourceforgettingremotedatafromtheAPIandthenyoualsohaveanotheroneforgettinglocaldatainourcasewewillusesharedpreferencestocachethedatalocallyandlocaldatasourcesarealsowhereyouwouldhaveyourforexampleGPSlocationcodeandallofthatgoodstuffdatasourcesdonothavetojustoperatewithdatabasestheycanalsooperatewiththeunderlyingplatformordeviceandtherepositoryisthebrainsofthedatalayerbecausethisrepositorywilldecidewhentocache, whattocache, whentogetdatafromtheremotedatasource, whentogetdatafromlocaldatasourcesoforexampleifthereisnointernetconnectionwedefinitelywanttogetdatathecacheddatafromlocaldatasourcesandyoumaynoticethatrepositoriesoutputentitieswhichkindofmakessenseandagainentityisjustthenumberandthetextofthenumbertriviareallysimpleinourcasebutdatasourcesdonotoutputentitiestheydealwithsomethingcalledmodelsandthisnomenclatureisreallynotallthatimportantitdoesn't matterhowyoucallthesethingsit's justthatyouknowwhatthosenamesmeanandthereasonbehindhavingmodelsisthattransformingrawdatawhichisforexampleJSONrequiressomeconversionlogicbecausewecannotworkwithJSONinourappwehavetoDartobjectsbutnowlet's thinkaboutthiswedefinitelydonotwanttoputourJSONconversionlogicsotoJSONandfromJSONasweareallusedtoforexamplefrombuiltvalueorJSONserializablewedonotwanttoputthoseconversionmethodsintoentitiesandwhyisthatwellentitiesshouldbecompletelyplatformanddatalayerindependentsoforexampleifweswitchfromJSONtoXMLortosomebinarydatacrazinesswedonotwanttochangethedomainlayeratallweonlywanttochangethedatalayerwhensomethingdatarelatedchangesbutthedomainshouldremainuntouchedthereforethesemodelswillbesimpleclasseswhichextendentitiesandaddsomefunctionalityontopofthemandbecausetheyaresubclassesofentitieswecanthensimplycastthemintoentitiesandtherepositorywilloutputtheentitywhichdoesnothaveanyadditionalfunctionalityorfieldsaddedontopofitinthenumbertriviaappsincewedonothaveanythingreallydifficulttodomodelswillhaveonlytoJSONandfromJSONmethodsbutifyouarestoringsomethinglocallyinansqlidatabaseandforsomereasonyouhavetohavetheidinsidethedatabasestoredinsidethemodelyoucanalsoaddsomecustomfieldstothemodelnotjustmethodsinourapptheremotedatasourcewillperformanHTTPgetrequesttonumbersAPIwhichissimplynumbersapi.comandalloftheselinksandallofthatwhich I amexplaininghereisalsoavailablefromthewrittentutorialsodefinitelycheckthatoutbuthereisnumbersapi.comthisistheAPIwewillbeusingsoasyoucanseewecangetrandomtriviarightthisiswhatwearedoingfromwithintheappsothisiswhattheremotedatasourcewilldoitwillperformgetrequestsandthenwehavealsolocaldatasourcewhichwillsimplycachedatausingthesharedpreferencespackageandthenthesetwodatasourceswillbejust a simplethingitwillcheckwhetherornottheuserisconnectedtotheinternetifthereisinternetconnectionitwillalwaysprefertogetfreshdatafromtheremotedatasourceifthereisnointernetitwillgetthecacheddataanditwillalsohave a simplecachinglogicwhichisthatwealwayscacheeverythingassoonasit's gottenfromtheAPIsothatifthereisnointernetconnectionitwillalwaysreturnthecacheddatathelastcacheddatatobepreciseallrightsolet's nowcreatethefolderstructureevenforthedatalayerbecausethethingsbelowarenotactually a partofourappthesearesomeexternalthingswedonotcareaboutthemit's not a partofourcodebaseandthedatalayerwillbecomprisedofdatasources, modelsandfinallyimplementationsofrepositoriessotherepositoriesfolderindatawillholdimplementationsandtherepositoriesfolderindomainwillholdtheabstractclassesorinterfaceswhicharethecontractswhichtherepositoriesimplementedindatamustfulfillandagainthisabstractionisnecessarysothatthedomainlayercanbecompletelyindependentofeveryotherlayerallrightsothisfirstpartofthistestdrivendevelopmentcleanarchitecturefluttercoursewasreallytheoryheavythat's becausesomethinglikecleanarchitecturerequires a lotofexplanationbecauseafterallyoucannotjuststartbuilding a housewithoutfirstplanninghowthehousewilllooklikeyouhavetohaveatleastsomebasicstructuresomebasicdrawingsinplaceandthesedrawingswerelaiddowninthisfirstpartsointhenextpartswearegoingtoactuallygetcodinganddoingtestdrivendevelopmentandwearegoingtostartoffwiththisdomainlayersoifyoudonotwanttomissthattutorialandmoreothertutorialslikethisdefinitelysubscribetothischannelandalsojointhenotificationsquadbyhittingthebellbuttontomakesureyougrowyourflutterskillsbecausehereonresocoder i amdeterminedtoprovideyouwiththebestappdevelopmenttutorialsandresourcesouttherealsomakesuretocheckoutthewrittentutorialavailablefromthelinkinthevideodescriptiontogothroughallofthisatyourownpaceyouwillhighlybenefitfromreadingthewrittentutorialifyouwanttolearnthemostaboutcleanarchitecturewhich i'm sureyouwanttodoifthisvideohelpedyouwithclearingtheconceptsofcleanarchitecturegiveit a likeandalsoshareitwithourdeveloperswhowillsurelybenefitfromthistoofollowmeoninstagram i gounderthenameresocodereverywhereleave a commentifyouhaveanythingtosayanysuggestionsorquestionsstaytunedforthenextpartinwhichwearegoingtofinallystartwritingcodedoingtest-drivendevelopmentandseeyouinthenextvideoyou