作者发现,本文被多个博客和网站转发。赠人玫瑰,手有余香!
本文版权归作者和博客园共有,欢迎转载,转载请注明出处: https://www.cnblogs.com/buguge

我们的项目程序里,由于赶项目进度,同时,大家缺乏相应的沟通,在服务层提供的接口里,涉及到分页查询的,有如下三种情形:

l  List<OrderInfo> GetOrderList(OrderQueryModel condition, int pageIndex, int pageSize);

l  List<OrderInfo> GetOrderList(OrderQueryModel condition, int pageNo, int pageSize);

l  List<OrderInfo> GetOrderList(OrderQueryModel condition, PageMode pagedInfo);

对于以上的接口声明,同时涉及到了pageIndex和pageNo,加上缺乏必要的注释,前端开发组人员的调用方式,尤其是获取第一页数据时,就有些犯迷糊了,有的给的是0,有的给的是1。开发经理在review大家的交付成果时,显然就出现bug了。 于是,倡导统一就显得很迫切了,但是由于项目比较庞大,怕修改会带来新的麻烦。

架构师观点:从使用习惯上来看,pageIndex是从0开始的,index嘛;而pageNo表示计数,所以从1开始就比较容易理解了。

技术总监:不管是叫什么名了,就约束前端调用方从1开始传递这个参数。(技术总监的英语水平用一个名牌形容就是TCL)。

我觉得这种重构是值得尽快来做,越往后拖的话可能就越糟糕,就执意坚持。 最后,和开发经理花了2个小时,并做了一些检查,最终修复成如下方案:

分页查询使用统一模型PageModel,其中,页码属性使用PageIndex,调用方从0开始传参。即第一页的话pageIndex=0,第二页pageIndex=1,et cetera.

毕竟这是团队项目,底层框架、技术预研、服务层逻辑、前端UI,大家有不同的分工。我想,即使是完全交给某一个人来做,迟早他也会乱的。因此,尤其是team leader,应该尽早在做code review时发现这些问题,并统一开发规范。这就完了吗?没有,接下来是…………………………………..………………………………….…………………………………..………………………………….………………………………..………………………………….………………………………..………………………………….………………………………..………………………………….………………………………..………………………………….……………………………..………………………………….………………………………..…………………………………. …………………………………..………………………………….…………………………………..………………………………….………………………………..…………………………………. …………………………………..………………………………….…………………………………..…………………………………………………………………..…………………………………. …………………………………..………………………………….…………………………………..…………………………………………………………………..…………………………………. …………………………………..………………………………….…………………………………..…………………………………………………………………..…………………………………. …………………………………..………………………………….…………………………………..………………………………….…………………………………..…………………………………. …………………………………..………………………………….…………………………………..………………………………….………………………………..…………………………………. …………………………………..………………………………….…………………………………..………………………………….…………………………………..…………………………………. …………………………………..………………………………….…………………………………..………………………………….…………………………………..…………………………………. …………………………………..………………………………….…………………………………..………………………………….…………………………………..…………………………………. …………………………………..………………………………….…………………………………..………………………………….…………………………………..…………………………………. …………………………………..………………………………….…………………………………..………………………………….…………………………………..…………………………………. …………………………………..………………………………….…………………………………..………………………………….…………………………………..…………………………………. …………………………………..………………………………….…………………………………..………………………………….…………………………………..…………………………………. …………………………………..………………………………….…………………………………..………………………………….…………………………………..…………………………………. …………………………………..………………………………….…………………………………..………………………………….…………………………………..…………………………………. …………………………………..………………………………….监控大家的执行情况。

跑题了,接着聊一点规范吧。在你的开发组的项目里,

l  就商品/产品的命名上,是否同时存在product和goods甚至good? 就手机号的命名上,是否同时存在mobile和phone和telephone甚至mphone甚至tel?

l  是否存在一些全局变量(在使用时才声明变量,这是个好习惯,全局作用域极易因使用不当而带来潜在风险)

l  调用别人接口得到引用类型或集合后,是不是不判断为null(有时还需判断其Count>0)就直接使用?(不要轻信别人的代码,即使他确信不会返回null)  同样,是否也对接收到的参数做类似的判断?

l  ……

继续,我的一点实践总结:

l  对于List对象的命名。通常以-List结尾,比如productList、orderList。另一种方式,对于名词,可以以其复数形式来命名。如products、orders,而对于idList,则最好不用ids。

l  我们目前的项目是一个B2B+B2C模式的电商交易系统,订单表名自然是喜闻乐见的orders。这个表同时存放这2种模式的交易数据,对于零售来说是零售订单,对于商家交易来说是采购单。Orders表与会员(普通用户和商家)的ER见下图。对于交易涉及到的双方,orders表里有2个字段CustomerId和ShopId。随着业务逻辑梳理、服务层逻辑代码的编写、客户端调用、需求微调所致迭代等工作的不断进行,发现买家卖家登录后对这2个属性赋值查看自己订单列表时,存在诸多不便,尤其是理解层面。目前,项目在逐步将这2个属性改为BuyerId和SellerId(同样的CustomerName改为BuyerName,ShopName改为SellerName)。

l  在我们项目里,商城一些推荐栏比如推荐商品,这个功能是由运营人员通过后台来设置的,这个列表的显示需要有排序,这时在领域模型里就要有这么一个显示序号的属性,我们起初命名成了ShowOrder,后来改成了DisplayNo,为了避免让大家联想到订单。

我很赞同我们项目组架构师的一句话:“架构要考虑成本和效率”。他在面试求职者时曾提问:“如何做到你的接口不需要用户借助说明文档就能理解?” 值得我们思考。

真的是有最佳实践的,

如webservice的wsdl。

再如public void CreateCache(int cacheSize)

传入的数据是bytes, KB, MB 还是GB?

改成public void CreateCache(int cacheSize_mb)

一目了然,并且会减少调用者传入错误数据的可能。

再让我们看看微软底层对一些参数的命名:

public sealed class Thread : CriticalFinalizerObject, _Thread
{
//
// 摘要:
// 将当前线程挂起指定的时间。
//
// 参数:
// millisecondsTimeout:
// 线程被阻塞的毫秒数。指定零 (0) 以指示应挂起此线程以使其他等待线程能够执行。指定 System.Threading.Timeout.Infinite
// 以无限期阻止线程。
//
// 异常:
// System.ArgumentOutOfRangeException:
// 超时值为负且不等于 System.Threading.Timeout.Infinite。
[SecuritySafeCritical]
public static void Sleep(int millisecondsTimeout);
}

继续跑题,说下产品设计方面,在我们产品经理设计的商城页面里,其中,采购平台页面里有一个栏位叫最新上架:

在另一个一级分类频道页里,也有一个取数逻辑相同的栏位叫新品到货:

个人认为,全局角度来看的话,这2个栏位应该取相同的名字。难道同一个商城里你能有些页面称商品为商品而有些页面称商品为产品么?

BTW,老早就想写这篇博客了,总是找各种理由推脱。周二晚上下班和一同事一起乘公交回去,我告诉他我次日上班后就抽时间写一篇博客。谁知,到了周三中午我同事问我写了没有时,我却发现我由于工作忙给忘记了。——我借故忙给推脱了,直到现在,8月份的最后一个工作日。

说到忙,这段时间,精确的说,是有3个月了,是有些忙,倒是没少加班,每到周五晚又搭车80公里回家看孩子,每周一5点起大早又匆匆赶回来。为什么老回家?我家新添了两名小成员,我的双胞胎女儿,小飞飞和小扬扬,真是不知不觉,她们已经两个半月大了,这期间的每个日夜,妻子默默付出了很多。。。

当pageIndex遇上pageNo的更多相关文章

  1. MVC遇上bootstrap后的ajax表单模型验证

    MVC遇上bootstrap后的ajax表单验证 使用bootstrap后他由他自带的样式has-error,想要使用它就会比较麻烦,往常使用jqueyr.validate的话只有使用他自己的样式了, ...

  2. 敏捷遇上UML-需求分析及软件设计最佳实践(郑州站 2014-6-7)

      邀请函: 尊敬的阁下:我们将在郑州为您奉献高端知识大餐,当敏捷遇上UML,会发生怎样的化学作用呢?首席专家张老师将会为您分享需求分析及软件设计方面的最佳实践,帮助您掌握敏捷.UML及两者相结合的实 ...

  3. 敏捷遇上UML—软创基地马年大会(广州站 2014-4-19)

        我们将在广州为您奉献高端知识大餐,当敏捷遇上UML,会发生怎样的化学作用呢?首席专家张老师将会为您分享需求分析及软件设计方面的最佳实践,帮助您掌握敏捷.UML及两者相结合的实战技巧. 时间:2 ...

  4. 敏捷遇上UML——软创基地马年大会(深圳站 2014-3-15)

    邀请函: 尊敬的阁下: 我们将在深圳为您奉献高端知识大餐,当敏捷遇上UML,会发生怎样的化学作用呢?首席专家张老师将会为您分享需求分析及软件设计方面的最佳实践,帮助您掌握敏捷.UML及两者相结合的实战 ...

  5. 初识genymotion安装遇上的VirtualBox问题

    想必做过Android开发的都讨厌那慢如蜗牛的 eclipse原生Android模拟器吧! 光是启动这个模拟器都得花上两三分钟,慢慢的用起来手机来调试,但那毕竟不是长久之计,也确实不方便,后来知道了g ...

  6. SQL SERVER 2008 R2 SP1更新时,遇上共享功能更新失败解决方案

    SQL SERVER 2008 R2 SP1更新时,遇上共享功能更新失败的问题,可作如下尝试: 更新失败后,在windows的[事件查看器→应用程序]中找到来源为MsiInstaller,事件ID为1 ...

  7. 当创业遇上O2O,新一批死亡名单,看完震惊了!

    当创业遇上O2O,故事就开始了,总投入1.6亿.半年开7家便利店.会员猛增至10万……2015半年过去后,很多故事在后面变成了一场创业“事故”,是模式错误还是烧钱过度?这些项目的失败能给国内创业者带来 ...

  8. LoadRunner - 当DiscuzNT遇上了Loadrunner(下) (转发)

    当DiscuzNT遇上了Loadrunner(下) 在之前的两篇文章中,基本上介绍了如何录制脚本和生成并发用户,同时还对测试报告中的几个图表做了简单的说明.今天这篇文章做为这个系列的最后一篇,将会介绍 ...

  9. LoadRunner - 当DiscuzNT遇上了Loadrunner(中) (转发)

    当DiscuzNT遇上了Loadrunner(中) 在上文中,介绍了如果录制脚本和设置脚本执行次数.如果经过调试脚本能够正常工作的话,就可以设置并发用户数并进行压力测试了. 首先我们通过脚本编辑界面上 ...

随机推荐

  1. Windows如何修改MySQL用户root密码

    听语音 浏览:16925 | 更新:2015-06-12 14:49 | 标签:windows 1 2 3 4 5 6 分步阅读 MySQL是一个关系型数据库管理系统,在 WEB 应用方面 MySQL ...

  2. 再牛逼的梦想,也抵不住SB似的坚持

    说起梦想,哪都是好几年前的事了.自从毕业之后,梦想不知道去哪了.可能一次次的失败,找不到了梦想的方向了吧! 自从毕业去了深圳,为了能够在这个城市安稳下来,白天正常上班晚上在街上摆地摊给人下载音乐和电影 ...

  3. 使用C#代码部署SharePoint 2013开发包简单总结(一)

    这篇文章将总结下如何将自己开发的列表.Web部件.事件接收器等元素部署到SharePoint的服务器.因水平有限,我的做法未必是最佳实践,会有些错误理解和疏漏,欢迎各位高手批评指正——但一定要能给出更 ...

  4. 浅析 IDE跟编译器

    之前听别人总说你用啥IDE,直接用编译器. 总的来说IDE包含编译器,而编译器仅仅是IDE的一部分, IDE包括编辑器与编译器. IDE: 可以在IDE上面编写代码,然后编译运行,有错误还能调试.比如 ...

  5. Qt 为tableview的item添加网格线

    使用qss可以显示每个item的网格: selection-background-color: rgb(170, 170, 127); gridline-color: rgb(255, 255, 25 ...

  6. 有一种感动叫ACM(记陈立杰在成都赛区开幕式上的讲话)

    各位选手,各位教练,大家好,我是来自清华大学交叉信息学院的陈立杰,今天很荣幸站在这里代表全体参赛选手发言.对于我来说,这是我第一次正式参加ACM的比赛.不过我跟ACM之间的缘分,大概在很早的时候就已经 ...

  7. memset 究竟在做什么?

    我要 一字节一字节 地 memory set

  8. oracle中用户删除不了,ORA-01940提示 “无法删除当前已连接用户”

    Oracle删除用户的提示无法删除当前已连接用户两种解决方法如下: 1.先锁定用户.然后查询进程号,最后删除对应的进程.在删除对应的用户 SQL>alter user XXX account l ...

  9. Android AbsListView 的item动画类库 —— JazzyListView

    https://github.com/twotoasters/JazzyListView/tree/master/sample github:https://github.com/twotoaster ...

  10. JAVA设计模式--抽象工厂模式

    抽象工厂设计模式 1.系统中有多个产品族,而系统一次只可能消费其中一族产品2.同属于同一个产品族的产品以其使用.来看看抽象工厂模式的各个角色(和工厂方法的如出一辙):抽象工厂角色: 这是工厂方法模式的 ...