论坛首页 Java企业应用论坛

浅谈系统拆分

浏览 7329 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2013-01-25  
今晚好冷啊,回去的路上,我突然想到一件关于系统拆分的事情。举的例子很极端,仅供参考,不一定有实际的意义

我感觉拆分系统,和拆分代码,本质上是一样的。小到一个方法,大到几个系统,都是一个从输入到输出的序列

Level 1:
public void doSomething(){
    System.out.println("111");
    System.out.println("222");
    System.out.println("333");
}

这种情况是最简单的,所有的代码都在一个方法里,没有任何拆分

Level2:
public void m2(){
    System.out.println("222");
}

public void doSomething(){
    System.out.println("111");
    m2();
    System.out.println("333");
}

效果和Level 1是一样的,只是中间多了一次方法的调用,实际上是内存指针偏移。但比起将所有代码写在一个方法里,这里已经做了最简单的拆分

Level3:
public class Class2{
    
    public static void m2(){
        System.out.println("222");
    }

}

public class Class1{

    public void doSomething(){

        System.out.println("111");
        Class2.m2();
        System.out.println("333");
    }

}

还是很简单,但是比Level2又多了一层,将部分代码拆分到了另一个类里

直到目前为止,无论拆分与否,所有的代码都在同一个进程里,所以都是本地调用(仅需要偏移内存指针即可),过程类似下图:



这里要补充一点,就JAVA平台来说,凡是要调用的代码在同一个JVM里,且classloader可见,都可以认为是本地调用。不管它是打包在.jar文件里,还是直接存放在classpath里,也不管其源码是否来自一个地方

Level4:



现在,输出222这段逻辑,被拆分到了另外一个系统里

所以,只有通过远程调用(RPC),才能111->222->333了,但是本质并没有改变,还是从输入到输出的一串序列,只是本地调用,和远程调用的区别

事实上,这种区别对调用者来说,常常是透明的
public void doSomething(){
    System.out.println("111");
    Proxy proxy = getProxy();// Proxy是一个interface
    proxy.print222ForMe();
    System.out.println("333");
}

对这个调用者来说,它并不需要知道proxy的实现来自哪里。这是一次本地调用还是一次远程调用,对调用者来说是透明的。只有在上面的部署图里,才能看出区别

通过这个例子,我想说明的是:核心的问题是逻辑,而不是怎么拆分系统。逻辑不会因为放在一个方法里,或者放在10个不同的系统里,就发生变化。最终的结果都是一样的。同时,当需要思考“为什么要拆分系统”的时候,某种程度上和“为什么要拆分代码”是类似的

实际的设计中,拆分系统一般都是必要的,我认为至少有以下3个方面的好处:

1、复用服务

前面举的例子过于简单了,可能有点无法说明问题。但是想象中间那行
System.out.println("222");

是一段非常重要的代码,其他很多逻辑都需要它。那么如果它是混杂在一个方法中,应用的其他部分就无法重复地调用它了(复用);而把它抽取出来之后,就可以实现复用

系统拆分也是一样,比如我画的这两张示意图,是用QQ截图功能截成JPG的。为了截这2张图,我只好把QQ给打开了。如果QQ截图被抽取为单独的模块,我就可以单独打开截图功能了;如果腾讯其他的应用也需要实现截图,就可以复用这部分功能了

当然,系统之所以被称为“系统”,而不是“应用”、“模块”、“方法”,是因为它比较大(我认为除此之外,完全是一回事,有输入、输出、逻辑的都是系统)

所以,作为系统,复用的往往不是截图这么小的功能,一般希望能够复用一个完整的服务。比如独立出“用户权限管理系统”,就可以在多个业务系统中,复用“用户校验和鉴权”的服务了。我想这就类似几年前比较流行的一个大词SAAS

2、性能考虑

一个大的系统,往往其中的某个部分,承担了很大的并发压力,或者逻辑运算特别复杂,因此成为系统的性能瓶颈

这时就可以考虑将这部分独立出来,从而实现单独部署,再通过负载均衡等手段,来解决性能的问题

3、逻辑清晰

根据业务上、流程上的不同环节,将整个系统拆分为不同的子系统,在逻辑上会更加清晰,从而更容易在架构上说清楚,或者进一步做优化

暂时想到这3点,欢迎补充

PS:至于源码工程的管理,完全是另一回事了。一个工程可以构建出N个系统;N个工程也可以构建出一个系统。是架构的2个不同角度的视图
  • 大小: 12 KB
  • 大小: 18 KB
   发表时间:2013-01-25  
OOP 有一点就是单一职责,也就是说不要把所有的逻辑揉在一起,要进行职责单一化,增加内聚,减少耦合,提高复用
0 请登录后投票
   发表时间:2013-01-25  
任何系统拆分,在脱离了需求环节上讨论,都是没有意义的。
0 请登录后投票
   发表时间:2013-01-25  
Kisses99 写道
任何系统拆分,在脱离了需求环节上讨论,都是没有意义的。


说得对,很赞同
0 请登录后投票
   发表时间:2013-01-26  
的确,纯粹为了解耦而解耦是没有意义的,解耦之后对程序运行效率是存在一定影响的!
0 请登录后投票
   发表时间:2013-01-29  
1、为什么要拆分?不易做单元测试,不易复用,不宜隔离Bug,不宜进行扩容。
2、拆分的依据?系统瓶颈,业务逻辑分层。
3、拆分的弊端?由本地调用转为远程调用,增加复杂性(如需共享数据,则需要进行通信),引入了网络不可靠性带来的处理。

个人之见,一起讨论。
0 请登录后投票
   发表时间:2013-01-31   最后修改:2013-01-31
      你说的基本都是面向对象的设计思想,系统拆分,首先毋庸置疑是提高了复用性,其二降低了耦合,不会因为强关联导致系统需求更改而大动干戈。其三,拆分可以使事物按多维度发展,从而更根据有扩展性。暂时先想到这么几点....
0 请登录后投票
论坛首页 Java企业应用版

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