zoukankan      html  css  js  c++  java
  • 代码分析

    NerdDinner分析

    NerdDinner的一个优点就是接口设计非常恰当,我觉得编程最有搞头的可能就是接口设计,很多“问题代码”都是接口设计不当造成的。

    创建与编辑的方法接口对比:

    创建:public ActionResult Create(Dinner dinner)

    编辑:public ActionResult Edit(int id, FormCollection collection)

    为什么Edit不用Edit (Dinner dinner)这种看起来更简洁的写法呢?首先,Edit页最后是要保存数据的,但这些数据往往不是在页面上完全包含,比如创建日期一般就不会放在编辑页面上。所以Edit方法不能用类似Create的那种接口,而是先根据id来从数据源取出Dinner对象,然后用UpdateModel(dinner);方法更新那些在编辑页面上有的字段,然后再保存到数据源。

    接口举例

    比如public ActionResult ViewErrorLog(ViewErrorSearchOption searchOption)就是很好的接口设计,因为一进入这个方法就能直接用参数了,public ActionResult CalendarAdmin(FormCollection formCollection)可能是不太好的,是可以进一步改进的接口,因为首先,这个方法的功能不单一,是一碗意大利面(意大利面主要原因并不是某种编程语言(比如Basic)造成的,而是编程者的编程思想,高手即使用汇编也能写出比较容易读懂的代码),里面用了大量的formCollection["XXX"]形式的代码来一个一个获取参数,缺乏对输入参数的抽象。解决方法是从2方面,一是“拆”,即页面改造,用Ajax+PartialView对功能做拆分,二是抽象,对输入和输出参数做抽象,使参数获取和使用简单化。

    当一个页面简单的时候,这个页面可能适合整体做,不需要做什么功能拆分和Ajax,比如ViewErrorLog页面。但当页面包含了搜索条件、显示搜索结果、编辑保存等众多功能时,必须拆。拆了会变成几个方块,比如BusinessBranchAdmin。不拆就会变成意大利面,比如CalendarAdmin没有拆。注意BusinessBranchAdmin代码仍然较多,主要是页面上有级联下拉框和较多的页面元素,这里面有很多都是可以进一步优化的,要解决的主要问题是功能重复的时候,代码没有设计成可重用,这其实在开发过程中是正常现象,因为不可能一下子就设计出一个最优的系统,但一直保持这样,一直不去优化,就会给进一步开发及后期维护工作带来巨大工作量和Bug,经常否定自我,优化老代码才能走的顺。

    接口代码分析

    BusinessBranchAdmin里分成3个方法:

    1. public ActionResult BusinessBranchAdmin()方法处理带有BusinessId参数的Get请求,这是一种容错的写法,当没有参数的时候,它会显示NotFound页面,现在感觉是多此一举了,用public ActionResult BusinessBranchAdmin(decimal businessId)更合适,因为这是后台代码,后台一般人不会乱弄个Url乱搞的。正常情况下return View(formModel);

    2. public ActionResult Edit(int BusinessBranchId)处理获取Get请求,它由客户端的Ajax代码showEdit方法触发,正常情况下它返回的是一个PartialViewreturn PartialView("BusinessBranchForm" , info);不过我检查代码时发现了笔误,写的是return View("BusinessBranchForm", info);不过两种写法都能正常运行,不过因为BusinessBranchForm是用户控件,所以用PartialView更合适。数据返回浏览器后由onGetDetailComplete方法处理,显示在divEdit里。

    3. public ActionResult Edit(int BusinessBranchId, FormCollection formValues)处理Post请求,由客户端postEditForm方法触发,这个方法里用到了通用提交表单的postForm方法。服务器端处理成功后会return PartialView("EditSuccess");失败会设置错误信息并return PartialView("BusinessBranchForm", info);

    整个页面的JS只有非常简短的,一目了然的,可望词生义的5个函数,共25行。

    CalendarAdmin里有很多方法,拿最重要的前2个方法为例:

    1. public ActionResult CalendarAdmin(),这个方法处理Get请求,既处理最初显示搜索条件的任务,又处理后续的根据参数查询数据的任务,以及分页逻辑等等众多功能,非常不容易看明白。有几个编码问题比较突出:一个是获取参数的GetParamters方法,里面全部是out参数,还有些方法里会改变某些参数的值,这都不是一种好的接口设计,要解决这个问题,最管用的还是“拆”字诀,然后对输入输出数据做抽象。

    2. public ActionResult CalendarAdmin(FormCollection formCollection)处理Post请求,处理首次检索任务,里面有非常多与第一个方法相同的逻辑功能代码。我发现里面有一个意大利面的铁证:Goto语句,可见逻辑之复杂。解决方法还是“拆”字诀,拆才能简单化,拆才能清晰易懂。

    Html结构分析

     

    结构良好的:

     

    CSS

       <style type="text/css">

                .outputTable

                {

                    background-color: White;

                    100%;

                }

                .outputTable tr

                {

                    height: 25px;

                }

                .outputTable th

                {

                    background-color: #C0D6F6;

                }

                .outputTable td

                {

                    background-color: #ECF3FD;

                }

            </style>

     

    Html

            <table border="0" cellpadding="3" cellspacing="2" id="divCalendarList" class="outputTable">

                <%--<caption>

                    Search Result</caption>--%>

                <thead>

                    <tr>

                        <th>dgtStartDateTime

                        </th>

                    </tr>

                </thead>

                <tbody>

                    <% foreach (SIL.RealStew.DAL.Entities.BusinessBranch c in Model.BusinessBranches)

                       { %>

                    <tr>

                        <td>

                            <a href="javascript:showEdit(<%= c.BuBrId %>)">BuBrName</a>

                        </td>

                    </tr>

                    <% } %></tbody>

            </table>

     

    结构不好的(class="bold" height="25"bgcolor="#C0D6F6"之类的完全可以写在CSS里):

     

    <table border="0" cellpadding="3" bgcolor="#ffffff" cellspacing="2" id="divCalendarList" style=" 100%">

                    <tr class="bold">

                        <td height="25" bgcolor="#C0D6F6">

                            <%= Html.Resource("dgtStartDateTime")%>

                        </td>

                    </tr>

                    <% foreach (SIL.RealStew.BLL.Home.Model.CalendarViewEntry c in Model.CalendarList)

                       { %>

                    <tr bgcolor="#ECF3FD" >

                        <td height="25">

                            <%= c.CaEnStartDate == null ? "" : ConvertDateTime.ConvertToCurrentDatetimeFormat(c.CaEnStartDate.Value.Date.ToString()) + (c.CaEnStartTime == "00:00" ? "" : "<br>" + c.CaEnStartTime)%>

                        </td>

                    </tr>

                    <% } %>

                </table>

     

    多语言代码分析

    1. Global.asax里的protected void Application_BeginRequest(object sender, EventArgs e)方法

    2. LanguageEnvironmentLanguage属性

    3. EnquiryLoadManager类的GetTradeDetail方法的language参数可以省去,方法里用语言的时候用Language.EnvironmentLanguage就行了,不需要从外面传进来。需要用Culture的地方,比如格式化日期、货币的地方,用CultureInfo.CurrentCulture就行了。

    编程风格分析

    1. 最常见的问题是超长的行,比如memberCallCentreModel.CountryList = new SelectList(countryEntityList as IEnumerable, "CountryID", "CountryName", memberCallCentreModel.SearchCountryID);

    如果写成以下风格会更有可读性:

                memberCallCentreModel.CountryList =

                    new SelectList(countryEntityList as IEnumerable

                        , "CountryID"

                        , "CountryName"

                        , memberCallCentreModel.SearchCountryID);

    2. 代码(特别是Html)的缩进和空行特别乱,就不举例了

    3. JS的存放,我并不认为所有的JS都应该放到单独的JS文件,首先有很多JS代码都会用到服务器端变量,直接在页面里写会更方便,假如代码太多,放在页面上就会影响视线了,不容易弄清楚页面结构,适合放在单独的JS文件里。少量代码且用到服务器端变量的适合直接放在页面上,如果不论什么都放到JS文件里,则会增加文件的数量,万一有什么修改的话,还需要打开2个文件对比着看,增加工作量。JS文件缓存可以节省流量,提高速度,但现在带宽都挺高的,一小段JS并不会带来性能问题,反而可以减少请求数,至少能在首次载入时增加速度。

    4. int pageSize = int.Parse(ConfigurationManager.AppSettings["PageSize"]);这是典型的HardCoding形式,不利于维护,用我写的SolutionConfig.PageSize可以避免之。

    5. 无效代码:即被注释掉的代码,是很影响视线的。我的习惯是在重构时将过时的代码注释掉,当重构完成时,删掉其中的大部分,只留极少数有参考价值的代码。然后每次看到漏删的完全没用的无效代码时,彻底删除之。

    通用级连下拉框代码的分析

    1. 本示例代码的数据源是Xml文件,集成到数据库里需要做适当改动

    2. Web.config里配置级联下拉框的KeyKey的层次结构以及Key与数据提供类的映射。

    3. 顶级下拉框基础数据提供类需要继承SelectListProviderBase

    比如public class Countries : SelectListProviderBase

    4. 有父亲的数据提供类要继承HasParentBase

    比如CitiesSuburbsStreets

    5. 取下拉框数据用DdlFormModel.CreateInstance方法,这个方法有3个重载,一个用于顶级下拉框,一个用于中间级下拉框,一个用于末级下拉框

    6. 页面上引入commonddl.js

    7. 页面上引用通用级联下拉框用户控件,例如:

    <% Html.RenderPartial("GetDdl", Model.Countries); %>

    8. 下拉框外层元素的Id命名约定:为内层下拉框Id后加Wrapper

    通用分页存储过程分析

    SP名称:Utility_GetOnePage

    核心代码:ROW_NUMBER() OVER (order by '+@OrderBy+') as Pos

    其它:都是一些拼SQL的语句

    注意事项:调用这个存储过程的存储过程必须在最后有Select语句,正常有的没有问题,如果没有,需要加上(一般写成Select 1),因为要兼容Netail工具让其生成返回IDataReader的方法,否则会生成返回void的方法。

    调用方法:参考SILCustom_Business_Search存储过程

     

  • 相关阅读:
    Java(15) _Runtime类 内存方法
    Mysql(1)_ 基本sql语句
    Java(13)_ 用IO流复制文件
    Java(12)_switch语句
    Java(10) _无参构造方法调用问题
    Java(9) _强制类型转换
    Java(8)_符串常量赋值
    Java(7)_file类的常用方法
    Java(6)_ Runtime类调用exe程序
    Java(5) _类的定义
  • 原文地址:https://www.cnblogs.com/bighuiwolf/p/1771377.html
Copyright © 2011-2022 走看看