3人ã®ããã°ã©ããŒããã£ãŒã«ãã暪æããå察åŽã®å®¶ã«çãããã«é ŒãŸããŸããã åå¿è ããã°ã©ããŒã¯çãè·é¢ãèŠãŠããããã¯ããé ããªãïŒ 10åããããŸããã çµéšè±å¯ãªããã°ã©ããŒããã®åéãèŠãŠããã°ããèããŠãã1æ¥ã§ããã«çãããšãã§ããããšèšã£ãã æ°äººã¯é©ããŠåœŒãèŠãã ãœãããŠã§ã¢ã®ç¬¬äžäººè ã¯ãã®åéãèŠãŠèšã£ãã ã10åã»ã©ã§ããã15åã§ååã ãšæããŸããã çµéšè±å¯ãªããã°ã©ããç¬ã£ãã
åå¿è ããã°ã©ããŒã¯åºçºããŸããããæ°å以å ã«å°é·ãççºãå§ãã倧ããªããããæ®ããŸããã ççºããã圌ã¯æ»ã£ãŠé£ãã ããããŠåœŒã¯æåããããçŽããªããã°ãªããªãã£ãã ç®æšãéæããã®ã«2æ¥ããããŸããã ããã«ã圌ã¯è³ãæã§æºããå°çãããšãã«è² å·ããŸããã
çµéšè±å¯ãªããã°ã©ããŒãåã€ãcããããŸããã å°é¢ãåªããææ¢ãããé±å±±ãæ¢ããŠãå®å šã ãšç¢ºä¿¡ããå Žåã«ã®ã¿ç§»åããŸããã ãã£ãããšæ³šææ·±ã圌ã¯æ¥äžã«çãæž¡ã£ãã æ°åãã£ãã ãã§ãã
ããã°ã©ããŒã®ç¬¬äžäººè ã¯åºçºãããã£ãŒã«ãããŸã£ããã«è¡ããŸããã æå³çãã€çŽæ¥çã 圌ã¯ããã10åã§ç®æšãéæããŸããã
ããããã©ã®ããã«ç®¡çããŸãããïŒãä»ã®2人ã«å°ããŸããããã©ããã£ãŠåäžã®é±å±±ãåŒã£æããªãããã«ããã®ã§ããïŒã
ãç°¡åããšåœŒã¯çããã ãç§ã®éã«å°é·ãæ·ããŸããã§ãããã
æ®å¿µãªãããç§ã¯èªããããåŸãŸãã-ç§ãã¡ã¯èªåã®å°é·ãæ·èšããŠããŸãã æåã®éšåã§ã¯ããœãããŠã§ã¢éçºã®äž»ãªãªã¹ã¯ã詳现ã«èª¿ã¹ããããã®ãªã¹ã¯ã軜æžããæè¡çããã³æ¹æ³è«çãªæ¹æ³ã«ã€ããŠèª¬æããŸããã éå»1幎éãç§ã¯å€ãã®ã³ã¡ã³ããåãåããŸããããã®äž»ãªæå³ã¯æ¬¡ã®ãšããã§ããïŒããã¹ãŠãã¯ãŒã«ã§ãããã©ãããå§ããŠãå®éã®äžçã§ã©ã®ããã«èŠããããã å®éãæåã®ããã¹ãã¯ããçè«çãªæ§è³ªã®ãã®ã§ããããªã³ã¯ã®ã«ã¿ãã°ãè¡šããŠããŸãã ãã®èšäºã§ã¯ãã§ããã ãå€ãã®äŸã瀺ããŸãã
ååãªçµéšããªãããã°ã©ããŒã®å Žåã æåã®èšäºã§èª¬æããåé¡ã®å€ãã¯ãé·ãç®ã§èŠãã ãã§ç解ã§ããªãå¯èœæ§ããããŸãã10ããŒãžã«ãµã€ããèšè¿°ããæ¹æ³ãšããã£ã«ã¿ãªã³ã°çšã®ããã€ãã®ãã©ãŒã ãšCRUD管çããã«ã«å€§ããªéãã¯ãããŸãããã¹ãŠã®ã³ãŒãã¯æ°æ¥ã§ãŒãããæžãçŽãããšãã§ããŸãã ãããã1幎åã2幎ã§äœãèµ·ããã§ããããïŒ
ç§ãã¡ã®ãµã€ãã¯éçºãéå§ããæ°ããæ©èœãç»å Žãããã§ã«æ°åã®ããŒãžãšãã©ãŒã ããããå€éšãªãœãŒã¹ãšã®ã¢ãã£ãªãšã€ãããã°ã©ã ãè¿œå ãããŠããŸãã 倧å¯è±ªãVkontakteãã«åºåãåºããããŒãäžã«ã¡ã€ã³ããŒãžããéçºãããŸããã é¢ä¿ãããŸããããã£ãã·ã¥ã«ãšã©ãŸããŸãã ä»ãããªãã¯ããã«ãã¬ã³ããªãŒãªãµãŒãã¹ãšææºããå¿ èŠããããŸãã ã³ãŒãããŒã¹ããããŒãããŒãšçµ±åã³ãŒããã³ããŒããŠè²Œãä»ãããç§ãã¡ã®ãããŒã¿ãšãå€éšã®ãããŒã¿ãåæããããã®ãã¡ã€ã«ãäœæããŸãã
å€æŽã¯ããžãã¹ã«ãŒã«ã§å§ãŸããã¹ãã¬ãŒãžã®ã³ãŒããšãµããžã§ã¯ããšãªã¢ã§è€è£œããå¿ èŠããããã¡ã€ã³ããŒãžã®ãã£ãã·ã¥ãå®æçã«æŽæ°ããå¿ èŠããããããã¯ãã°ã®ãã°ãšæ§æã®åé¡ã®æ°ãå¢ããŠããŸãã
ããžãã¹ã«ãŒã«ã®å€æŽãçµ±åãããã©ãŒãã³ã¹ã®æé©åãæ©èœã®æ¡åŒµã6ã7åç¹°ãè¿ããã¹ã¿ãã¯ãªãŒããŒãããŒãããŒãããŒã®SDKã³ãŒããæŸèæããããããããããŸããŸãªéåžžã«åœ¹ç«ã€ãµãŒãããŒãã£ã®ã³ã³ããŒãã³ããããã³ç¬èªã®èªè»¢è»ãããªããµã³ãã«ã³ãŒããããã©ã³ã±ã³ã·ã¥ã¿ã€ã³ã¢ã³ã¹ã¿ãŒãäœæããŸããã
2-3幎åã®ã³ãŒãã§ä¿®æ£ããªããã°ãªããªãäž»ãªåé¡
- å®åã³ãŒãã®ç¹°ãè¿ãïŒäœ¿çšãtry-catchãlogãªã©ïŒïŒã³ãŒãããŒã¹ã®å€æŽãä¿®æ£ãå°é£ã«ãªããåãæ§æãæžãã®ã«éãã«æéãããããŸãïŒãããžã§ã¯ãã®æåã®æ°ç§ã1幎ãŸãã¯2æ¥åŸïŒã³ãŒãããŒã¹ã®ååšïŒ
- åãEntityãDTOãããã³ViewModelã¯ã©ã¹ã®æé»çã§æãããã®ãªãäœæãLinqã¯ãšãªã®è€è£œãåãã¿ã€ãã®ITEntityRepositoryã®äœæãå«ãã³ãŒãã®éè€ïŒå®è£ ã1ã€ãããªãIRepository <TEntity>ã€ã³ã¿ãŒãã§ã€ã¹
- SRPã®éåïŒç°ãªãã³ã³ããã¹ãããã®ãšã³ãã£ãã£ããããã£ã®è©°ã蟌ã¿ããã¡ã€ã³ã¢ãã«ãšã¯é¢ä¿ãªããããŸããŸãªãããŒãžã£ãŒããµãŒãã¹ããã«ããŒãæ確ãªè²¬ä»»ã§äœæãã
- LSPéå
- NullReferenceException
- ããŒã¿ãšã©ãŒ
- ãã£ãŒãããã¯ã®äœæãã¢ããªã±ãŒã·ã§ã³ã¬ã€ã€ãŒãã€ã³ãã©ã¹ãã©ã¯ãã£ã³ãŒãããã¡ã€ã³ã¢ãã«ã³ãŒãã®æ··å
éåžžããã®ãã¹ãŠã®æãã®æ£åœåã¯æ¬¡ã®ãšããã§ãã
- ã¿ã€ããªãªãªãŒã¹æ¥
- ãªãã¡ã¯ã¿ãªã³ã°ããæéããªã
- èšç»ãšèšèšã®æéäžè¶³ïŒã©ã®ã¢ãŒããã¯ãã£ã§ããïŒ
äžè¬ã«ãããã¯ãã¹ãŠçå®ã§ãããçµéšè±å¯ãªéçºè ã§ãããé©åãªæ±ºå®ãè¿ éã«äžãã®ã«ååãªããããéšåãããªãããšãå€ãããšãèªããªããã°ãªããŸããã ãæ¬åœããšããããšã§ãç§ã¯æ¬¡ã®ç¶æ³ãç解ããŠããŸãïŒ80ïŒ ã®å Žåãããžãã¹ã±ãŒã¹ãå®è¡ããã³ãŒããèšè¿°ãã20ïŒ ã®å Žåãç¹å®ã®20ïŒ ãèšè¿°ããå¿ èŠãããïŒã€ãŸããèŠä»¶ãã©ã®ããã«å€åãããïŒãæšæž¬ãããã³ã«ãå°ãå ãè¡ã£ãŠããŸãã å©å®³é¢ä¿è ãæããã®ïŒã¢ããªã±ãŒã·ã§ã³ã®ãã¡ã€ã³ã¢ãã«ãã©ã®ããã«å€åãããïŒãæšæž¬ããã«ã¯ãéåžžã管çäœæ¥ã®çµéšããã³/ãŸãã¯ãµããžã§ã¯ããšãªã¢ã®çµéšãå¿ èŠã§ãã
ãã ããå€ãã®æé·äžã®ãããžã§ã¯ãã§çºçããå€ãã®èŠä»¶ããããŸãã
- ãã«ããŠãŒã¶ãŒã¢ã¯ã»ã¹ïŒæªåé«ãhabrå¹æïŒããã¥ãŒããããïŒãªã©ã®ã«ãŠã³ã
- åæãšããŒãœãã©ã€ãŒãŒã·ã§ã³ïŒè²©å£²ãã¡ãã«ã®æ§ç¯ãããé¢é£æ§ã®é«ãã³ã³ãã³ããæäŸããããã®ãŠãŒã¶ãŒèšå®ã®åæïŒ
- å šææ€çŽ¢
- ã¹ã±ãžã¥ãŒã«ãããã¿ã¹ã¯ãšã¹ã±ãžã¥ãŒã«ãããã¿ã¹ã¯
- ããŒã¿ã®ãã£ã«ã¿ãªã³ã°ãå€æãããã³ããŒãžã³ã°
- ãã®ã³ã°ãéç¥ã·ã¹ãã ãç£èŠãèªå·±èšºæãé害ããã³ãšã©ãŒåŠçåŸã®èªå·±å埩
ãã®èšäºã§ã¯ãã¢ããªã±ãŒã·ã§ã³ã€ã³ãã©ã¹ãã©ã¯ãã£ãããã¡ã€ã³ïŒããžãã¹ã«ãŒã«ïŒãåé¢ããããšã«çŠç¹ãåœãŠãŸãã ãã¹ãŠã®AOPãåçã³ã³ãã€ã«ãããã³ãã®ä»ã®éæ³ã¯æ¬¡åã«æ®ãããŸãã
10ã®ã¢ããªã±ãŒã·ã§ã³å±€ã§ãã¹ãŠã®äººã«ååãªã¯ãã§ã
ãç空äžã®éåžžã®Webã¢ããªã±ãŒã·ã§ã³ãã®å Žåãæ倧10å±€ãã«ãŠã³ãããŸããã ããã¯ããããã§ããããããšãå°ãã§ããïŒ ãã³ãŒããŒãã«ãããããŠå€å žçãª3ã€ã§ããŸãããããšãã§ãããšããã°ãããã¯ã¡ããã©ãããšæããŸãã ãšã³ããã€ã³ããããŒã¿ããããŒããããªãã·ã£ãŒãµãã¹ã¯ã©ã€ããŒãã€ã³ãã¬ã»ãã¿ãŒãæšå¥šããŸãã æ®ãïŒ
- ãµãŒãã¹
- ã³ãã³ã/ã¯ãšãª
- ãšã³ãã£ãã£
- DAO
ãã¹ãŠãé©åãªå Žæã«é 眮ããããã«ãWebã¢ããªã±ãŒã·ã§ã³ã®æãåçŽãªã±ãŒã¹ã§ããã©ã³ãã£ã³ã°ããŒãžããå§ããŸãããã
ã©ã³ãã£ã³ã°ããŒãžïŒããšãã°ããã©ã³ãã£ã³ã°ããŒãžãïŒ-ç¹å®ã®æ¹æ³ã§æ§ç¯ãããWebããŒãžããã®äž»ãªã¿ã¹ã¯ã¯ã察象ãŠãŒã¶ãŒã®é£çµ¡å æ å ±ãåéããããšã§ãã åºåã®å¹æãé«ããèŠèŽè ãå¢ããããã«äœ¿çšãããŸã...
1ããŒãžãããããªãŒãããåéããŸãã ãªãŒãã«ã¯ã¡ãŒã«ãå¿ èŠã§ãã ãã©ãŒã ã®ãªãã·ã§ã³ã®ãã£ãŒã«ãã¯ãé»è©±çªå·ãšååã§ãã ã¯ã©ã¹ãleadããäœæããŸãããïŒ
public interface IEntity { string GetId(); } public class Lead : IEntity { public static Expression<Func<Lead, bool>> ProcessedRule = x => x.Processed; private string _email; [Key, Required, Index("IX_Email", 1, IsUnique = true)] public string Email { get { return _email; } set { if (string.IsNullOrEmpty(value)) { throw new ArgumentNullException("email"); } _email = value; } } public string Phone { get; set; } public bool Processed { get; set; } public DateTime CreatedDate { get; set; } [Obsolete("Only for model binders and EF, don't use it in your code", true)] internal Lead() { } public Lead([NotNull] string email, string phone = null) { Email = email; Phone = phone; CreatedDate = DateTime.Now; } public bool IsProcessed() { return this.Is(ProcessedRule); } public string GetId() { return Email; } }
ãšã³ãã£ãã£ããªãããã¡ã€ã³ã¢ãã«ãããã³é²åŸ¡ããã°ã©ãã³ã°ïŒå¥åã«ãã»ã«åïŒ
è«äºïŒ samolisov.blogspot.ru/2012/10/anemic-domain-model.htmlç§ã¯ãªãããã¡ã€ã³ã¢ãã«ïŒãªãããã¡ã€ã³ã¢ãã«ïŒã®æ¯æè ã§ããã貧è¡ã奜ãã§ã¯ãªããããLeadã¯é©åãªã³ã³ã¹ãã©ã¯ã¿ãŒãæã¡ãççŸããç¶æ ïŒäžå€æ¡ä»¶ã«éåïŒã«é¥ãããšãèš±å¯ããŸããã ç¥å ã貧è¡ã¢ãã«ãçã¿åºããçŸä»£ã®ORMãã¬ãŒã ã¯ãŒã¯ã«ãããã«ãã»ã«åã®åçã芳å¯ããããšãã§ããŸãïŒã»ãšãã©ïŒã å éšã¢ã¯ã»ã¹ä¿®é£Ÿåã圹ç«ã¡ãŸãã ç¹ã«ãæãæŽãããããã©ã«ãã§ã³ã³ã¹ãã©ã¯ã¿ãŒã䜿çšããªããŠãŒã¶ãŒã«ã¯ããã¡ã€ã³ã¢ã»ã³ããªå ã«[Obsolete]å±æ§ããããŸãã 2çªç®ã®ãã©ã¡ãŒã¿ãŒã¯ããã®ã³ã³ã¹ãã©ã¯ã¿ãŒãæ瀺çã«äœ¿çšããããšãããšãã«ããäžæããŸãããORMãšModelBinderã¯ãã®ã³ã³ã¹ãã©ã¯ã¿ãŒãå·éã«äœ¿çšããŸãã
[Obsolete("Only for model binders and EF, don't use it in your code", true)] internal Lead() { } public Lead([NotNull] string email, string phone = null) { Email = email; Phone = phone; CreatedDate = DateTime.Now; }
ãžã¥ãã¢ããããåé€ããªããšããä¿èšŒã¯ãããŸãããããã®ãããªããšã¯ã³ãŒãã¬ãã¥ãŒäžã«è§£æ±ºã§ããŸãã
.NETã®ããããã£ã¯ãããŒã¿ããŒã¹ã«ãããããããã ãã§ãªããçºæãããŸããã ãã®ãããªã³ãŒãã®ç·šæã«ãããããŒã¿ããŒã¹ã«ä¿åãããšãã§ã¯ãªããééã£ãé»åã¡ãŒã«ãèšå®ããããšããå Žæã«æ£ç¢ºã«åãŸããŸããããã¯ãå€ãèšå®ãããç¬éãããç¹ã«å€§èŠæš¡ãªæäœäžã«éåžžã«é ãããšããããŸãã
[Key, Required, Index("IX_Email", 1, IsUnique = true)] public string Email { get { return _email; } set { if (string.IsNullOrEmpty(value)) { throw new ArgumentNullException("email"); } _email = value; } }
ã³ã³ã¹ãã©ã¯ã¿ãŒã¯Emailããããã£ã䜿çšãããããäžå€åŒã¯ç¢ºå®ã«ä¿è·ãããŸãã
ãã®æ¹æ³ã§äœæ¥ããæ¹ãç°¡åãªã®ã§ãã«ãŒã«-ã³ãŒããã¡ãŒã¹ãã ãŸãããã¡ã€ã³ã¢ãã«ãäœæãã次ã«èªå移è¡ãäœæãïŒãããã£ãŠãEntity Frameworkã䜿çšïŒãå®è¡ããŸãã
ç§ã®èŠ³ç¹ãããããšããã©ã¡ãŒã¿ãŒã®ãªãã³ã³ã¹ãã©ã¯ã¿ãŒãžã®ã¢ã¯ã»ã¹ãpublicïŒpublicïŒã«çœ®ãæããŠãåãã¿ã€ãã®äžèŠãªDTOãšViewModelãäœæããã«ãã®ããã«èšè¿°ããããšã¯æ¥ãã¹ãããšã§ã¯ãããŸããã
[HttpPost] public ActionResult Index(Lead lead) { if (!ModelState.IsValid) { return View(lead); } //⊠}
æ¡ä»¶ã®äžã§ïŒ
- ãªãŒãã¯ã©ã¹ã¯éçŽã®ã«ãŒãã§ã¯ãããŸãã
- ã¢ããªã±ãŒã·ã§ã³ãã©ãŒã ã«ã¯ããªãŒãã¯ã©ã¹ãš1察1ã®ãããã³ã°ããããŸãã
- ãã©ã¡ãŒã¿ãŒãªãã®ã³ã³ã¹ãã©ã¯ã¿ãŒã¯ãObsoleteå±æ§ã«ãã£ãŠä¿è·ãããŠããŸã
ãã以å€ã®å Žåã¯ãDTOããã³/ãŸãã¯ViewModelãäœæããDataMapperã䜿çšããŸãã
ãã¶ãã¢ãã
Visual Studio 2015ãCTPã«æ°ããæŒç®åãæ®ãéãããã®ã¢ããã¯ã³ãŒããèªã¿ãããããã®ã«åœ¹ç«ã¡ãŸãã RïŒã®ãšã©ãŒãšããŠãJetBrains.Annotationsããã³NullReferenceExceptionã®å¯èœæ§ãšçµã¿åãããŠMaybeã䜿çšãããšãã³ãŒãã«NullReferenceExceptionãååšããªãããšãä¿èšŒãããŸãã å®éãããã¯NullObjectãã¿ãŒã³ã®æ©èœçãªã¹ã¿ã€ã«ã®å®è£ ã§ããããžãã¹ããžãã¯ãšã€ã³ãã©ã¹ãã©ã¯ãã£ïŒDDDïŒã®åé¢
DDDããããäž»ãªè«äºã¯ã次ã®ç¹ãäžå¿ã«å±éãããŸãã- ãããã¯ãŒã¯äžã®DDDã§å ¬éãããŠããã¢ã¯ã»ã¹å¯èœãªäŸãå°ãªãããããããããäœã§ãããã¯æ確ã§ã¯ãããŸãã
- ãã¡ã€ã³ãšèŠãªããããã®ãšã€ã³ãã©ã¹ãã©ã¯ãã£ãšã¯äœã§ãã
- DDD-op-opãready codeæ¹æ³è«ãšæ¯èŒããŠéåžžã«é·ãé«äŸ¡ã§ã
Evansã®æ¬ãèªãããšã¯ã The Art of Unit Testingã«ç¶ããŠãã³ãŒããç解ããäžã§ç§ã«ãšã£ãŠ2çªç®ã®æ¥è»¢ã§ããã ãœãããŠã§ã¢éçºã®10幎éãç§ã¯ååãªæ°ã®ã³ãŒãããŒã¹ãååã«åŸãããšãã§ããŸããã ãããããããšã«ããã¹ãŠã®ããã°ã©ãã³ã°èšèªã«ã¯ãã§ã«åºæ¬çãªãã©ãããã©ãŒã ïŒãã¬ãŒã ã¯ãŒã¯ïŒãšããã±ãŒãžãããŒãžã£ãŒãããããã©ãã¯ãžã£ãã¯ãšé女ã§MVCãã¬ãŒã ã¯ãŒã¯ãèšè¿°ããããšã¯èª°ã«ãèµ·ãããŸããã
ãã ããããžãã¹ããžãã¯ã¯ãã¢ããªã±ãŒã·ã§ã³å ã®ããŸããŸãªå ŽæïŒã¹ãã¢ãããã·ãŒãžã£ããã«ããŒããããŒãžã£ãŒããµãŒãã¹ãã³ã³ãããŒã©ãŒæ¬äœããªããžããªãlinqã¯ãšãªïŒã§èŠã€ããããšãã§ããŸãã æ確ãªèŠå¶ããªãå Žåãåéçºè ã¯ãçŸãããã®ã«ã€ããŠã®ã¢ã€ãã¢ã«åŸã£ãŠããžãã¹ããžãã¯ãç·šæããŸãã
ããã¯åé¡ã®å šäœãäœæããŸãïŒ
- ããžãã¹ã«ãŒã«ãæ¢ãå Žæãæ確ã§ã¯ãªã
- ãã¡ã€ã³ã¢ãã«ã³ãŒãã®ãã¹ãã«ãã¬ããžãšã¯äœããšãã質åã«æ確ã«çããããšã¯äžå¯èœã§ãã
- ã³ãŒãã¯æç¶ãåã¹ã¿ã€ã«ã«åŒãå¯ããããã«ãã»ã«åã¯å£ããŠããŸã
- 2ãæ以äžã§ããžãã¹ã«ãŒã«ãè€è£œããå±éºããããŸãïŒããšãã°ãcïŒã³ãŒããšã¹ãã¢ãããã·ãŒãžã£ã³ãŒããèŠä»¶ãå€æŽãããå Žåã1ãæã®ã¿ã§ã«ãŒã«ãå€æŽãããå¯èœæ§ããããŸãããã®çµæãå·®ç°ã¯æ®ããæ°ãæåŸã«çºçããå¯èœæ§ããããŸããä»ã®äººã¯åé¡ã«ãªããŸããããããã©ã®ããã«ãæ£ããããã¹ããããç¥ã£ãŠãããšããäºå®ã§ã¯ãããŸãããããã«ããããŒãžã£ãŒãšãã«ããŒã¯äžæ確ãªè²¬ä»»ãæã€ã¯ã©ã¹ã§ãããé«ã確çã§æéãšãšãã«ç¥ã®ãªããžã§ã¯ãã«å€ãããŸã
- ã¢ã»ã³ããªéã®äŸåé¢ä¿ã¯äžåèŠå¶ãããŠããŸããã ãžã¥ãã¢ã®è»œéãã¡ã€ã³ã¢ãã«ã¯ã©ã¹ã¯ãWebã³ã³ããã¹ããšCommon.Webã®ã¢ã»ã³ããªã«ç°¡åã«äŸåãå§ããããšãã§ããŸãã
ããé«ãã¬ãã«ã§ã¯ãããã¯æ¬¡ã®ããã«å€æãããŸãã
- ãã«ã¿ã€ã ããŒã å šäœããã°ã®ãµããŒããšãã°ã®é€å»ã«å¿ããç¶æ ãŸã§ãéçºã®ããŒã¹ãé ããã
- 絶ãéãªããã°ä¿®æ£ãšæŸèæ
- ã¢ããªã±ãŒã·ã§ã³ããŒã¿ããŒã¹ã®ãšã©ãŒããµããŒãããã³æé€ããããã«è¿œå ã®ãªãœãŒã¹ãå²ãåœãŠãå¿ èŠããã
ç§ã«ãšã£ãŠãEvans DDDã¯ããžãã¹ããžãã¯ã§äœæ¥ãæšæºåããæ¹æ³ã§ãã DDDã¯ããã®ããã®äžé£ã®ãã¿ãŒã³ãæäŸããŸãã äž»ãªãã®ãèŠãŠã¿ãŸãããã åæã«ãå¥ã®ããã¡ãã·ã§ããã«ãªãã³ã³ã»ããã§ãããCQRSããšãçµå©ãããŸãã
ããã¯DDDãšã©ã®ããã«é¢é£ããŠããŸããïŒ
DDDã¯ããã¡ã€ã³ãå¥åã§ãããã€ã³ãã©ã¹ãã©ã¯ãã£ãå¥åã§ããããšã瀺ããŠããŸãã ããŠãããšã³ãã£ãã£ãããããŸãããšã³ãã£ãã£
public interface IEntity { string GetId(); }
ãšã³ãã£ãã£ã¯ãäžæã®èå¥åãæã€ãã®ã§ãã è¢ã®äžã®2æ¬ã®éã¯ãšã³ãã£ãã£ã§ã¯ãããŸããããªããªããããªãã¯äžæ¹ãä»æ¹ãšåºå¥ã§ããªãããã§ãã ãã¡ã€ã³ã«é¢ããŠã¯ããããã¯åäžã§ãã ããããç§ãã¡ã®çšã®ããã®VasyaãšPetya-ãšã³ãã£ãã£ã çŽçšè çªå·ïŒTINïŒããããŸãã
ææ°ã®ã¢ããªã±ãŒã·ã§ã³ã§ã¯ãæãäžè¬çã«äœ¿çšãããIDã¯èªåã€ã³ã¯ãªã¡ã³ãæŽæ°å€ãŸãã¯GUIDã§ãã ãã®ã¢ãããŒãã®æ®åã«ãããããããå Žåã«ãã£ãŠã¯ãç¹å¥ãªåŠçãå¿ èŠãšããç¶æ³ãäœãåºãããšãã§ããŸãã èªç©ºäŒç€Ÿã®ãã±ãããã¢ã°ãªã²ãŒã¿ãŒããè³Œå ¥ããããšãããå Žåãã¢ã°ãªã²ãŒã¿ãŒã®äºçŽçªå·ã¯èªç©ºäŒç€Ÿã®äºçŽçªå·ãšäžèŽããªãããšããããŸãã ããã¯ããã£ãªã¢ãç¬èªã®ITã·ã¹ãã ãæã¡ãã¢ã°ãªã²ãŒã¿ãŒãç¬èªã®ã·ã¹ãã ãæã£ãŠãããšããäºå®ã«ãããã®ã§ãã
ã©ã³ãã£ã³ã°ããŒãžã«æ»ã£ãŠããµã³ãã«ããªãŒãããŸãããã IEntityã®æãæœè±¡çãªå®è£ ã¯ãIDãæååãšããŠè¿ãã¡ãœããã§ãã ç§ã¯æå³çã«ããããã£ã§ã¯ãªãã¡ãœããã䜿çšããŸãã Leadã¯ã©ã¹ã®ãã¹ãŠã®ããããã£ã¯ãããŒã¿ããŒã¹ãã£ãŒã«ãã«ããããããŸãã ããã«ããããããŸãããé¿ãããããã³ã°ãèŠãå¿ èŠããªããªããŸãã äž»ããŒã¯ãIDã§ã¯ãªãé»åã¡ãŒã«ã§ãã Idããããã£ãå®è£ ããå ŽåãIdããããã£ãããŒã¿ããŒã¹ã®Emailãã£ãŒã«ãã«ããããããŠããããšãæ瀺çã«ç€ºãå¿ èŠããããŸããããã«ãããã«ããä»ã®ã¿ã€ãïŒæŽæ°ãšGUIDïŒã®äž»ããŒã«åé¡ãçºçããŸã
public class Lead : IEntity { private string _email; [Key, Required, Index("IX_Email", 1, IsUnique = true)] public string Email { get { return _email; } set { if (string.IsNullOrEmpty(value)) { throw new ArgumentNullException("value"); } _email = value; } } public string Phone { get; set; } public bool Processed { get; set; } public DateTime CreatedDate { get; set; } // IEntity Implementation public string GetId() { return Email; }
ORM Entity Frameworkãã¡ã€ã³ãšããŠäœ¿çšããããšã¯æ¢ã«è¿°ã¹ãŸããããããã ãã§ã¯ãããŸããã äž»ãªçç±ïŒ
- 移è¡ã®èªåçæïŒå€ãã®æéãç¯çŽããã«ãŒãã³ã³ãŒããèšè¿°ããå¿ èŠããããŸããïŒ
- .NETã§ã®æé«ã®linqãµããŒã
- NHibernateããéãéçº
- ããŒã¿ã®ãããã³ã°ãšç§»è¡ã®äœæã®ããã®DataAnnotationå±æ§ããµããŒã
æµentãªãããã³ã°VS Atributeãããã³ã°
ãã¡ããããã¹ãŠã®ããŒã«ãŒã®å³ãšè²ã¯ç°ãªããŸãã æµmappingãªãããã³ã°ã¯ããã¯ãªãŒã³ã§ããããã¡ã€ã³ã¢ã»ã³ããªã«å¿ããŠEFããã©ãã°ããããšã¯ã§ããŸãããããã®åé·æ§ãš2ã€ã®ã¯ã©ã¹ããµããŒãããå¿ èŠæ§ã奜ãã§ã¯ãããŸããïŒãšã³ãã£ãã£ãšãããã³ã°ã ããã¯SRPéåã§ãããšèª°ããèšããããããŸããã ç§ã®æèŠã§ã¯ãå±æ§ã¯å¿ é ã®ã³ãŒãã§ã¯ãªãããã®ãããªæ¯èŒã¯æ£ãããããŸããã èšé²ã®åœ¢åŒãšEFãžã®äœåãªäŸåã ãã«éããèŠãããŸãããå¿ èŠã«å¿ããŠç°¡åã«åãåãããšãã§ããŸããæ°žç¶æ§ã®ç¡ç¥
ãã®ããããã¡ã€ã³ãšã³ãã£ãã£ããããããŒã¿ãœãŒã¹ããããŒã¿ãäœæãåŠçãä¿åããã£ã«ã¿ãªã³ã°ãååŸãåé€ããå¿ èŠããããŸãã äžè¬ã®äººã ã§ã¯ãããã¯CRUDæäœãšåŒã°ããŸãã ãªããžã§ã¯ãã®äžå€åŒã«éåããªããæ£ãããã³ã³ã¹ãã©ã¯ã¿ã䜿çšããå¿ èŠãããããšãå¿ããã«ãnewæŒç®åã䜿çšããŠãšã³ãã£ãã£ãäœæã§ããŸãã ORMãµããŒãã®ããã«ã®ã¿ããã©ã«ãã³ã³ã¹ãã©ã¯ã¿ã宣èšãã[Obsolete]å±æ§ã䜿çšããŠæ±ããæããèªåèªèº«ãä¿è·ããŸããããªããžã§ã¯ããä¿åããŠããŒã¿ãœãŒã¹ããååŸããã«ã¯ã©ãããã°ããã§ããïŒ ææ°ã®ãã¬ãŒã ã¯ãŒã¯ã§ã¯ãã¢ã¯ãã£ãã¬ã³ãŒãïŒARïŒãšäœæ¥åäœïŒUoWïŒã®2ã€ã®ã¢ãããŒãã䜿çšãããŸãã ç§ã¯Active Recordã®åŒ·æµã§ãã 解éãããPLã§ã¯ARãå©ç¹ãäžããå¯èœæ§ããããŸãããã³ã³ãã€ã«ãããPLã§ã¯ããã§ã¯ãããŸããã ARã¯æãRPãæ¹æ³ã§SRPã«éåããSaveã¡ãœããããã¹ãŠã®ãšã³ãã£ãã£ã«è¿œå ããŸãã ãšã³ãã£ãã£ã®ã¿ã¹ã¯ã¯ãããŒã¿ããŒã¹ã«èªèº«ãä¿åããã®ã§ã¯ãªããããžãã¹ããžãã¯ãå®è£ ããããŒã¿ãã«ãã»ã«åããããšã§ãã ãããã£ãŠãç§ã®éžæã¯ãããã§ãã
public interface IUnitOfWork: IDisposable { void Commit(); void Save<TEntity>(TEntity entity) where TEntity : class, IEntity; void Delete<TEntity>(TEntity entity) where TEntity : class, IEntity; }
EFã®å ŽåãUoWå®è£ ã¯ã¢ããªã±ãŒã·ã§ã³ã®DataContextã«ãªããŸãã ãã ããDataContextèªäœã¯ãã¡ã€ã³ã¢ã»ã³ããªã«åºå·ããŸããã ãŸãããªãããã§EFã«äŸåããå¿ èŠãããã®ã§ããïŒ æ¬¡ã«ãå€ãã®å ŽåãéçºããŒã ãåé¢ããããã«å¢çã³ã³ããã¹ããå®è£ ããå¿ èŠããããŸãããããŒã¿åç·ã®åæ解é€ã®ãªãã·ã§ã³ãé€å€ããã«ã¯ãåãDataContextå ã«ç§»è¡ãæ®ãæ¹ãè¯ãã§ãã
ä¿åãç·šéãåé€ã®æ¹æ³ã¯æ確ã§ãã ããŒã¿ãååŸããæ©èœã¯æ®ããŸãã åŸæ¥ããã®æ©èœã¯ãªããžããªã䜿çšããŠå®è£ ãããŠããŸããã ãããŠäŒçµ±çã«ãäžåšçšã«ãå®è£ ãããŸããã åé¡ã«ã€ããŠã¯ãã åé¡ã®ãããªããžããªãã³ãã¬ãŒã ãã®èšäºã§è©³ãã説æããŠããŸã ã
èŠããã«ãæåã«ãããè¡ããŸãïŒ
public interface IRepository<T> { T GetById(int id); IEnumerable<T> GetAll(); bool Add(T entity); bool Remove(T entity); }
çµæã¯æ¬¡ã®ãšããã§ãã
class AccountRepository : IRepository<Account> { public Account GetByName(string name); public Account GetByEmail(string email); public Account GetByAge(int age); public Account GetByNameAndEmail(string name, string email); public Account GetByNameOrEmail(string name, string email); // ... public Account GetByAreYouFuckingKiddingMe(SomeCriteria c); }
ãã®ãããªç¶æ³ãçµäºããŸãïŒä»¥äžã«èª¬æããçç±ã«ãããæ¡åŒµã¡ãœããã䜿çšãããªãã·ã§ã³ã¯èæ ®ããŸããïŒã
public interface IRepository<T> { T GetById(int id); // IQueryable<T> Query(); bool Add(T entity); bool Remove(T entity); }
ãã ãã次ã®ããã«äžæããŸãã
// - repo.Query().Where(a => a.IsDeleted = false); // , repo.Query().Where(a => a.IsDeleted = false && a.Balance > 0); // runtime error repo.Query().Where(a => a.CreationDate < getCurrentDate());
æåŸã®äŸã§ã¯ãæåã®2ã€ã®linqã¯ãšãªã¯ãã¢ã¯ãã£ãã¢ã«ãŠã³ãããžãã¹ã«ãŒã«ã®å€æŽã瀺ããŠããŸãã æåã¯ãåé€ãããŠããªããã®ãã¢ã¯ãã£ãã§ãããšèŠãªããããã©ã³ã¹ã¯ãŒããã倧ãããªããã°ãªããªãããšããèŠä»¶ãè¿œå ãããŸããã linqã¯ãšãªã¯éåžžã«ç°¡åã«èšè¿°ã§ãããããã³ãŒãããŒã¹ã®æ°åç®æã«ã³ããŒãããŸãã ã»ãšãã©ç¢ºå®ã«ã©ããã§ãããå€æŽããŸãããã©ããã§ãããå¿ããŸãã
3çªç®ã®äŸã¯æ£åžžã«ã³ã³ãã€ã«ãããŸãããORMã¯getCurrentDateé¢æ°ãSQLã«å€æããæ¹æ³ãç解ããŠããªããããå®è¡æã«ã¯ã©ãã·ã¥ããŸãã æéããªããªããã¿ã¹ã¯ãåŸèŒ©ã«å±ããå Žåã圌ã¯ããã«æ¬¡ã®ãããªãã¡ã€ã«ã§ã³ãŒãããä»äžãããŸãã
repo.Query().ToEnumerable().Where(a => a.CreationDate < getCurrentDate());
ãŸãã300äžã®ã¢ã«ãŠã³ãã¯ãã¹ãŠRAMã«æ ŒçŽãããŸãã
IQueryableãåºåããããšã«ã¯ãŸã æé»çãªåé¡ããããŸãã
- IQueryableããªãŒã¯ããŠããã æããã«LSPã«éåããŠããŸãã ãã£ãŒãããåŒãããã€ãžã§ã¹ããããIQueryableå®è£ ã¯ãã¡ã¢ãªå ã®ã¿ã§ãã ãã ããã¡ã¢ãªå ã«ã¯linq2objectããããããIQueryableã¯ç¡æå³ã«ãªããŸãã Whereãªã¯ãšã¹ãã¯ãã³ãŒãã®æœåšçãªé害ãã€ã³ãã§ãã
- ãã¹ãŠã®ããŒã¿ãœãŒã¹ãlinqããµããŒãããŠããããã§ã¯ãããŸããã ããæç¹ã§ããã«ããã¹ãæ€çŽ¢ãå¿ èŠã«ãªããããã䜿çšããŠSphinxãŸãã¯Elasticãå¿ èŠã«ãªããŸãã ãlinq-providerãæžããŸãããããšããææ¡ãçµå¶é£ããã®å¿çãèŠã€ããããšãçããŸãïŒãããŠãã¡ãªã¿ã«æ£ããïŒã åé¡ã¯ãã«ããã¹ãã«éå®ããããããŒã¿ã¯ãããã¯ãŒã¯ãçµç±ããŠãã£ã¹ã¯ã«ä¿åãããã¯ã©ãŠããã¡ã€ã«ã·ã¹ãã ã«ä¿åãããŸãã
- ããŒã¿ããŒã¹ãããŒã¿ãœãŒã¹ãšããŠæ©èœããå Žåã§ããããã©ãŒãã³ã¹ã®ç®çã§ãããŒã¿ã®äžéšãéæ£èŠåããã圢åŒã§ããããNOSQLãœãªã¥ãŒã·ã§ã³ã«è»¢éãããå¯èœæ§ããããŸãã ã¯ãšãªãæã§æžããŠããã¹ãŠãæ倧éã«èª¿æŽããå¿ èŠãããå¯èœæ§ããããŸãã ãããã³ã°ãªããžã§ã¯ã
æåã®åé¡ã¯ååãšããŠè§£æ±ºãããŸããã ããã¯ãlinqã®èšèšã«ããèšèšãããŠããŸãã æå¥ãèšãã®ã¯çœªã§ããlinqã¯ãšãŠã䟿å©ã§ãã é ç®2ããã³3ã¯ãå®éã«ã¯IQueryableããã¹ãŠã®å Žé¢ã§æœè±¡åãšããŠé©åã§ã¯ãªãããšã瀺åããŠããŸãããªããªããå®éã®äžçã§ã¯ããã¹ãŠã®.NETéçºè ãããŒãããã¯ã§åŒããªãŒã解æããŠãä»»æã®ããŒã¿ãœãŒã¹ã«ã
ã¿ããªããã§ã«ç§ãã¡ã®ããã«æ¥ãŠãããŠããããã§ã
ä»æ§å¥åãã£ã«ã¿ãŒ
public interface ISpecification<in T> where T:IEntity { bool IsSatisfiedBy(T o); } public interface IRepository<T> { T GetById(int id); // IEnumerable<T> GetBySpecification(ISpecification<T> spec); bool Add(T entity); bool Remove(T entity); }
ä»æ§ã¯ããžãã¹ãã£ã«ã¿ãªã³ã°ã«ãŒã«ã§ãã ãªããžã§ã¯ããæ¡ä»¶ãæºãããŠãããã©ããã瀺ãã¡ãœããã¯1ã€ã ãã§ãã çŸåšã®åœ¢åŒã§ã¯ãä»æ§ã¯ã³ãŒãã®éè€ã®åé¡ã解決ããŸããLinqããªããåãã£ã«ã¿ãªã³ã°ã«ãŒã«ã«å¯ŸããŠç¬èªã®ä»æ§ã¯ã©ã¹ãèšè¿°ããå¿ èŠããããŸãã
ãããããã¿ãŸããããªããããå¿ èŠãªã®ã§ããïŒ IsSatisfiedByãSQLã«å€æããããšã¯ã§ããŸãããã€ãŸããããŒã¿ããŒã¹ãããã¹ãŠã®ã¬ã³ãŒããå床ååŸãããããã§ãã£ã«ã¿ãªã³ã°ããå¿ èŠããããŸãã ããã§ããããã¿ããšã«ä»æ§ãäœæããå¿ èŠããããŸããããã¯ãïŒç¹å®ã®æ¹æ³ã§ããŒã¿ããã£ã«ã¿ãªã³ã°ããå¿ èŠãããã€ã³ã¿ãŒãã§ãŒã¹ã®ä»£ããã«ïŒäžåºŠã ã䜿çšãããå€ãã®ã¯ã©ã¹ãäœæããããšãæå³ããŸãã
å®éãå šäœã®è°è«ãé²è¡äžã§ããã ãä»æ§ãã®ãã¿ãŒã³ã¯linqã®åºçŸã«ããæ代é ãã«ãªã£ããšåœŒãã¯èšããŸã ã
建ç¯å®å®é£è¡å£«ãæåã«æäŸããããšã¯æ¬¡ã®ãšããã§ãã
public interface IExpressionSpecification<T> : ISpecification<T> where T:class,IEntity { Expression<Func<T, bool>> Expression { get; } } public interface IRepository<T> { T GetById(int id); // IEnumerable<T> GetBySpecification(IExpressionSpecification<T> spec); bool Add(T entity); bool Remove(T entity); }
åãåµãä»æ§ã®åœ¢ã§è¿œå ã®äžå¿ èŠãªã¬ã€ã€ãŒãæã€ãããã¡ã€ã«ãã¥ãŒã衚瀺ããããã«ãã¹ãŒããŒãã¯ãŒãæã€å¿ èŠã¯ãããŸããã ããã«ãã³ãŒãå ã®linqã¯ãšãªã®éè€ã®åé¡ã¯ã次ã®ããã«ãšã¬ã¬ã³ãã«è§£æ±ºã§ããŸãã
public class Account : IEntity { [BusinessRule] public static Expression<Func<Lead, bool>> ActiveRule = x => x.IsDeleted && x.Ballance > 0; }
æåŸã«
- ãªããžããªã¯ããã¹ãŠã®ããŒã¿ãœãŒã¹ã®åºæ¬çãªæœè±¡åãšããŠå¹æçã«äœ¿çšããããšã¯ã§ããŸãã
- linqã¯éåžžã«äŸ¿å©ã§ãããçµæžçãªçç±ãããã©ãŒãã³ã¹ã®å¶éã®ããã«ã©ãã«ãé©ããŠããŸãã
CQ [R] S-ã³ãã³ããã¯ãšãª[責任]åé¢
ãŸãã¯ããã·ã¢èªã§ã®èªã¿åããšæžã蟌ã¿ã®åé¢ã ååã¯ãããŒããããã·ã¹ãã ã§æ倧ã®ã¢ããªã±ãŒã·ã§ã³ãèŠã€ããŸããã å€å žçãªäŸã¯ããœãŒã·ã£ã«ãããã¯ãŒã¯äžã®ãã£ãŒãã§ãããã¹ãŠã®å人ã®ããŒãã«ã®å±±ããããŒã¿ãååŸããå¿ èŠãããã誰ããããªãã®åçãã©ã®ããã«æ°ã«å ¥ã£ãŠåæçš¿ããããèæ ®ããããšãå¿ããªãã§ãã ããã åŸæ¥ã®å®è£ ã¯ãã®ã¿ã¹ã¯ã«ã¯é©ããŠããŸãã-çµåãšèªã¿åã/æžã蟌ã¿ããã¯ãå€ãããŸããäžè¬çãªè§£æ±ºçã¯ãèªã¿åããšæžã蟌ã¿ãåé¢ããŠããããã³ã°ãåé¿ããããšã§ãã ããããã€ãŒãŒã·ã§ã³æŠç¥ã¯ç°ãªãå ŽåããããŸãããäž»ãªãã€ã³ãã¯æ¬¡ã®ãšããã§ãã
- çµåãåãé€ãããã©ããããŒã¿ãèªã¿åããŸã
- èªã¿åã/æžã蟌ã¿ããã¯ãåé¿ãã
- ãããã¯ã°ã©ãŠã³ãã§ãããŒã¿ãåæããå€æŽãèç©ãã
ãããã£ãŠãã¯ã©ã·ãã¯ãªããžããªã¯ãã³ãã³ããšã¯ãšãªã®2ã€ã®ã€ã³ã¿ãŒãã§ã€ã¹ã«åãããŠããŸãã
ã³ãã³ãã¯è¿œå ãå€æŽãããã³åé€ãå®è£ ããã¯ãšãªã¯ããŒã¿ã®èªã¿åããå®è£ ããŸãã
public interface IQuery<TEntity, in TSpecification> where TEntity : class, IEntity where TSpecification : ISpecification<TEntity> { IQuery<TEntity, TSpecification> Where([NotNull] TSpecification specification); IQuery<TEntity, TSpecification> OrderBy<TProperty>( [NotNull] Expression<Func<TEntity, TProperty>> expression, SortOrder sortOrder = SortOrder.Asc); IQuery<TEntity, TSpecification> Include<TProperty>([NotNull] Expression<Func<TEntity, TProperty>> expression); [NotNull] TEntity Single(); [CanBeNull] TEntity FirstOrDefault(); [NotNull] IEnumerable<TEntity> All(); [NotNull] IPagedEnumerable<TEntity> Paged(int pageNumber, int take); long Count(); } public interface ICommand { void Execute(); } public interface ICommand<in T> { void Execute(T context); } public interface IPagedEnumerable<out T> : IEnumerable<T> { long TotalCount { get; } } public class CreateEntityCommand<T> : UnitOfWorkScopeCommand<T> where T: class, IEntity { public override void Execute(T context) { UnitOfWorkScope.GetFromScope().Save(context); UnitOfWorkScope.GetFromScope().Commit(); } public CreateEntityCommand([NotNull] IScope<IUnitOfWork> unitOfWorkScope) : base(unitOfWorkScope) { } } public class DeleteEntityCommand<T> : UnitOfWorkScopeCommand<T> where T: class, IEntity { public DeleteEntityCommand([NotNull] IScope<IUnitOfWork> unitOfWorkScope) : base(unitOfWorkScope) { } public override void Execute(T context) { UnitOfWorkScope.GetFromScope().Delete(context); UnitOfWorkScope.GetFromScope().Commit(); } }
ã¯ãšãªã®äž»ãªåœ¹å²ã¯ãä»æ§ïŒãã¡ã€ã³ãã£ã«ã¿ã«ãŒã«ïŒãããŒã¿ãœãŒã¹ïŒã€ã³ãã©ã¹ãã©ã¯ãã£ïŒã®ã¯ãšãªã«å€æããããšã§ãã ã¯ãšãªã¯ããŒã¿ãœãŒã¹ããã®æœè±¡åãæäŸããŸã-ããŒã¿ã®ååŸå ã¯é¢ä¿ãªããä»æ§ã¯linq +ã®äžçš®ã§ãã linqããµããŒãããããŒã¿ãœãŒã¹ã®å ŽåãExpressionSpecificationã䜿çšã§ããŸãã linqã®äœ¿çšãå°é£ãªå ŽåïŒElastic Searchã®å Žåã®ããã«ãããã€ããŒãååšããªãå Žåãªã©ïŒãåŒãã¹ããŒããŠä»æ§ã䜿çšããŸãã
public interface IExpressionSpecification<T> : ISpecification<T> where T:class,IEntity { Expression<Func<T, bool>> Expression { get; } } public static IQuery<TEntity, IExpressionSpecification<TEntity>> Where<TEntity>( this IQuery<TEntity, IExpressionSpecification<TEntity>> query, Expression<Func<TEntity, bool>> expression) where TEntity : class, IEntity { return query.Where(new ExpressionSpecification<TEntity>(expression)); }
ä»æ§ã®ã€ã³ã¹ã¿ã³ã¹ã䜿çšããŠãRAMå ã®ããŒã¿ããã£ã«ã¿ãŒåŠçããä»æ§ãã¯ãšãªã«å€æããŠãããŒã¿ãœãŒã¹ãžã®ã¯ãšãªãã¯ãšãªã«äŸåãããããšãã§ããŸãã
ICommandFactoryãIQueryFactory
å€æ°ã®å°ããªã³ãã³ãããã³ã¯ãšãªãªããžã§ã¯ãã®äœæã¯éå±ãªäœæ¥ã«ãªãå¯èœæ§ããããŸããæ £äŸã«åŸã£ãŠIOCã³ã³ããã«ç»é²ããã®ã¯è«ççã§ãã ã³ã³ããããã¹ãŠã®ã¢ã»ã³ããªã«ãã©ãã°ãããServiceLocatorãäœæããªãããã«ããã®è²¬ä»»ããã¡ã¯ããªã«å²ãåœãŠãŸãã public interface ICommandFactory { TCommand GetCommand<TEntity, TCommand>() where TCommand : ICommand<TEntity>; T GetCommand<T>() where T : ICommand; CreateEntityCommand<T> GetCreateCommand<T>() where T : class, IEntity; DeleteEntityCommand<T> GetDeleteCommand<T>() where T : class, IEntity; } public interface IQueryFactory { IQuery<TEntity, IExpressionSpecification<TEntity>> GetQuery<TEntity>() where TEntity : class, IEntity; IQuery<TEntity, TSpecification> GetQuery<TEntity, TSpecification>() where TEntity : class, IEntity where TSpecification : ISpecification<TEntity>; TQuery GetQuery<TEntity, TSpecification, TQuery>() where TEntity : class, IEntity where TSpecification: ISpecification<TEntity> where TQuery : IQuery<TEntity, TSpecification>; }
次ã«ãã¯ãšãªã®æäœã¯æ¬¡ã®ããã«ãªããŸã
_queryFactory.GetQuery<Product>() .Where(Product.ActiveRule) // , Account. ExpressionSpecification .OrderBy(x => x.Id) .Paged(0, 10) // 10 // ElasticSearch, : _queryFactory.GetQuery<Product, FullTextSpecification>() .Where(new FullTextSpecification(«»)) .All() // EF Dapper _queryFactory.GetQuery<Product, DictionarySpecification, DapperQuery>() .Where(new DictionarySpecification (someDirctionary)) .All()
ãã¹ãŠã®å Žåã§ãåãã³ãŒãã䜿çšãã_queryFactory.GetQuery <ProductãDictionarySpecificationãDapperQuery>ïŒïŒæ§é ã¯ããããæé©åã§ããããšãæ瀺çã«ç€ºããŠããŸãããã®è¡ã¯ãé²åã®ãªãã¡ã¯ã¿ãªã³ã°äžã«ã®ã¿ã³ãŒãã«è¡šç€ºãããŸãããããã¯ãæåã¯éçºé床ã®ããã«ORMã§èšè¿°ããããã§ããããŒã å ã«åŒããªãŒã«ç²ŸéããŠãã人ãããå Žåããã¹ãŠã®èŠæ±ãåŸã ã«linqã«ç¿»èš³ã§ããŸãïŒå®éã®ç掻ã§ã¯ãçµæžçãªçç±ããããã¯ã»ãšãã©äžå¯èœã§ãïŒã
_queryFactory.GetQuery <ProductãFullTextSpecification>ïŒïŒã®å Žåãããã«ããã¹ãä»æ§ããæå®ããŸããããã¡ã€ã³ã³ãŒãã¯è¿ãããã€ã³ã¹ã¿ã³ã¹ïŒElasticSearchQueryïŒã«ã€ããŠäœãç¥ããŸããã圌ã«ãšã£ãŠãããã¯åãªãå šææ€çŽ¢ãã£ã«ã¿ãªã³ã°ã«ãŒã«ã§ãã
è«äºïŒhabrahabr.ru/post/125720
å°ãæ§æç³
äŸã«æ»ããŸãã public class Account : IEntity { [BusinessRule] public static Expression<Func<Lead, bool>> ActiveRule = x => x.IsDeleted && x.Ballance > 0; bool IsActive() { // ??? } }
ãã¢ã¯ãã£ãã¢ã«ãŠã³ããããžãã¹ã«ãŒã«ã¯è«ççãªå Žæã«é 眮ãããåå©çšãããŸãããããžã§ã¯ãå šäœã«æ£åšããã©ã ããæããå¿ èŠã¯ãããŸããã
ãã®èŠä»¶ã¯ãExpression <Func <Leadãbool >>ã®åœ¢åŒã§å¿ èŠã«ãªãå ŽåããããŸã-ããŒã¿ãœãŒã¹ãžã®ã¯ãšãªãžã®å€æã®ããã«å¿ èŠãªå ŽåããããŸãããã¹ãŠã®äººã®ããã«ä»æ§ã¯ã©ã¹ãäœæããããšã¯ãè¯ãã¢ã€ãã¢ãšã¯æããŸããã次ã®å®è£ ããã€äœ¿çšã§ããŸããïŒ
public static class Extensions { private static readonly ConcurrentDictionary<Expression, object> _cachedFunctions = new ConcurrentDictionary<Expression, object>(); public static Func<TEntity, bool> AsFunc<TEntity>(this object entity, Expression<Func<TEntity, bool>> expr) where TEntity: class, IEntity { //@see http://sergeyteplyakov.blogspot.ru/2015/06/lazy-trick-with-concurrentdictionary.html return (Func<TEntity, bool>)_cache.GetOrAdd(expr, id => new Lazy<object>( () => _cache.GetOrAdd(id, expr.Compile()))); } public static bool Is<TEntity>(this TEntity entity, Expression<Func<TEntity, bool>> expr) where TEntity: class, IEntity { return AsFunc(entity, expr).Invoke(entity); } public static IQuery<TEntity, IExpressionSpecification<TEntity>> Where<TEntity>( this IQuery<TEntity, IExpressionSpecification<TEntity>> query, Expression<Func<TEntity, bool>> expression) where TEntity : class, IEntity { return query .Where(new ExpressionSpecification<TEntity>(expression)); } } public class ExpressionSpecification<T> : IExpressionSpecification<T> where T:class,IEntity { public Expression<Func<T, bool>> Expression { get; private set; } private Func<T, bool> _func; private Func<T, bool> Func { get { return this.AsFunc(Expression); } } public ExpressionSpecification([NotNull] Expression<Func<T, bool>> expression) { if (expression == null) throw new ArgumentNullException("expression"); Expression = expression; } public bool IsSatisfiedBy(T o) { return Func(o); } } public class Account : IEntity { [BusinessRule] public static Expression<Func<Lead, bool>> ActiveRule = x => x.IsDeleted && x.Ballance > 0; bool IsActive() { this.Is(ActiveRule); } }
ãµãŒãã¹ããããŒãžã£ãŒããã«ããŒã¯ã©ãã«ããŸããïŒ
ã³ãŒããé©åã«ç·šæãããŠããã°ããã¡ã€ã³ã«helper'ovã¯ãããŸããããã¬ãŒã³ããŒã·ã§ã³å±€ã«äœããããã®ãââããããŸããã ManagerãšServiceã¯åããã®ãªã®ã§ãManagerãšããååããŸã£ãã䜿çšããªãæ¹ãè¯ãã§ãããããµãŒãã¹ã¯çŽç²ã«æè¡çãªçšèªã§ãã Serviceãæ¥å°ŸèŸãšããŠã®ã¿äœ¿çšãããããŸã£ãã䜿çšããŸããïŒIOCã®åæã«ããç»é²ããããã«åå空éã®ã¿ãæ®ããŸãïŒãå®éã®ããžãã¹ã«ã¯ããµãŒãã¹ãã¯ãªããããã£ãã·ã¥ãã¹ã¯ããããã¹ãã£ã³ã°ãããã¯ã©ãŒã¿ããªã©ããããŸãããã®ãããã¢ããªã±ãŒã·ã§ã³ãã¡ã€ã³ã«åŸã£ãŠããžãã¹ããžãã¯ãšååã¯ã©ã¹ãã°ã«ãŒãåããå¿ èŠãªå Žåã«ã®ã¿äœæããããšããå§ãããŸãã CRUDæäœã«ãµãŒãã¹ã¯å¿ èŠãããŸããã UoW + Command + Query + Specification + Validatorã®ãã³ãã«ã¯ãäŒèšã·ã¹ãã ã®ããŒãºã®90ïŒ ãã«ããŒããã®ã«ååã§ããã¡ãªã¿ã«ãããã«ã¯1ã€ã®ã³ã³ãããŒã©ãŒã¯ã©ã¹ã®ã¿ãå¿ èŠã§ãã
ãããã«
ãã®ãããªã¢ãŒããã¯ãã£ã¯éè² è·ã«èŠãããããããŸãããå®éããã®ãããªã¢ãããŒãã«ã¯ç¹å®ã®å¶éããããŸãã- éçºè ã®è³æ ŒïŒããã°ã©ãã³ã°ãã¿ãŒã³ã®ç解ãšãã©ãããã©ãŒã ã®ååãªç¥èãå¿ èŠã§ãã
- ã€ã³ãã©ã¹ãã©ã¯ãã£ã³ãŒããžã®åææè³ïŒãããžã§ã¯ãããã€ã³ã¿ãŒãã§ã€ã¹ãååŸããäžèŠãªäŸåé¢ä¿ã解ããã€ã³ãã©ã¹ãã©ã¯ãã£ãã§ããã ãæœè±¡çã§è»œéã«ããããã«ãã«ã¿ã€ã ã§ã»ãŒ4æ¥ããããŸããã
- å®éã®ãããžã§ã¯ãã§ãã¹ãã«åæ ŒããŠããã®ã¯ãã®ã¢ã»ã³ããªã§ãããã¡ããªãã¯ã¯ãªãããã®ã¢ãããŒããæšæºåã«ããããã©ãŒãã³ã¹ã®åäžãä¿èšŒããããšãä¿èšŒããŸãïŒäž»èŠ³çã«ã¯ãããã¯100ïŒ ç¢ºä¿¡ããŠããŸãïŒ
ã¡ãªãã
- ã€ã³ãã©ã¹ãã©ã¯ãã£ããã®ãã¡ã€ã³ã®æ確ãªåé¢
- , , , , ,
- -
- repair-kit
- ,
ç¶ç¶ããã«ã¯...