论坛首页 综合技术论坛

大型系统的挑战

浏览 17774 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2011-01-14  
以前参与研发的一个产品,和楼主所说系统类似:工程类产品,c++编写,代码规模也相近。
这个产品是这样处理复杂性的:把整个产品分成几十个模块(exe),然后每个项目组成员负责其中一个或者几个模块。所有这些模块不共用任何底层库(少数共用采用 copy&paste 方式)。
很显然,这会带来这些问题:
1、代码不统一,Point类至少有数十个;
2、GUI不统一,各个模块之间的界面风格和操作模式,差异非常大;
2、很多轮子会被重复制造几十次,开发效率很低。
我初进这个项目组的时候,认为这样的开发模式太不可思议了,完全就是个笑话。
但是,大家想知道最终结果吗?最终结果是,这个产品在市场上相当成功,是中国极少数能在国外(包括欧美日)也有一定销售额的软件产品之一。
后来我又考虑了一下,我认为这种方式是可以理解的。因为项目组领导和成员都不是计算机专业毕业,只对专业精通,但不怎么懂软件开发和软件开发管理。如果按照一个多层架构来做,其复杂性可能是项目组无法控制的。

所以我给楼主的建议是:
1、放弃代码洁癖,市场第一;
2、基本按照你的第一个方案,逐步重构:
   (1)、新写一套类,比如Pt2d、Anno之类,要求大家新开发的代码一定采用新的类;
   (2)、给原有的Point2D加上一个编译警告,设定一个期限(比如半年),要求所有人使用新的类,消除这个编译警告。
0 请登录后投票
   发表时间:2011-01-14  
xuby 写道
以前参与研发的一个产品,和楼主所说系统类似:工程类产品,c++编写,代码规模也相近。
这个产品是这样处理复杂性的:把整个产品分成几十个模块(exe),然后每个项目组成员负责其中一个或者几个模块。所有这些模块不共用任何底层库(少数共用采用 copy&paste 方式)。
很显然,这会带来这些问题:
1、代码不统一,Point类至少有数十个;
2、GUI不统一,各个模块之间的界面风格和操作模式,差异非常大;
2、很多轮子会被重复制造几十次,开发效率很低。
我初进这个项目组的时候,认为这样的开发模式太不可思议了,完全就是个笑话。
但是,大家想知道最终结果吗?最终结果是,这个产品在市场上相当成功,是中国极少数能在国外(包括欧美日)也有一定销售额的软件产品之一。
后来我又考虑了一下,我认为这种方式是可以理解的。因为项目组领导和成员都不是计算机专业毕业,只对专业精通,但不怎么懂软件开发和软件开发管理。如果按照一个多层架构来做,其复杂性可能是项目组无法控制的。

所以我给楼主的建议是:
1、放弃代码洁癖,市场第一;
2、基本按照你的第一个方案,逐步重构:
   (1)、新写一套类,比如Pt2d、Anno之类,要求大家新开发的代码一定采用新的类;
   (2)、给原有的Point2D加上一个编译警告,设定一个期限(比如半年),要求所有人使用新的类,消除这个编译警告。


这种软件一般都是些科学或者工程用的计算软件。我研究所的老板是希腊人,非科班出身,写的代码除了效率毫无可读性可言。她20多年前曾经开发过一个小软件 卖了也有好多份,据称她有一年无所事事,就靠这个软件养活了一家人。

我看过她的源码,几乎所有重构说的毛病都犯了..但是这还是个成功在市场上能卖的..
0 请登录后投票
   发表时间:2011-01-15   最后修改:2011-01-15
//直接上代码,大家都是做程序的,相信能看懂,建议都在代码里面了,
建议1:让工厂去创建你要的对象,这样你每次用子类去替换父类时,只关注工厂方法就够了;
建议2:适当地定义接口,别人在实现类中增加新方法的时候,没那么容易破换你的接口,
       重构时你也可以很轻而易举的把新方法抽取多他应该去的地方。好处很多,坏处只是繁琐而已。
建议3: 注意属性的可见性;我看你的代码很多属性都是public, 而且都没有get set 方法,这样做对后期代码重构是很麻烦的,类属性的可见性如private, protected, public, 这个不能乱用,不该让其他人调用的属性或方法坚决隐藏起来,这样可以给你重构时留下很多余地,重构时你会爱上private 和protected的。


//增加Point2dProxy class

class 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]//创建point2d
Point2dProxy  aPoint2d = PointFactory.createPoint2dProxy(3,8);
aPoint2d.setName("XXX");
aPoint2d.setAttrubute("key1","valuex");


//get Attribute or x y z and so on.
aPoint2d.getx();
....


//判断是 是否是2d point

if(aPoint2d instanceof IPoint2d) 

if(aPoint2d instanceof IPoint3d) 

 // The end



0 请登录后投票
   发表时间:2011-01-15  
可以看看esri的MapObject的类图和设计,业务属性与地理图元对象从设计到存储都是分离的,用id绑定
本来这类几何软件就应该在类库有限的接口上做业务,裁剪业务需求,而不是不断把业务逻辑往类库上加
基础不好最好别重构,对于纯粹靠项目吃饭的人,工期内的重构大多数时候都是吃力不讨好
0 请登录后投票
论坛首页 综合技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics