2013年上半年项目总结
哎 不得不感慨一下 入职两年 终于要接触一个正规的项目了!
首先说一下系统架构
这次的项目是C/S架构的,但是以后有可能要将大部分功能移植到Brower甚至移动终端上,所以这次采用了面向服务架构。
用Java搭建提供数据服务的后台服务器;而客户端则是C#,一堆WinForm拖控件搞定。
面向服务听起来挺洋气,实际上无非就是提供一个带有某种约定的公共数据接口,只要按照约定的请求方式(路径),就会获取到数据。
当然发送和获取的数据都是字符串,所以我们是传输JSON格式数据,然后双方在各自转换,如下图
人员构成
总共10人:一个产品经理兼ScrumLeader,两个小组负责人,7个开发人员
这两个小组负责人也是70%的时间开发,30%的时间帮助小组的开发(查看组员的开发进度等)
C#端架构
C#方面分为Model(实体),IDAL(数据接口),DAL(数据接口实现),BLL(业务),Tools(各种工具类),Test(单元测试),UI(表现)七部分
其中 DAL部分使用有一个数据操作的工具类RestHelper(功能相当于DBHelper),是为了Rest而存在的数据处理类
大部分的业务数据处理逻辑都放在了BLL中。谈到业务层,刚开始的时候也是很纠结的,明明规划的是所有业务逻辑都放到BLL中,UI只负责显示。
可是开发一段时间后发现这很不现实,因为很多UI的变化也是一种业务,难道要把对UI的更新也放到BLL中?最后索性只将业务的数据部分放到BLL。不知道有其他什么好方案否。。
单元测试是用的微软自带的测试工具(VS2010中,右键->创建单元测试 相当简单的说)
.Net Spring
出于面向接口编程考虑,在C#端采用了.Net Spring。
首先要添加两个引用:①Common.Logging ②Spring.Core (这个需要自己下载)
然后在项目下添加Spring配置文件Spring.xml.config,内容如下
<?xml version="1.0" encoding="utf-8" ?> <objects xmlns="http://www.springframework.net"> <object id="XXXService" type="com.DAL.XXXService,XXXUI"></object> <object id="XXXManager" type="com.BLL.XXXManager,XXXBLL"> <property name="service" ref="XXXService"/> <!--这里的XXXService与上面的XXXService相关联--> </object> </objects>
注:
- com.DAL.XXXService --> DAL层的数据接口实现类
- XXXUI --> DAL层的工程名
- XXXService --> 该实现类的代理名,在调用该数据接口的业务层代码里会用到
- com.BLL.XXXManager --> 业务实现类
- XXXBLL --> BLL层的工程名
- XXXManager --> 业务实现类的代理名,在调用业务的UI层代码中会用到
还要在工程的配置文件里添加上Spring的相关信息
如果是Winform程序的话,则是App.config文件,如果是Web程序的话,则是Web.config
在根节点<configuration>下添加如下内容
<configSections> <sectionGroup name="spring"> <section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core" /> </sectionGroup> </configSections> <spring> <context> <resource uri="http://www.cnblogs.com/spring.xml.config" /> </context> </spring>
到这里配置工作就OK了,最后是调用。
//IDAL数据接口层 提供数据接口方法 namespace com.IDAL { public interface XXXIService { int GetCount(); } } //DAL数据接口实现层 使用DBHelper通过传递WebService的相关资源路径请求数据 namespace com.DAL { public class XXXService { public int GetCount() { return DBHelper.GetCount("RequestRoot"); } } } //BLL业务层 细看一下就会发现 业务层里的数据接口没有使用固定的实现类 //而是接口,只将其声明为了一个属性却没有赋值。而这部分工作就是Spring做的 namespace com.BLL { public class XXXManager { private IXXXService service; public IXXXService Service { get { return service; } set { service = value; } } public int GetCount() { return service.GetCount(); } } } //UI层 注意要添加下面两个using using Spring.Context; using Spring.Context.Support; namespace com.UI { public partial class XXXForm : Form { private XXXManager manager; public XXXForm() { InitializeComponent(); IApplicationContext context = ContextRegistry.GetContext(); manager = (XXXManager)context.GetObject("XXXManager"); ooo(); } public void ooo() { MessageBox.Show(manager.GetCount().ToString()); } } }
日志模块
在C#里,日志模块使用的log4net。这个网上的介绍很多 就不多说了。
这样C#端就大功告成了!
细节方面
Model层,IDAL层都需要各自的基类,如Model层需要一个基类定义可序列化(在类名上面加[Serializable])和分页属性(数据检索的大部分场合)
获取数据的时候会将对象序列化后的信息作为参数传递,这样后台就会得到分页数据了。
IDAL层中的基类是用于提供一些公用的方法,如单个对象的增删改,根据检索条件获取结果量等等。为了可以被其他类公用,必须是要有泛型的。
using System; using System.Collections.Generic; namespace com.IDAL.Base { public interface ServiceBase<T> { /// <summary> /// 查询所有对象集合 /// </summary> /// <returns>对象集合</returns> IList<T> SelectAll(); /// <summary> /// 返回总行数 /// </summary> /// <returns>总行数</returns> int SelectAllCount(); /// <summary> /// 根据条件返回总行数 /// </summary> /// <param name="item">条件对象</param> /// <returns>总行数</returns> int SelectAllCount(T item); /// <summary> /// 查询符合条件的对象集合 /// </summary> /// <param name="item">条件对象</param> /// <returns>对象集合</returns> IList<T> SelectByObj(T item); /// <summary> /// 以一个对象作为条件修改对象数据 /// </summary> /// <param name="item">条件对象</param> /// <returns>成功与否</returns> bool Update(T item); /// <summary> /// 以多个对象作为条件修改对象数据 /// </summary> /// <param name="list">对象集合</param> /// <returns>成功与否</returns> bool Update(IList<T> list); /// <summary> /// 以一个对象作为条件删除对象数据 /// </summary> /// <param name="item">条件对象</param> /// <returns>成功与否</returns> bool Delete(T item); /// <summary> /// 以多个对象作为条件删除对象数据 /// </summary> /// <param name="list">对象集合</param> /// <returns>成功与否</returns> bool Delete(IList<T> list); /// <summary> /// 插入一个对象 /// </summary> /// <param name="item">对象</param> /// <returns>成功与否</returns> bool Insert(T item); /// <summary> /// 插入多个对象 /// </summary> /// <param name="list">对象集合</param> /// <returns>成功与否</returns> bool Insert(IList<T> list); /// <summary> /// 根据主键查询数据 /// </summary> /// <param name="id">数据主键</param> /// <returns>单个对象</returns> T SelectById(int id); } }
项目开发中的问题总结
1.不管是使用SVN还是VSS,代码的提交最好有一个固定的周期或固定的场合。
如每天下班前提交能成功运行的代码(要保证队友如果获取全部最新代码也能成功运行),或者一个功能模块完成后提交。
但是有些蛋疼的队友,自己都无法运行的代码你也提交上去,这不是害人呢么。别人获取之后就无法调试了,还要等你修改完,相当的不好。
2.项目开始前 对技术的了解不够。例如这次后台用Java,前台用C# 二者之间用JSON格式字符串传递数据。说起来简单,但实际开发起来之后就发现
C#与JAVA处理JSON格式数据时,实体类与JSON数据的双向解析方式有很多不同的地方。因为前期没有考虑到类似的问题会占用好多时间,所以队友的工期就会出现较大的出入。