http://martinfowler.com/bliki/SacrificialArchitecture.html
http://www.infoq.com/cn/news/2014/11/sacrificial-architecture
Good modularity is a vital part of a healthy code base, and modularity is usually a big help when replacing a system. Indeed one of the best things to do with an early version of a system is to explore what the best modular structure should be so that you can build on that knowledge for the replacement. While it can be reasonable to sacrifice an entire system in its early days, as a system grows it's more effective to sacrifice individual modules - which you can only do if you have good module boundaries.
http://ifeve.com/talk-arch-module/
http://mp.weixin.qq.com/s?__biz=MzI4MjA4ODU0Ng%3D%3D&idx=1&mid=401373742&sn=e27102eda726a2a56ee097013c2754ac
论架构师的自我修养
中小型网站架构分析及优化
http://www.infoq.com/cn/news/2014/11/sacrificial-architecture
But often the best code you can write now is code you'll discard in a couple of years time.
At Google, the explicit rule is to design a system for ten times its current needs, with the implication that if the needs exceed an order of magnitude then it's often better to throw away and replace from scratch[1]. It's common for subsystems to be redesigned and thrown away every few years.
Good modularity is a vital part of a healthy code base, and modularity is usually a big help when replacing a system. Indeed one of the best things to do with an early version of a system is to explore what the best modular structure should be so that you can build on that knowledge for the replacement. While it can be reasonable to sacrifice an entire system in its early days, as a system grows it's more effective to sacrifice individual modules - which you can only do if you have good module boundaries.
You can also apply this principle to features within an existing system. If you're building a new feature it's often wise to make it available to only a subset of your users, so you can get feedback on whether it's a good idea. To do that you may initially build it in a sacrificial way, so that you don't invest the full effort on a feature that you find isn't worth full deployment.
Modular replaceability is a principal argument in favor of a microservices architecture, but I'm wary to recommend that for a sacrificial architecture. Microservices imply distribution and asynchrony, which are both complexity boosters. I've already run into a couple of projects that took the microservice path without really needing to — seriously slowing down their feature pipeline as a result. So a monolith is often a good sacrificial architecture, with microservices introduced later to gradually pull it apart.
当前正确的设计对于十倍或者百倍的增长可能就是非常错误的了,可以针对十倍的增长进行设计,但在增长到百倍之前就要计划去重写了。模块化是一个可维护性应用最重要的特性。一个模块化的应用不会浪费,部件可以被修改、替换或者抛弃掉,而不会影响到应用的其他部件。
http://ifeve.com/talk-arch-module/
如何划分模块?
- 基于水平切分。把一个系统按照业务类型进行水平切分成多个模块,比如权限管理模块,用户管理模块,各种业务模块等。
- 基于垂直切分。把一个系统按照系统层次进行垂直切分成多个模块,如DAO层,SERVICE层,业务逻辑层。
- 基于单一职责。将代码按照职责抽象出来形成一个一个的模块。将系统中同一职责的代码放在一个模块里。比如我们开发的系统要对接多个渠道的数据,每个渠道的对接方式和数据解析方式不一样,为避免不同渠道代码的相互影响,我们把各个渠道的代码放在各自的模块里。
- 基于易变和不易变。将不易变的代码抽象到一个模块里,比如系统的比较通用的功能。将易变的代码放在另外一个或多个模块里,比如业务逻辑。因为易变的代码经常修改,会很不稳定,分开之后易变代码在修改时候,不会将BUG传染给不变的代码。
易变和不易变?
根据代码的易变程度,将不变和变化的功能隔离,可以让代码更加稳定,减少代码的修改量,从而降低维护成本。从几个层面逐渐入手:
- 系统分层:J2EE系统一般都划分成页面展现层,业务逻辑层和持久层。业务逻辑层容易变,而持久层变化小。对外提供服务系统分层是服务层,实现层和持久层,一般也是实现层不稳定需要经常修改,但是修改不会波及到持久层和服务层。将系统分层后,底层要更加稳定,可以新增接口或代码,但是尽量减少修改代码,因为底层一旦出错,影响面会非常广。系统间的分层也同样是需要底层系统更稳定。
- 代码分隔:代码上分为接口,抽象类和实现类。抽象类和接口要做到充分的抽象,从而减少修改。比如接口要符合单一原则,避免接口修改。比如Java的Closeable接口里只有一个close方法,指责非常单一,所以无论未来有什么场景,基本不会修改这个接口。如果你的接口里有很多其他职责的方法,一旦一个方法修改,很多实现类就必须跟着修改。
http://mp.weixin.qq.com/s?__biz=MzI4MjA4ODU0Ng%3D%3D&idx=1&mid=401373742&sn=e27102eda726a2a56ee097013c2754ac
论架构师的自我修养
中小型网站架构分析及优化