`
piao_bo_yi
  • 浏览: 4455 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论
阅读更多
系统背景: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核心类图。
  • 大小: 45.8 KB
分享到:
评论
33 楼 ppgunjack 2011-01-15  
可以看看esri的MapObject的类图和设计,业务属性与地理图元对象从设计到存储都是分离的,用id绑定
本来这类几何软件就应该在类库有限的接口上做业务,裁剪业务需求,而不是不断把业务逻辑往类库上加
基础不好最好别重构,对于纯粹靠项目吃饭的人,工期内的重构大多数时候都是吃力不讨好
32 楼 guoapeng 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



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

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


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

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

所以我给楼主的建议是:
1、放弃代码洁癖,市场第一;
2、基本按照你的第一个方案,逐步重构:
   (1)、新写一套类,比如Pt2d、Anno之类,要求大家新开发的代码一定采用新的类;
   (2)、给原有的Point2D加上一个编译警告,设定一个期限(比如半年),要求所有人使用新的类,消除这个编译警告。
29 楼 ray_linn 2011-01-14  
point2d是父类,标志点,G点,都是子类
28 楼 bonny 2011-01-14  
在初步重构方案中
原来的Ponit2D对象依然沿用,但是不将其作为一个OO意义上的对象用,而作为一个门面模式。尽量保持对现系统的兼容

分析并构造新的对象。并通过原point2d来用。

这样做的目的是保持代码的清晰性和稳定性



以后新代码直接使用新对象,老代码通过搜索point2d对象,慢慢进行重够也不迟

27 楼 强强爱妍妍 2011-01-13  
统计原来的Point2D中的怪异属性被使用的场景.
针对发现的场景,用继承Point2D(x,y)或聚合Point2D(x,y)的方式产生新类,替换之.
26 楼 mingjian01 2011-01-13  
kurier 写道
piao_bo_yi 写道
kurier 写道
这时候大规模改动Point2d风险太大了。
可以考虑提取父类实现纯几何意义的2D点,然后再用策略模式实现各种语境下的不同含义:"在不同语境下有不同的物理含义,比如标注点, 三维点,等等”。
这样Point2d改动不太大,几何含义物理含义也分开了,经常变化的点也可控。

的确,风险是很大。实际情况是,现在系统不是运行得好好的,我只是单纯为了重构而重构。
1.我们现在添加功能,都是件很麻烦的事。
2.经常出一些很隐蔽的错误。调试需要花很多时间。
3.基于底层几何库的上层,对于几何库的错误,编程的时候有些人会采取对返回结果修正的方式编程。
4.由于物理逻辑没有从几何逻辑中抽出来,和这些物理意义相关的逻辑,实际上,在系统的不同模块都有类似的代码来处理。
所以,改变收益是很大的,风险是可以接受的。要是我们有单元测试就好了,哎~~~~~


在一些历时较久的系统中总是很容易出现这种问题。
我现在的理解,觉得根本原因在于,某些功能划分不清楚,没有明确功能的负责人,或者没有明确功能的所属模块。毕竟设计时总会有一些遗漏,当功能进入编码阶段,又不一定能及时反应过来。
所以我觉得,分散在各处的相似代码、修正代码等等一定是要收回来的,要不然意义不大。


按照LZ的情况,要收回来的成本太大,如果Point2D是属于底层类,并且被引用的次数比较多,证明基于这个类的功能和组件也很多。如果引用的地方很多,按一定机率来算产生新bug的地方起码上百个地方,而这些地方又会导致上层逻辑的出错,所以这个方案等于将系统推翻了。 但问题在于LZ希望将抽象和实现分开,但是又没办法将实现全部抽取出来,这是相当纠结啊。要不就直接从现在起系统采用新的2D架构,所有人写添加新功能时必须采用新2D架构来写,这样虽然遏制了原来2D架构的不良反应,但是如果已经在旧2D架构上已经有比较多的基础功能和组件的话,新2D架构就要花不少时间来重写这些功能和组件了,而且一个系统有两种架构的存在本来就是一个错误........
25 楼 Mr.China 2011-01-13  
大型系统?没有单元测试吗?
24 楼 kurier 2011-01-12  
piao_bo_yi 写道
kurier 写道
这时候大规模改动Point2d风险太大了。
可以考虑提取父类实现纯几何意义的2D点,然后再用策略模式实现各种语境下的不同含义:"在不同语境下有不同的物理含义,比如标注点, 三维点,等等”。
这样Point2d改动不太大,几何含义物理含义也分开了,经常变化的点也可控。

的确,风险是很大。实际情况是,现在系统不是运行得好好的,我只是单纯为了重构而重构。
1.我们现在添加功能,都是件很麻烦的事。
2.经常出一些很隐蔽的错误。调试需要花很多时间。
3.基于底层几何库的上层,对于几何库的错误,编程的时候有些人会采取对返回结果修正的方式编程。
4.由于物理逻辑没有从几何逻辑中抽出来,和这些物理意义相关的逻辑,实际上,在系统的不同模块都有类似的代码来处理。
所以,改变收益是很大的,风险是可以接受的。要是我们有单元测试就好了,哎~~~~~


在一些历时较久的系统中总是很容易出现这种问题。
我现在的理解,觉得根本原因在于,某些功能划分不清楚,没有明确功能的负责人,或者没有明确功能的所属模块。毕竟设计时总会有一些遗漏,当功能进入编码阶段,又不一定能及时反应过来。
所以我觉得,分散在各处的相似代码、修正代码等等一定是要收回来的,要不然意义不大。
23 楼 piao_bo_yi 2011-01-12  
mingjian01 写道
不知道LZ有没有统计这个类一共有多少个使用的场景,如果可能的话,是不是可以在Point2D中加入一个自动转换的方法  NewPonit2D AutoConvert( ),  将这种动态的旧类根据特定的属性(如: attribute.key().contains(" the atrribute")之类的判断)  转换为新类返回, 并返回新类的父类


场景我大概看了一下,数千个地方。按照你的做法我必须去读他们如何使用这个点类,然后判断是否可以用单纯的几何类替换。原来我也是这么想的,但是代码的质量的确不高,很多地方职责耦合太过严重。很多地方难以区分是否是单纯的几何运算。
22 楼 piao_bo_yi 2011-01-12  
kurier 写道
这时候大规模改动Point2d风险太大了。
可以考虑提取父类实现纯几何意义的2D点,然后再用策略模式实现各种语境下的不同含义:"在不同语境下有不同的物理含义,比如标注点, 三维点,等等”。
这样Point2d改动不太大,几何含义物理含义也分开了,经常变化的点也可控。

的确,风险是很大。实际情况是,现在系统不是运行得好好的,我只是单纯为了重构而重构。
1.我们现在添加功能,都是件很麻烦的事。
2.经常出一些很隐蔽的错误。调试需要花很多时间。
3.基于底层几何库的上层,对于几何库的错误,编程的时候有些人会采取对返回结果修正的方式编程。
4.由于物理逻辑没有从几何逻辑中抽出来,和这些物理意义相关的逻辑,实际上,在系统的不同模块都有类似的代码来处理。
所以,改变收益是很大的,风险是可以接受的。要是我们有单元测试就好了,哎~~~~~
21 楼 kurier 2011-01-11  
这时候大规模改动Point2d风险太大了。
可以考虑提取父类实现纯几何意义的2D点,然后再用策略模式实现各种语境下的不同含义:“在不同语境下有不同的物理含义,比如"标注点", 三维点,等等”。
这样Point2d改动不太大,几何含义物理含义也分开了,经常变化的点也可控。
20 楼 mingjian01 2011-01-11  
不知道LZ有没有统计这个类一共有多少个使用的场景,如果可能的话,是不是可以在Point2D中加入一个自动转换的方法  NewPonit2D AutoConvert( ),  将这种动态的旧类根据特定的属性(如: attribute.key().contains(" the atrribute")之类的判断)  转换为新类返回, 并返回新类的父类
19 楼 mingjian01 2011-01-11  

写个代表几何逻辑的Point2D父类,让旧的和新的point2d算法逻辑类都继承这个父类,新旧代码所有Point2D算法逻辑类全部重构成新的父类,以后再加新算法的时候再多个子类,这种方案行不?  我觉得如果算法会经常变的话,用工厂模式可以会好点
18 楼 inshua 2011-01-11  
怎么说呢,attributes ,name,动态语言。。。

最简单的做法就是弄个基类,只有 x y 两个属性,什么 get set 倒不是必须的,把现在这个类设为它的子类

下一步把用不到 name attributes 等属性的函数替换成这个新识别出来的基类

这个类貌似还缺一个 toString
17 楼 piao_bo_yi 2011-01-11  
truekbcl 写道

这个template不是用来考虑你的数值精度的,而是用来考虑的的体系结构。
比如从你的描述看,template<class Point, class Property> class PointBinder 这种结构比较容易使用。而你的处理器完全可以这样:template<class PointT> void processor(PointT & p)
{
    proc_point<PointT::point_type>(p);
    proc_property<PointT::property_type>(p);
}
你的这个Property完全可以不定义,而这些都用traits来处理。如果Property是一个空类型,proc_property这个模板函数直接被优化掉,根本不需要生成代码。这些都是编译器来搞定,不需要你去关心。
这样代码相当的直观,而不是oo那样到处是接口,而且至少必须提供一个空指针,你的维护就来了,而且修改接口,涉及到的都需要懂。template基本没有这些麻烦。


其实我这里的问题,和语言关系不大,和是不是用template关系不大。再好的技术也是人用,用不好还是一团乱。
16 楼 piao_bo_yi 2011-01-11  
truekbcl 写道

这个template不是用来考虑你的数值精度的,而是用来考虑的的体系结构。
比如从你的描述看,template<class Point, class Property> class PointBinder 这种结构比较容易使用。而你的处理器完全可以这样:template<class PointT> void processor(PointT & p)
{
    proc_point<PointT::point_type>(p);
    proc_property<PointT::property_type>(p);
}
你的这个Property完全可以不定义,而这些都用traits来处理。如果Property是一个空类型,proc_property这个模板函数直接被优化掉,根本不需要生成代码。这些都是编译器来搞定,不需要你去关心。
这样代码相当的直观,而不是oo那样到处是接口,而且至少必须提供一个空指针,你的维护就来了,而且修改接口,涉及到的都需要懂。template基本没有这些麻烦。


我觉得用template的目的,主要还是将逻辑和类型解耦,而直接针对概念编程。
比如distance(Point p1, Point p2);从共性上来说,无论Point是MyPoint还是YourPoint;是double还是float; 是直角坐标系、极坐标系还是自定义坐标系; 是2D还是3D点。distance都应该是一个接口,这时用template是非常适合的。
但是此处对于我来说,我是有很多点的类型,但是几何点只有一个,而不是多个。对于其他的含有物理逻辑的点类型来说,共性是很少的,比如一个物理逻辑点,他只能被命名为"xPoint", 他只能出现在区域[-1, -1], [1, 1]。这些非通用的算法你只能是把它作为这个类的成员函数。

对于你说的修改接口,需要的地方都需要动,用template也是一样的。
15 楼 truekbcl 2011-01-11  
piao_bo_yi 写道
truekbcl 写道
piao_bo_yi 写道
truekbcl 写道
这样的代码重构,template是不二的选择。

这个貌似和template没什么关系吧...

我的意思:采用template比oo的弹性大得多,你如果重构,可以考虑用template来做。


弹性大归大,但是修改量是相当恐怖的。其实我的向量类Vector<Real>是用模板做的,但后来发现其实没有必要。
1.我不需要提供不同的精度。double即满足我们的精度需求。
2.我不需要提供不同的坐标系。我们都是以直角坐标系建模,极坐标系等不用考虑。

这个template不是用来考虑你的数值精度的,而是用来考虑的的体系结构。
比如从你的描述看,template<class Point, class Property> class PointBinder 这种结构比较容易使用。而你的处理器完全可以这样:template<class PointT> void processor(PointT & p)
{
    proc_point<PointT::point_type>(p);
    proc_property<PointT::property_type>(p);
}
你的这个Property完全可以不定义,而这些都用traits来处理。如果Property是一个空类型,proc_property这个模板函数直接被优化掉,根本不需要生成代码。这些都是编译器来搞定,不需要你去关心。
这样代码相当的直观,而不是oo那样到处是接口,而且至少必须提供一个空指针,你的维护就来了,而且修改接口,涉及到的都需要懂。template基本没有这些麻烦。
14 楼 piao_bo_yi 2011-01-11  
thinkx 写道
把point2d换个名字不是太复杂的事情,因为编译器会替你检测所有的错误,你只要保证换名称后能编译通过即可;麻烦的是这20个人都得负责改这个名称。

可是需求不是给类换名字,汗...

相关推荐

    大型应用系统架构.pdf

    《大型应用系统架构》不仅为读者提供了坚实的理论基础,更重要的是教会了如何将这些理论应用于实践中,解决真实世界中的挑战。无论是对于刚接触这一领域的新人,还是已经有一定经验的专业人士来说,都是一本不可多得...

    大型网吧网络系统设计方案

    ### 大型网吧网络系统设计方案解析 #### 一、引言 随着互联网技术的迅猛发展,大型网吧作为集娱乐、休闲...随着技术的不断进步,未来的大型网吧网络系统设计还将面临更多挑战与机遇,持续优化与创新将是不变的主题。

    大型购物系统 大型购物系统

    在构建一个大型购物系统时,我们面临的是一个复杂的IT挑战,需要综合运用多种技术和策略来确保系统的高效、稳定和安全。以下是对这个大型购物系统的一些关键知识点的详细说明: 1. **架构设计**:大型购物系统通常...

    大型应用系统设计 系统安全设计 微博平台防御体系介绍 共25页.pdf

    在大型应用系统设计中,尤其是针对像微博这样的高并发、高可靠性、高性能的平台,系统安全设计至关重要。本文档主要围绕以下几个方面展开讨论: 首先,微博平台所面临的挑战包括高并发流量、对高可靠性和高性能的...

    大型系统架构简介

    大型系统的架构通常需要考虑到海量的网络访问和海量数据存储这两个要素。海量的网络访问意味着系统需要能够处理上亿次的页面浏览量(Page Views,简称PV)。而海量数据存储则要求系统能够保存和高效检索大量的数据,...

    大型网站系统与Java中间件实践PDF

    分布式事务处理,例如两阶段提交和补偿事务模型,也是大型网站系统必须面对的挑战。 负载均衡技术如Nginx和HAProxy,以及集群和分布式计算框架Hadoop和Spark的使用,能够帮助构建可扩展的系统,实现资源的有效利用...

    大型网站系统与java中间件实践 pdf下载 高清完整版

    1. **高并发处理**:如何有效地处理海量用户的并发请求,是大型网站系统面临的一个重大挑战。 2. **数据一致性**:在分布式环境下保持数据的一致性是一项复杂的任务。 3. **性能优化**:包括前端优化、数据库优化等...

    《大型网站系统与JAVA中间件实践》

    分布式事务处理是大型网站系统中的挑战之一。JAVA中间件如Atomikos、Seata提供了分布式事务解决方案,确保跨多个数据库或服务的事务一致性。 八、微服务架构 随着业务复杂性的增加,微服务架构成为趋势。JAVA的...

    大型网站系统与JAVA中间件实践-曾宪杰

    此外,还有分布式缓存、分布式文件系统、分布式计算等技术,以应对海量数据和高并发挑战。 四、性能优化 - **负载均衡**:通过负载均衡器将请求分发到多个服务器,避免单一节点过载。 - **缓存策略**:利用内存缓存...

    java大型架构三本全书(大型分布式网站架构设计,大型网站系统与java中间件实践,分布式java应用 基础与实践)

    Java大型架构设计主要涵盖的是构建高可用、高性能、可扩展的分布式系统的技术和实践,这在互联网行业中至关重要。三本书分别关注大型分布式网站架构设计、大型网站系统与Java中间件的实践以及分布式Java应用的基础与...

    大型网站系统 与 JAVA 中间件实践 曾宪杰

    这本书详细介绍了如何利用Java技术栈解决在开发和运维大型网站过程中遇到的各种挑战,旨在帮助读者理解并掌握Java中间件的核心原理与实践技巧。 在大型网站系统的构建中,Java中间件起着至关重要的作用。它们为高...

    大型水电站电力监控系统网络安全态势感知系统应用与研究.pdf

    为了应对这些挑战,国家提出了一些重点项目,比如“电力监控系统网络安全监测关键技术研究与示范应用”。这些项目要求500kV以上电压等级的大型水电站建设态势感知系统,部署网络安全监测厂站终端,并对现有电力监控...

    大型网站系统与Java中间件实践pdf+架构师视频资源

    2. **Java中间件**:Java中间件是构建大型系统的重要工具,包括但不限于Web服务器(如Tomcat)、应用服务器(如Jetty、JBoss)、消息队列(如RabbitMQ、Kafka)、缓存系统(如Redis、Memcached)、数据库(如MySQL、...

    C++大型仓库管理系统应用

    《C++大型仓库管理系统应用详解》 在信息技术日益发达的今天,仓库管理系统的应用已经渗透到各行各业,有效地提升了物流效率,降低了库存成本。本篇将深入探讨如何利用C++编程语言构建一个大型仓库管理系统,并结合...

    hadoop大型电商分布式系统实践视频-1

    大型电商平台通常面临以下挑战: - **海量数据处理**:每天产生的交易记录、用户行为数据等数量庞大。 - **高并发访问**:特别是在促销活动期间,需要应对瞬间激增的用户流量。 - **实时性要求**:例如库存管理、...

    大型网站系统与Java中间件实践读书笔记(二)

    【大型网站系统与Java中间件实践读书笔记(二)】 大型网站系统是指处理海量数据、应对高并发访问、以及应对复杂业务逻辑的网络...通过合理选择和设计中间件,可以有效解决大型网站面临的挑战,实现稳定、高效的运行。

Global site tag (gtag.js) - Google Analytics