敏捷开发“松结对编程”系列之十七:L型代码结构(编程篇之二)(中)
续前文。
本文是“松结对编程”系列的第十七篇。(松结对编程栏目目录)
上一篇文章基本上把Controller中Action和与Action直接相关的复用讲到了,下面讲讲比较困难的部分。
几个关键问题1. 如何实现整体结构相同,而局部不同的复用比如我们的业务需求中,整体上都是一个横向的结构(请参考下图),每个单元上面都是标题,下面都是增删改查之类的按钮,唯独中间的部分不同。如果是团队,要显示成员,如果是产品,要显示最近的发布:[HttpPost, UrlLog] public ActionResult Create(int fatherID, string what, string type, FormCollection collection, string returnUrl) { ViewBag.Father = _repMFC.ReadAt<Item>(fatherID); try { Item item = ……; returnUrl = String.IsNullOrEmpty(returnUrl) ? "~/MFC/Items/Edit?id=" + item.ID + "&createNotice=off" : returnUrl.Replace("[id]", item.ID.ToString()); Notice.CreateNotice(Notice.NoticeTypes.ItemCreated, User.Identity.Name, item, new[] {Notice.RecipientTypes.DeptTeam, Notice.RecipientTypes.UserCurrentOwner}, repMFC: _repMFC); return Redirect(returnUrl); } catch (Exception e) { ModelState.ReportException(e); return View(MFCWebViewPage.ViewFailed, e); } }
注意这里附带处理了没有指定returnUrl的情况(会转向到Edit);returnUrl有很多用处,除了返回某个页面/自动导向某个页面,还可以重复指向Create以便不断创建多个。
3. 哪些Action需要写View哪些Action需要写View,然后在View里边RenderAction(比如这个Teams/Index);哪些不用写View,直接在Controller的Action里边RedirectToAction到ItemsController的操作?(这样简单,连View都不用谢,但有局限就是Url会跳转)?
前者的坏处是要额外写一个View。但好处是会保留Url,也就是看上去还在Teams/Index,但现实的内容却是Items/ItemHorizentalList的内容。这样如果要根据Url来安排主菜单或相关链接,则比较方便。
后者因为已经完全转向到别处了,正好相反。
这个事情困扰了我们一段时间,逐渐发现一个规律:如果一个页面是“长期页面”,比如Index,也就是说所有业务都围绕其开展,所有相关链接都在这个页面上,则写一个View保持不跳转;如果一个页面是“短期页面”,比如Create/Edit/Delete,也就是来看完后,几乎不会停留在这个页面上,则直接在Controller里边转向,加一个returnUrl办完事后回到长期页面就可以了。
4. 这些编码方法与松结对编程有何关系?虽然看起来也不算是很复杂的技术,但常常因为几个原因造成推广困难。这就是为什么从2000年就开始谈论“复用”“面向对象”,但到现在有几个企业或团队有自己的可复用库呢?