最新软件架构设计大全.docx

上传人:b****2 文档编号:23191514 上传时间:2023-05-15 格式:DOCX 页数:36 大小:437.13KB
下载 相关 举报
最新软件架构设计大全.docx_第1页
第1页 / 共36页
最新软件架构设计大全.docx_第2页
第2页 / 共36页
最新软件架构设计大全.docx_第3页
第3页 / 共36页
最新软件架构设计大全.docx_第4页
第4页 / 共36页
最新软件架构设计大全.docx_第5页
第5页 / 共36页
点击查看更多>>
下载资源
资源描述

最新软件架构设计大全.docx

《最新软件架构设计大全.docx》由会员分享,可在线阅读,更多相关《最新软件架构设计大全.docx(36页珍藏版)》请在冰豆网上搜索。

最新软件架构设计大全.docx

最新软件架构设计大全

最新软件架构设计大全

架构之家

微信号itfly8

功能介绍ITFLY8架构之家,专注于架构知识分享交流,涵盖项目管理和产品设计。

包括大型分布式网站架构(高性能,高可用,缓存,消息队列...),设计模式,架构模式,大数据,项目管理(SCRUM,PMP,Prince2),产品设计等

架构引用维基百科:

软件体系结构是构建计算机软件实践的基础。

与建筑师设定建筑项目的设计原则和目标,作为绘图员画图的基础一样,一个软件架构师或者系统架构师陈述软件构架以作为满足不同客户需求的实际系统设计方案的基础。

从和目的、主题、材料和结构的联系上来说,软件架构可以和建筑物的架构相比拟。

一个软件架构师需要有广泛的软件理论知识和相应的经验来实施和管理软件产品的高级设计。

软件架构师定义和设计软件的模块化,模块之间的交互,用户界面风格,对外接口方法,创新的设计特性,以及高层事物的对象操作、逻辑和流程。

软件架构师与客户商谈概念上的事情,与经理商谈广泛的设计问题,与软件工程师商谈创新的结构特性,与程序员商谈实现技巧,外观和风格。

软件架构是一个系统的草图。

软件架构描述的对象是直接构成系统的抽象组件。

各个组件之间的连接则明确和相对细致地描述组件之间的通讯。

在实现阶段,这些抽象组件被细化为实际的组件,比如具体某个类或者对象。

在面向对象领域中,组件之间的连接通常用接口来实现。

架构来源于建筑工程学,描述对软件密集型系统设计蓝图。

在不同软件领域,有其不同特征,但有一部分共同基础设计原则和共性。

目录:

1—面向对象设计原则理解

2—一些软件设计的原则

3—逻辑层vs物理层

4—服务层的简单理解

5—SOA面向服务架构简述

6—业务逻辑层简述

7—设计箴言理解

8—数据访问层简述

9—存储过程传言

10—表现层模式-MVC

1—面向对象设计原则理解

面向对象设计(OOD)核心原则让我的程序模块达到“高内聚低耦合”,这是来自于30年前兴起的结构化设计(structuredDesign),但是同样适用于我们的OOD。

1.高内聚:

高内聚是指某个特定模块(程序,类型)都应完成一系列相关功能,描述了不同程序,类型中方法,方法中不同操作描述的逻辑之间的距离相近。

高内聚意味可维护性,可重新性,因为模块对外部的依赖少(功能的完备性)。

如果两个模块之间的修改,互不影响这说明模块之间是高内聚的。

模块的内聚和其担当的职责成反比,即,模块的职责越多,模块的内聚性越低,这也是模块的单一原则(SRP),SRP提倡每个类型都最好只承担单一的职责,只有单一的改变因素。

2.低耦合:

耦合是描述模块之间的依赖程度,如果一个模块的修改,都有影响另一个模块则,两模块之间是相互依赖耦合的。

(依赖具有传递性,耦合的两个模块可能间接依赖),低耦合是我们的设计目的,但不是不存在耦合不存依赖,依赖是必须的,因为模块之间必须通信交互,不过我的设计依赖应该依赖于不变或者不易变的接口,无需了解模块的具实现(OO封装性)。

在面向对象:

我们可以简述为功能完备(高内聚)的对象之间的交互是依赖于不变或不易变的接口契约(低耦合)。

实现高内聚低耦合:

行之有效的方式是分了关注点(SOC),将系统拆分成功能不同没有重叠功能集。

每个功能只关注一个方面(Aspect)保证模块之间功能没有或者尽量少的重复。

模块化内部实现细节隐藏,只暴露必须的接口,使得模块之间依赖于抽象,达到稳定。

分离关注点的思想存在于我们软件设计的各个领域。

如在.net的世界里SOA(面向服务架构)服务就是关注点,只暴露出必要的契约。

分层架构从逻辑上利用接口抽象信息隐藏,减少依赖。

MVC,MVP也是遵循分了关注点原则,达到表现层和逻辑的分离。

面向对象设计原则:

1.降低耦合度:

对象直接需要交互,这就存在依赖,为了实现低耦合就必须减少依赖,依赖于稳定或不易变抽象。

考虑如下订单日志记录场景:

我们需要在订单每部操作记录更改日志。

publicclassOrderManager

{

publicvoidCreate(Orderorder)

{

//订单处理.

Loggerlog=newLogger();

Stringhistory=GetHistory();

log.log(history);

}

}

在这里我们的OrderManager和Logger存在高耦合,Logger类的修改可能导致OrderManager的修改,而且不能随意切换我们的日志记录方式,比如文件,控制台,数据库等日志方式。

面向抽象编程提出抽象(接口,abstract类)是不易变的稳定抽象;对于OrderManager来说我不需要了解日志记录组件内部,只需要明白提供那些接口可用,怎么用。

publicinterfaceILogger

{

voidLog(Historyhistory);

}

publicclassLogger

{

publicvoidLog(Historyhistory)

{

//内部实现

};

}

那么我们可以从设计模式工厂模式(工厂模式是负责一些列相似对象的创建)Create日志组件ILogger。

我们的OrderManager就可以实现为:

ILoggerlog=LoggerFactory.Create();

log.Log(history);

这样我们的OrderManager就依赖于ILogger,而隔离Logger具体实现,将依赖于抽象,把变化缩小到Factory内部(同样也可以用抽象工厂),如果日志实现变化我们可以重新实现ILogger,修改Factory逻辑,如果内部利用配置我的需求变更转移到配置。

这就是面向对象第一原则,依赖于抽象而隐藏实现。

(利用IOC是一种更好的方式)

2.代码的重用性:

尽量保证相同功能代码只出现一次(Codeoncerunanywhere)。

代码的重用在面对对象设计中有继承和组合两种方式,一般推荐组合优先。

组合依赖于接口,组合更安全,易于维护,测试。

继承存在父类访问权限,父类的修改导致子类的变化,太多的继承也有导致派生类的膨胀,维护管理也是件头痛的事。

3.开闭原则(OCP):

表述拥抱需求变化,尽量做到对模块的扩展开发,修改关闭。

对于新增需求我们完美的做法是新增类型而不是修改逻辑,这就意味着我们必须使用组合或者是继承体系(为了避免上一条重用性,我的继承应该是干净的继承体系,派生类应该只是新增功能而不是修改来自父类上下文),

4.里氏替换(LSP):

表述派生类应该可以在任何地方替代父类使用。

并不是所有的子类都可以完全替换子类,比如设计父类私有上下文信息的访问,导致子类无法访问。

5.依赖倒置(DIP):

描述组件之间高层组件不应该依赖于底层组件。

依赖倒置是指实现和接口倒置,采用自顶向下的方式关注所需的底层组件接口,而不是其实现。

DI框架实现IOC(控制反转)就是DIP很好的插入底层组件构造框架(分构造注入,函数注入,属性注入)。

微软Unity,Castlewindsor,Ninject等框架支持。

最后分离关注点,衍生出声明式编程,面向方面编程(AOP)实现纵切关注点,把具体业务逻辑和日志安全等框架集公用逻辑分离。

2—一些软件设计的原则

以前本站向大家介绍过一些软件开发的原则,比如优质代码的十诫和Unix传奇(下篇)中所以说的UNIX的设计原则。

相信大家从中能够从中学了解到一些设计原理方面的知识,正如我在《再谈“我是怎么招聘程序”》中所说的,一个好的程序员通常由其操作技能、知识水平,经验层力和能力四个方面组成。

在这里想和大家说说设计中的一些原则,我认为这些东西属于长期经验总结出来的知识。

这些原则,每一个程序员都应该了解。

但是请不要教条主义,在使用的时候还是要多多考虑实际情况。

其实,下面这些原则,不单单只是软件开发,可以推广到其它生产活动中,甚至我们的生活中。

Don’tRepeatYourself(DRY)

DRY是一个最简单的法则,也是最容易被理解的。

但它也可能是最难被应用的(因为要做到这样,我们需要在泛型设计上做相当的努力,这并不是一件容易的事)。

它意味着,当我们在两个或多个地方的时候发现一些相似的代码的时候,我们需要把他们的共性抽象出来形一个唯一的新方法,并且改变现有的地方的代码让他们以一些合适的参数调用这个新的方法。

参考:

http:

//en.wikipedia.org/wiki/Don%27t_repeat_yourself

KeepItSimple,Stupid(KISS)

KISS原则在设计上可能最被推崇的,在家装设计,界面设计,操作设计上,复杂的东西越来越被众人所BS了,而简单的东西越来越被人所认可,比如这些UI的设计和我们中国网页(尤其是新浪的网页)者是负面的例子。

“宜家”(IKEA)简约、效率的家居设计、生产思路;“微软”(Microsoft)“所见即所得”的理念;“谷歌”(Google)简约、直接的商业风格,无一例外的遵循了“kiss”原则,也正是“kiss”原则,成就了这些看似神奇的商业经典。

而苹果公司的iPhone/iPad将这个原则实践到了极至。

把一个事情搞复杂是一件简单的事,但要把一个复杂的事变简单,这是一件复杂的事。

参考:

http:

//en.wikipedia.org/wiki/KISS_principle

Programtoaninterface,notanimplementation

这是设计模式中最根本的哲学,注重接口,而不是实现,依赖接口,而不是实现。

接口是抽象是稳定的,实现则是多种多样的。

以后面我们会面向对象的SOLID原则中会提到我们的依赖倒置原则,就是这个原则的的另一种样子。

还有一条原则叫Compositionoverinheritance(喜欢组合而不是继承),这两条是那23个经典设计模式中的设计原则。

Command-QuerySeparation(CQS)–命令-查询分离原则

∙查询:

当一个方法返回一个值来回应一个问题的时候,它就具有查询的性质;

∙命令:

当一个方法要改变对象的状态的时候,它就具有命令的性质;

通常,一个方法可能是纯的Command模式或者是纯的Query模式,或者是两者的混合体。

在设计接口时,如果可能,应该尽量使接口单一化,保证方法的行为严格的是命令或者是查询,这样查询方法不会改变对象的状态,没有副作用,而会改变对象的状态的方法不可能有返回值。

也就是说:

如果我们要问一个问题,那么就不应该影响到它的答案。

实际应用,要视具体情况而定,语义的清晰性和使用的简单性之间需要权衡。

将Command和Query功能合并入一个方法,方便了客户的使用,但是,降低了清晰性,而且,可能不便于基于断言的程序设计并且需要一个变量来保存查询结果。

在系统设计中,很多系统也是以这样原则设计的,查询的功能和命令功能的系统分离,这样有则于系统性能,也有利于系统的安全性。

参考:

http:

//en.wikipedia.org/wiki/Command-query_separation

YouAin’tGonnaNeedIt(YAGNI)

这个原则简而言之为——只考虑和设计必须的功能,避免过度设计。

只实现目前需要的功能,在以后您需要更多功能时,可以再进行添加。

∙如无必要,勿增复杂性。

∙软件开发先是一场沟通博弈。

以前本站有一篇关于过度重构的文章,这个示例就是这个原则的反例。

而,WebSphere的设计者就表示过他过度设计了这个产品。

我们的程序员或是架构师在设计系统的时候,会考虑很多扩展性的东西,导致在架构与设计方面使用了大量折衷,最后导致项目失败。

这是个令人感到讽刺的教训,因为本来希望尽可能延长项目的生命周期,结果反而缩短了生命周期。

参考:

http:

//en.wikipedia.org/wiki/You_Ain%27t_Gonna_Need_It

LawofDemeter–迪米特法则

迪米特法则(LawofDemeter),又称“最少知识原则”(PrincipleofLeastKnowledge),其来源于1987年荷兰大学的一个叫做Demeter的项目。

CraigLarman把LawofDemeter又称作“不要和陌生人说话”。

在《程序员修炼之道》中讲LoD的那一章叫作“解耦合与迪米特法则”。

关于迪米特法则有一些很形象的比喻:

∙如果你想让你的狗跑的话,你会对狗狗说还是对四条狗腿说?

∙如果你去店里买东西,你会把钱交给店员,还是会把钱包交给店员让他自己拿?

和狗的四肢说话?

让店员自己从钱包里拿钱?

这听起来有点荒唐,不过在我们的代码里这几乎是见怪不怪的事情了。

对于LoD,正式的表述如下:

对于对象‘O’中一个方法’M',M应该只能够访问以下对象中的方法:

1.对象O;

2.与O直接相关的ComponentObject;

3.由方法M创建或者实例化的对象;

4.作为方法M的参数的对象。

在《CleanCode》一书中,有一段Apacheframework中的一段违反了LoD的代码:

finalStringoutputDir=ctxt.getOptions().getScratchDir().getAbsolutePath();

这么长的一串对其它对象的细节,以及细节的细节,细节的细节的细节……的调用,增加了耦合,使得代码结构复杂、僵化,难以扩展和维护。

在《重构》一书中的代码的环味道中有一种叫做“FeatureEnvy”(依恋情结),形象的描述了一种违反了LoC的情况。

FeatureEnvy就是说一个对象对其它对象的内容更有兴趣,也就是说老是羡慕别的对象的成员、结构或者功能,大老远的调用人家的东西。

这样的结构显然是不合理的。

我们的程序应该写得比较“害羞”。

不能像前面例子中的那个不把自己当外人的店员一样,拿过客人的钱包自己把钱拿出来。

“害羞”的程序只和自己最近的朋友交谈。

这种情况下应该调整程序的结构,让那个对象自己拥有它羡慕的feature,或者使用合理的设计模式(例如Facade和Mediator)。

参考:

http:

//en.wikipedia.org/wiki/Principle_of_Least_Knowledge

面向对象的S.O.L.I.D原则

一般来说这是面向对象的五大设计原则,但是,我觉得这些原则可适用于所有的软件开发。

SingleResponsibilityPrinciple(SRP)–职责单一原则

关于单一职责原则,其核心的思想是:

一个类,只做一件事,并把这件事做好,其只有一个引起它变化的原因。

单一职责原则可以看作是低耦合、高内聚在面向对象原则上的引申,将职责定义为引起变化的原因,以提高内聚性来减少引起变化的原因。

职责过多,可能引起它变化的原因就越多,这将导致职责依赖,相互之间就产生影响,从而极大的损伤其内聚性和耦合度。

单一职责,通常意味着单一的功能,因此不要为一个模块实现过多的功能点,以保证实体只有一个引起它变化的原因。

∙Unix/Linux是这一原则的完美体现者。

各个程序都独立负责一个单一的事。

∙Windows是这一原则的反面示例。

几乎所有的程序都交织耦合在一起。

Open/ClosedPrinciple(OCP)–开闭原则

关于开发封闭原则,其核心的思想是:

模块是可扩展的,而不可修改的。

也就是说,对扩展是开放的,而对修改是封闭的。

∙对扩展开放,意味着有新的需求或变化时,可以对现有代码进行扩展,以适应新的情况。

∙对修改封闭,意味着类一旦设计完成,就可以独立完成其工作,而不要对类进行任何修改。

对于面向对象来说,需要你依赖抽象,而不是实现,23个经典设计模式中的“策略模式”就是这个实现。

对于非面向对象编程,一些API需要你传入一个你可以扩展的函数,比如我们的C语言的qsort()允许你提供一个“比较器”,STL中的容器类的内存分配,ACE中的多线程的各种锁。

对于软件方面,浏览器的各种插件属于这个原则的实践。

Liskovsubstitutionprinciple(LSP)–里氏代换原则

软件工程大师RobertC.Martin把里氏代换原则最终简化为一句话:

“Subtypesmustbesubstitutablefortheirbasetypes”。

也就是,子类必须能够替换成它们的基类。

即:

子类应该可以替换任何基类能够出现的地方,并且经过替换以后,代码还能正常工作。

另外,不应该在代码中出现if/else之类对子类类型进行判断的条件。

里氏替换原则LSP是使代码符合开闭原则的一个重要保证。

正是由于子类型的可替换性才使得父类型的模块在无需修改的情况下就可以扩展。

这么说来,似乎有点教条化,我非常建议大家看看这个原则个两个最经典的案例——“正方形不是长方形”和“鸵鸟不是鸟”。

通过这两个案例,你会明白《墨子小取》中说的——“娣,美人也,爱娣,非爱美人也….盗,人也;恶盗,非恶人也。

”——妹妹虽然是美人,但喜欢妹妹并不代表喜欢美人。

盗贼是人,但讨厌盗贼也并不代表就讨厌人类。

这个原则让你考虑的不是语义上对象的间的关系,而是实际需求的环境。

在很多情况下,在设计初期我们类之间的关系不是很明确,LSP则给了我们一个判断和设计类之间关系的基准:

需不需要继承,以及怎样设计继承关系。

InterfaceSegregationPrinciple(ISP)–接口隔离原则

接口隔离原则意思是把功能实现在接口中,而不是类中,使用多个专门的接口比使用单一的总接口要好。

举个例子,我们对电脑有不同的使用方式,比如:

写作,通讯,看电影,打游戏,上网,编程,计算,数据等,如果我们把这些功能都声明在电脑的抽类里面,那么,我们的上网本,PC机,服务器,笔记本的实现类都要实现所有的这些接口,这就显得太复杂了。

所以,我们可以把其这些功能接口隔离开来,比如:

工作学习接口,编程开发接口,上网娱乐接口,计算和数据服务接口,这样,我们的不同功能的电脑就可以有所选择地继承这些接口。

这个原则可以提升我们“搭积木式”的软件开发。

对于设计来说,Java中的各种EventListener和Adapter,对于软件开发来说,不同的用户权限有不同的功能,不同的版本有不同的功能,都是这个原则的应用。

DependencyInversionPrinciple(DIP)–依赖倒置原则

高层模块不应该依赖于低层模块的实现,而是依赖于高层抽象。

举个例子,墙面的开关不应该依赖于电灯的开关实现,而是应该依赖于一个抽象的开关的标准接口,这样,当我们扩展程序的时候,我们的开关同样可以控制其它不同的灯,甚至不同的电器。

也就是说,电灯和其它电器继承并实现我们的标准开关接口,而我们的开关产商就可不需要关于其要控制什么样的设备,只需要关心那个标准的开关标准。

这就是依赖倒置原则。

这就好像浏览器并不依赖于后面的web服务器,其只依赖于HTTP协议。

这个原则实在是太重要了,社会的分工化,标准化都是这个设计原则的体现。

参考:

http:

//en.wikipedia.org/wiki/Solid_(object-oriented_design)

CommonClosurePrinciple(CCP)–共同封闭原则

一个包中所有的类应该对同一种类型的变化关闭。

一个变化影响一个包,便影响了包中所有的类。

一个更简短的说法是:

一起修改的类,应该组合在一起(同一个包里)。

如果必须修改应用程序里的代码,我们希望所有的修改都发生在一个包里(修改关闭),而不是遍布在很多包里。

CCP原则就是把因为某个同样的原因而需要修改的所有类组合进一个包里。

如果2个类从物理上或者从概念上联系得非常紧密,它们通常一起发生改变,那么它们应该属于同一个包。

CCP延伸了开闭原则(OCP)的“关闭”概念,当因为某个原因需要修改时,把需要修改的范围限制在一个最小范围内的包里。

参考:

CommonReusePrinciple(CRP)–共同重用原则

包的所有类被一起重用。

如果你重用了其中的一个类,就重用全部。

换个说法是,没有被一起重用的类不应该被组合在一起。

CRP原则帮助我们决定哪些类应该被放到同一个包里。

依赖一个包就是依赖这个包所包含的一切。

当一个包发生了改变,并发布新的版本,使用这个包的所有用户都必须在新的包环境下验证他们的工作,即使被他们使用的部分没有发生任何改变。

因为如果包中包含有未被使用的类,即使用户不关心该类是否改变,但用户还是不得不升级该包并对原来的功能加以重新测试。

CCP则让系统的维护者受益。

CCP让包尽可能大(CCP原则加入功能相关的类),CRP则让包尽可能小(CRP原则剔除不使用的类)。

它们的出发点不一样,但不相互冲突。

参考:

HollywoodPrinciple–好莱坞原则

好莱坞原则就是一句话——“don’tcallus,we’llcallyou.”。

意思是,好莱坞的经纪人们不希望你去联系他们,而是他们会在需要的时候来联系你。

也就是说,所有的组件都是被动的,所有的组件初始化和调用都由容器负责。

组件处在一个容器当中,由容器负责管理。

简单的来讲,就是由容器控制程序之间的关系,而非传统实现中,由程序代码直接操控。

这也就是所谓“控制反转”的概念所在:

1.不创建对象,而是描述创建对象的方式。

2.在代码中,对象与服务没有直接联系,而是容器负责将这些联系在一起。

控制权由应用代码中转到了外部容器,控制权的转移,是所谓反转。

好莱坞原则就是IoC(InversionofControl)或DI(DependencyInjection)的基础原则。

这个原则很像依赖倒置原则,依赖接口,而不是实例,但是这个原则要解决的是怎么把这个实例传入调用类中?

你可能把其声明成成员,你可以通过构造函数,你可以通过函数参数。

但是IoC可以让你通过配置文件,一个由ServiceContainer读取的配置文件来产生实际配置的类。

但是程序也有可能变得不易读了,程序的性能也有可能还会下降。

参考:

∙http:

//en.wikipedia.org/wiki/Hollywood_Principle

∙http:

//en.wikipedia.org/wiki/Inversion_of_Control

HighCohesion&Low/Loosecoupling&–高内聚,低耦合

这个原则是UNIX操作系统设计的经典原则,把模块间的耦合降到最低,而努力让一个模块做到精益求精。

∙内聚:

一个模块内各个元素彼此结合的紧密程度

∙耦合:

一个软件结构内不同模块之间互连程度的度量

内聚意味着重用和独立,耦合意味着多米诺效应牵一发动全身。

参考:

∙http:

//en.wikipedia.org/wiki/Coupling_(computer_science)

∙http:

//en.wikipedia.org/wiki/Cohesion_(computer_science)

ConventionoverConfiguration(CoC)–惯例优于配置原则

简单点说,就是将一些公认的配置方式和信息作为内部缺省的规则来使用。

例如,Hibernate的映射文件,如果约定字段名和类属性一致的话,基本上就可以不要这个配置文件了。

你的应用只需要指定不conve

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 小学教育 > 英语

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1