首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件开发 >

特大型系统的挑战

2012-09-28 
大型系统的挑战系统背景:1.c++100~150万行源代码。CS体系结构。CAE,CAM类型的桌面程序。2.历时4年×20人开发周

大型系统的挑战
系统背景:1.c++100~150万行源代码。CS体系结构。CAE,CAM类型的桌面程序。
               2.历时4年×20人开发周期。
               3.产品开发,距发布还有1年。

重构背景:
当我负责重构整个系统的几何算法库的时候,发现我们系统里有一个用来表示几何二维点Point2d的类,用来表示Point2d几何相关的逻辑。单纯几何逻辑不应该包括下面代码的name, attributes,2D几何点不应该包括z.
class Point2d
{
public double x;
public double y;
public double z;
public String name;
public Map<String, String> attributes;
}

随着时间的推移,越多的属性被添加进去,很明显点这个类承担了过多的职责。这个类被大量使用。在不同语境下有不同的物理含义,比如"标注点", 三维点,等等。
重构过程我认为是异常复杂的。
方案一:
将Point2d换个名字,用来表示混乱逻辑的2D点。新建一个纯几何意义的2D点。新的代码尽量使用新的数据结构。这样做的好处是隔离了系统继续耦合的趋势。但是,这种做法多了,会对系统的可理解性造成致命伤害。想象一下,你想用一个几何点的时候,你有多个选择是多么恐怖的场景。实际上,我们系统已经有了不同的三套几何算法库了,相当混乱。
方案二:
其实我是没有其他方案了,也许你会说分别修改所有引用点,根据使用,建立新的点类,最终去掉原有Point2d类多余的属性和职责。但是系统是巨大的(100~150万行),引用的地方怎样使用我单独去看,是看不明白的。另外,没有单元测试可以保证我的修改是正确的。先写所有单元测试也不是现实的,当然,我不太期望我重构时系统不会引入我误操作的Bug。

我想这个问题的解决方案应该不仅是技术上的,还应该从时间安排,重构的过程控制,团队的分工来思考。各位大虾,来点头脑风暴,发表自己的高见吧。

P.S.
1.上面代码为伪代码,实际系统是c++组成的。
2.将把您的建议实施,并反馈重构过程和结果。
重构进度
1.2011-01-11
过程:对name, attributes, z添加get,set函数。用时4个小时。
问题:由于系统重构中,原有功能有些不能用,所以部分人没有更新代码,他们新添加的代码有可能出错。
2.2011-01-12
过程:今天大家都提到了提取出纯几何意义的父类。其实这个想法和我的方案一应该是一个意思。弊端上面也描述了。
今天我打算先去掉一两个和三维点有关的函数,将其引用处改为三维点。

附上我们几何库的2D核心类图。

场景我大概看了一下,数千个地方。按照你的做法我必须去读他们如何使用这个点类,然后判断是否可以用单纯的几何类替换。原来我也是这么想的,但是代码的质量的确不高,很多地方职责耦合太过严重。很多地方难以区分是否是单纯的几何运算。//增加Point2dProxy classclass Point2dProxy implements IPoint2d{ public String [color=red]name[/color]; public Map<String, String> [color=red]attributes[/color]; public IPoint2d point2d; public double getX(){ return point2d.getX(); } public double getY(){ return point2d.getY(); } public Point2dProxy ( IPoint2d point2d){ this.point2d = point2d; } public void setAttribute(String key, String value){ attributes.add(key,value); }}class Point2d implements IPoint2d{//用重构里面的extract class方法 抽取成一个Point3d class[/color][color=red]//public double x;//public double y;//public double z;//新增加属性 point3d , public IPoint3d point3d;name and attributes 移动到Point2dProxy 中//public String [color=red]name[/color];//public Map<String, String> [color=red]attributes[/color];[color=red]//新增加构造器public Point2d(double x, double y){ point3d = PointFactory.createPoint(x,y,0); //z恒等于0} public double getX(){ return point3d.x; } public double getY(){ return point3d.y; }}class Point3d implements IPoint3d{ public double x; public double y; public double z; public double getX(){ return x; } public double getY(){ return y; } public double getZ(){ return z; } public Point3d (double x, double y, double z){ this.x=x; this.y=y; this.z=z; }}interface IPoint3d{ public double getX(); public double getY(); public double getZ();}interface IPoint2d{ public double getX(); public double getY();}// 所有的point都通过 PointFactory 创建class PointFactory(){ public static IPoint3d createPoint(double x, double y, double z){ return new Point3d (x,y,z); } public static IPoint2d createPoint(double x, double y){ return new Point2d (x,y); } public static Point2dProxy createPoint2dProxy(double x, double y){ return new Point2dProxy (createPoint(x,y)); }}//调用举例[color=red]//创建point2dPoint2dProxy aPoint2d = PointFactory.createPoint2dProxy(3,8);aPoint2d.setName("XXX");aPoint2d.setAttrubute("key1","valuex");//get Attribute or x y z and so on.aPoint2d.getx();....//判断是 是否是2d pointif(aPoint2d instanceof IPoint2d) if(aPoint2d instanceof IPoint3d) // The end
33 楼 ppgunjack 2011-01-15   可以看看esri的MapObject的类图和设计,业务属性与地理图元对象从设计到存储都是分离的,用id绑定
本来这类几何软件就应该在类库有限的接口上做业务,裁剪业务需求,而不是不断把业务逻辑往类库上加
基础不好最好别重构,对于纯粹靠项目吃饭的人,工期内的重构大多数时候都是吃力不讨好

热点排行