包头软件项目的简要总结

5月开始参与的一个内蒙古包头市某厂的软件项目已经完成有一段时间了,也有不少心得,但是一直没有找时间做系统的整理。今天先写一个简要的总结,算是个日后撰写详细材料的索引。

这里主要记录犯下的错误还有不尽人意的地方,对于执行良好的正确经验则较少分享。

  1. 需求
    1. 客户需求的模糊性只能通过多次的沟通逐步消除,尤其是和国有企业打交道的时候,不合逻辑的情况随时可能发生,软件实施人员绝对不可以简单地使用case合理性分析做出判断。
    2. 拥有庞大组织机构的客户总是会有自己的制度和规章,但是这些东西作为应付领导检查的摆设而存在的价值远远高于指导业务和生产的价值。软件开发人员即使取得了这些资料,也很难真实地还原出客户的生产管理各个环节。
    3. 在需求阶段接受访谈的工作人员常常会因为担心承担责任而将自己的部门规章或者操作规程作为资料和谈话的基本依据。除非谈话过程中让他们相信软件开发人员不可能也没必要对他们的工作现状问责,否则他们不会道出实情。
      1. 一个好的实践是设法让参与谈话的客户工作人员相信违背规程操作是因为规程设计不合理导致各部门不能协作,而开发管理软件的目的就是发现并设法解决这种不合理
    4. 客户津津乐道的业务过程和细节常常是既有方法已经能够圆满解决的部分,客户泛泛而谈的业务往往是他们尚无有效手法处理的部分,很可能也正好是客户对新软件最为期许的部分。客户往往会这么想:把我用本子和笔已经处理得很好的问题交给计算机处理完全没有必要,我希望计算机软件的引入能解决我现在处理得一团乱的问题。
    5. 客户不具备发现业务矛盾的专业素养,他们阐述的业务过程常常隐含着各种矛盾。越早发现并指出这些矛盾,软件项目实施的成本越低,完全照葫芦画瓢地采集客户的业务过程,只能带来软件设计工作上的困境,届时的补充沟通工作会拉高软件前期的时间成本。
  2. 配置管理
    1. 基于fusion/stable模式的源代码管理非常不理想。
      1. 每当软件开发工作紧张的时候,几乎所有团队成员都会自觉不自觉地选择放弃向stable分支合并,以此逃避撰写log的工作。
      2. 一个划分良好的软件项目中,即使fusion模式下代码冲突率也非常低,fusion模式的尽早发现冲突的优点没能实现。(压根就没冲突)
      3. fusion模式下的历史记录功能也无法得到发挥,在没有log的版本历史中追溯是一件痛苦的事情,更重要的是所有人的提交历史都在导致版本号的增长,根本无法简单地确认自己需要恢复到的版本号。甚至它还没有传统的注释、重命名函数等让可疑代码停止发挥作用的手段有效。
      4. 由于多人的同时在工作,向stable合并的时候势必会提交仅仅提交者负责的模块处于stable状态的版本。这意味着stable分支上的历史其实总是非stable的。如果参与项目的人比较多的话,那么随便检出一个stable分支的版本源码,都会得到大部分模块不能工作的拷贝。
    2. 除了源代码、文档、数据库结构变更SQL之外,客户的服务器配置信息也应该纳入版本控制。产品上线后利用虚拟机创建的本地同步环境为补丁的上线测试提供了可能。虚拟机磁盘的snapshot功能在这种测试中帮助巨大——对于发布后无法正常工作的补丁,可以快速undo这次发布。
  3. 软件开发
    1. 开发工作必须以统分的方法进行,没有协调一致的整体设计作为前提,直接将模块划分给各人只能带来无法整合的独立模块。
    2. 绝对不能把需求分析工作交给不同的人,除非先分解成两个需求集合,并约定好各自的职责范围和协作规范,然而在大多数中小型软件项目中,这种规范约定工作耗费的时间会超过让大家开圆桌会议一起做需求分析所花的时间。
    3. 基于urlrewrite技术实现的单入口和路由导向规则喜忧参半,入口统一带来的优势非常明显,但代价也非常高昂,失去了$_GET变量,也失去了相对路径链接调度。以后可以考虑使用非/分割的urlrewrite。
    4. 一个数据验证和回存代码的自动生成工具让开发工作强度有所减轻,但是这个工具过于stupid也为系统引入了不少bug。
    5. 所有表单都设计为可用初始值填充,对于新增操作,初始值是空白,对于编辑操作,初始值是旧数据。使用session保存$_POST数据再进行登录和权限验证能有效提升用户体验,当登录超时发生时,这些保存的数据可以让用户辛苦填写的数据不必付之东流。
    6. 页面表单、实体对象属性、数据库字段三种名字的统一规范非常有利于降低页面开发工作量。比如包含表单数据的$_POST变量与包含旧数据的实体类因为统一了命名,所以都可以用来对表单做初始化填充。这样可以方便地做到部分字段不合法时不必导致整个表单数据丢失。
    7. 基于MVC模式开发,关注重点放在Controller上,这样一来数据模型和页面模版都无法复用。许多CURD页面都通过复制粘贴+少许修改实现,不符合DRY原则。未来项目可以考虑将关注点放在View上,让页面模板主动请求加载数据,而不是让控制器向其分配数据。另一方面,让页面模版中的功能和界面分离,可以实现部分页面逻辑的跨项目复用。
    8. 用“自动膨胀-定高”或者“自动膨胀-定宽”的方式设计界面,要比HTML+CSS简单实用得多,可以考虑编写一个XML到HTML的编译工具,将这种简单的页面布局方式翻译成HTML和CSS。
  4. 软件测试
    1. 及早开展测试工作总是正确的。
    2. 缺乏交换测试让开发舒适度最大化的同时也让bug最大化。
    3. 用边界检查的方法发现权限控制代码的问题比测试更有效。
    4. 缺乏良好的bug跟踪和反馈是这个项目的一大败笔。甚至在项目上线之后,许多人还在为已经解决的问题喋喋不休地讨论解决方案。如果坚持使用bugfree的话也许这就不是问题。
  5. 软件部署
    1. 缺乏互联网接入条件的现实让软件部署工作变得颇费周折,远程操作变得不可能实现。
    2. 基于patch的软件更新发布让前往现场进行部署工作的人员非常痛苦——他不得不小心翼翼地检查每一步操作。考虑基于deb软件包的安装升级方案或许会有所帮助。
    3. 没有图形界面的服务器让客户自己进行软件升级变得无比困难,即使使用deb包进行升级也需要在命令行下输入大量操作指令。
Continue Reading