Download presentation
Presentation is loading. Please wait.
1
第12讲. 架构与其他模式
2
内容 架构分析 2018/1/25
3
1. 架构分析 架构分析的意义 降低在系统设计中丢失某些重要因素的风险 避免在低优先级的问题上花费过多的精力 有助于产品与业务目标的一致
2018/1/25
4
何时开始架构分析 早期工作中就要识别和解决架构问题 架构分析和早期开发活动并行 2018/1/25
5
变化点和进化点 变化点:当前现有系统或需求中的变化之处 进化点:现有需求中不存在,但可能在将来发生,推测性的变化点 2018/1/25
6
架构分析是在功能性需求(例如销售处理)的语境中,识别和处理系统的非功能性需求(例如安全需求等)的活动。
2018/1/25
7
架构分析 问题示例 可靠性和容错需求如何影响设计 采购子构件的许可费用如何影响收益率 可适应性和可配置性需求如何影响设计
商标名称的选择如何影响架构 2018/1/25
8
常用步骤 识别和分析对架构有影响的非功能性需求
对于这些在架构方面具有重要影响的需求,需要分析可供选择的办法并创建解决这些影响的解决方案—架构决策 2018/1/25
9
架构因素的识别和分析 所有的FURPS+需求对系统的架构都有重要影响,其中涉及可靠性,进度安排,技巧和成本约束等
具有架构意义的因素称为关键架构因素 2018/1/25
10
描述方法 架构因素表(P394) 包括因素,度量和质量场景,可变性,影响,对于成功的优先级,困难或风险 2018/1/25
11
收集和组织有关的架构性因素,称为架构的科学 依据相互依赖情况,优先级,权衡考虑等,做出解决这些因素的决定,称为架构的艺术
2018/1/25
12
记录架构选择,决策以及动机 优先级 基本的架构设计原则 技术备忘录 引导架构决策的目标:强制性约束,业务目标,所有其它目标
我们已经介绍的原则都适用:低耦合,高内聚,防止变异 构件的粒度更大 2018/1/25
13
目标 运用分层模式,对系统进行层和分块逻辑体系结构设计
运用UML包图Illustrate the logical architecture using UML package diagrams 运用外观,观察者和控制器模式 2018/1/25
14
What is Software Architecture
There are many definitions Software architecture deals with the big picture The organization and structure of the major elements of the system Architectural analysis Architectural Investigation Architectural Design 2018/1/25
15
架构模式 模式分类 架构模式 设计模式 Idioms 2018/1/25 大范围和粗粒度的设计:分层模式
与小范围和中等范围的对象和框架设计有关: Façade, Strategy Pattern Idioms Language or implementation-oriented low-level design solutions: Singleton pattern 2018/1/25
16
架构模式: 分层
17
问题 在应用中,哪一个部分最容易改变? Interface? Application logic? 2018/1/25
18
解决方案 将大型系统的逻辑结构分成具有各个包含内部相关责任的层. 层内耦合 2018/1/25
19
2018/1/25
20
2018/1/25 Log4J Technical Services Domain Presentation Pricing
PricingStrategy Factory Text ProcessSale Console used in quick experiments Persistence DBFacade «interface» ISalePricingStrategy Taxes ITaxCalculatorAdapter Services Sales Register Sale Swing Frame Payments CreditPayment ICreditAuthorization ServiceAdapter ServiceAccess Inventory IInventoryAdapter Jess A general purpose third- party rules engine. POSRuleEngine POSRuleEngineFacade SOAP not the Java Swing libraries, but our GUI classes based on Swing 2018/1/25
21
层内耦合和包间耦合 2018/1/25 Log4J Technical Services Domain Presentation
Pricing Persistence DBFacade Taxes «interface» ITaxCalculatorAdapter Services Factory Sales Register Sale Swing ProcessSale Frame Payments CreditPayment ICreditAuthorization ServiceAdapter ServiceAccess Inventory IInventoryAdapter Jess POSRuleEngine POSRuleEngineFacade SOAP 2018/1/25
22
Log4J Technical Services Domain Presentation Jess Persistence POSRuleEngine Inventory Payments ServiceAccess Pricing Sales Text Swing SOAP Hide the specific types and focus on illustrating the package-package coupling 2018/1/25
23
层内和包间交互场景 2018/1/25 : Domain:: Sales:: Register :Cashier
: Presentation:: Swing:: Process SaleFrame enterItem (id, qty) «singleton» : Tech- Services:: Persistence:: Persistence- Facade spec := getProduct Spec(id) x := isInvalid (lineItem, sale) spec := getObject(...,id) POSRule- Engine:: Engine s : Domain:: Sale Products:: Product Catalog makeLineItem(spec, qty) «subsystem» Services ::Jess someJessCalls(lineItem, sale) Points of crossing interesting boundaries or layers. These are especially noteworthy for people who need to understand the system, and thus are highlighted in this diagram. This diagram supports communicating the l ogical view of the architecture (a UP term) because it emphasizes architecturally significant information. UML notation : Note that a subsytem can be modeled as an object in the UML. This is useful in this case where I don't know or want to describe the details of how the Jess rule engine works, but just want to show collaboration with it. : UML path name to indicate packaging onPropertyEvent(s, "sale.total", total) PropertyListener 2018/1/25
24
简单包和子系统 某些包就是子系统 某些包只是对象集合 Persistence, POSRuleEngine,…
Pricing Package 2018/1/25
25
外观 访问代表子系统的包的方法最常用的模式就是外观模式 外观一般不能暴露太多的低层操作 外观经常是下层子系统对象的协调器 2018/1/25
«subsystem» Persistence DBFacade Jess POSRuleEngine POSRuleEngineFacade Pricing not a subsystem 2018/1/25
26
会话外观和应用层 2018/1/25
27
2018/1/25 Application Domain Presentation Sales Register Sale Swing
ProcessSale Frame Application session facade objects that maintain session state and control workflow related to some work--often by use case. SessionFacade ProcessRental HandleReturns ... Rentals Rental 2018/1/25
28
系统操作和层 2018/1/25 Presentation Swing :System ProcessSale ... Frame
Domain Presentation Swing ProcessSale Frame ... Register makeNewSale() enterItem() : Cashier endSale() enterItem(id, quantity) :System description, total * [more items] the system operations handled by the system in an SSD represent the operation calls on the Application or Domain layer from the Presentation layer 2018/1/25
29
外部资源或者外部数据库层的表示 2018/1/25 Domain(s) Technical Services Foundation
Inventory Persistence Naming and Directory Services Web AppFramework Technical Services POS Worse mixes logical and implementation views Better a logical view a logical representation of the need for data or services related to these subdomains, abstracting implementation decisions such as a database. Novell LDAP UML notation : A UML component, or physical part of the system. : A physical database in the UML. 2018/1/25
30
采用观察器进行向上协同 2018/1/25 PropertyListener : Presentation:: s : : Domain::
Swing:: Domain:: Sales:: Process Sales:: Register SaleFrame Sale :Cashier enterItem (id, qty) enterItem (id, qty) ... makeLineItem(spec, qty) ... onPropertyEvent(s, "sale.total", total) Collaboration from the lower layers to the Presentation layer is usually via the Observer (Publish-Subscribe) pattern. The Sale object has registered subscribers that are PropertyListeners. One happens to be a Swing GUI JFrame, but the Sale does not know this object as a GUI JFrame, but only as a PropertyListener. 2018/1/25
31
禁忌 某些情况下,增加层次将引入性能问题 并不是适用于所有问题 For example, Pipes and Filters
2018/1/25
32
好处 关注点分离Separation of concerns->降低耦合和依赖,提高内聚,增加重用性和清晰度
相关的复杂性被封装和分解Related complexity is encapsulated and decomposable 低层包含了可重用的功能Low layers contain reusable functions 某些层可以分布Some layers can be distributed 团队开发Team development 2018/1/25
33
经典的三层架构 Interface Application Logic Storage 2018/1/25
34
部署 2018/1/25 calculate taxes Application Logic Interface
classic 3-tier architecture deployed on 2 nodes: "thicker client" classic 3-tier architecture deployed on 3 nodes: "thiner client" UML notation: a node. This is a processing resource such as a computer. 2018/1/25
35
模型视图分离原则 模型: 领域层对象 视图: 表现对象, 例如windows, applets and reports
模型(领域)对象不能够直接知道视图(表现)对象 2018/1/25
36
模型视图分离和“向上”通信 从上面拉Pull-from-above 从下面推Push-from-below 2018/1/25
观察者模式Observer Pattern: making the GUI object appears as an object implements an interface such as PropertyListener UI外观对象Presentation façade object adds a level of indirection to Domain Presentation Register Sale ProcessSale Frame UIFacade UIFacades are occasionally used when a push-from-below communication model is required. Not a Swing or GUI class. Just a plain object which the GUI objects 2018/1/25
37
Chapter 33 使用模式解决某些实际问题: 7个新模式 Reliability and recovery
Local caching Handling failure Handling payments 7个新模式 2018/1/25
38
采用适配器和多态模式实现缓存 2018/1/25 ProductCatalog 1
productsService : IProductAdapter 1 <<interface>> getSpecification() IProductsAdapter 1 getSpecification( itemID ) : ProductSpecification Implements the adapter 1 interface, but is not really an adapter for a second LocalProducts DBProductsAdapter component. remoteProductsService: IProductAdapter getSpecification( itemID ) Rather, it itself implements the local service function. getSpecification( itemID ) BigWebServiceProductsAdapter getSpecification( itemID ) 2018/1/25
39
Singleton 和 Factory 提供了实现接口的类
2: create(pc) create() :Store :Register 返回本地服务 1: create() pc: 1.1: psa := getProductsAdapter() <<singleton>> ProductCatalog :ServicesFactory 1.1.2: create( externalService ) 1.1.1: create() externalService : psa : LocalProducts DBProductsAdapter IProductsAdapter IProductsAdapter 本地服务获取了对外部服务的适配器的引用 2018/1/25
40
从缓存或者数据库中获取产品信息 2018/1/25 IProductsAdapter IProductsAdapter
2 [not in file] : ps := getSpecification(id) ps := getSpecification(id) remoteService : : LocalProducts DBProductsAdapter 1: ps := get( id ) continued in another diagram 3 [not in file ]: put( id, ps ) : KeyIndexedFileOf SerializedObjects 2018/1/25
41
处理故障 本地缓存中未命中且访问外部产品服务失败时,如何处理? 解决方案: 抛出异常 用信号通知收银员人工输入价格和描述?
取消输入该商品项? 解决方案: 抛出异常 低层的异常转换成高层次中有意义的异常 依据问题而不是抛出者命名异常 2018/1/25
42
处理错误 (seq diagram) recall that indicating the instance of type "Object" is useful when one wants to indicate the interface, but not the class of an instance <<exception>> ProductInfoUnavailableException() stopping the message line at this point indicates the PersistenceFacade object is catching the exception IProductsAdapter java.sql.Statement : DBProducts : Persistence : Object Adapter Facade ps := getSpecification(id) ps := get(...) note the difference between resultSet := executeQuery(...) synchronous and asynchronous message arrowheads in the UML <<exception>> <<exception>> SQLException() DBUnavailableException() UML notation : * All asynchronous messages, including exceptions, are illustrated with a stick arrowhead. * Exceptions are shown as messages indicated by the exception class name. * a kind of signal in the UML), if increased visibility is desired. An optional <<exception>> or <<signal>> stereotype is legal (an exception is 2018/1/25
43
Exceptions in a UML class diagram
UML notation : The UML has a "default" syntax for operations. But it does not include an official solution to show exceptions thrown by an operation. There are at least three solutions: 1. The UML allows the operation syntax to be any other language, such as Java. In addition, some UML CASE tools allow display of operations explicitly in Java syntax.Thus, Object get(Key, Class) throws DBUnavailableException, FatalException 2. The default syntax allows the last element to be a "property string." This is a list of arbitrary property+value pairs, such as { author=Craig, kids=(Hannah, Haley), ...}. Thus, put(Object, id) { throws= (DBUnavailableException, FatalException) } 3. Some UML CASE tools allow one to specify (in a special dialog box) the exceptions that an operation throws. exceptions caught PersistenceFacade are modeled as a kind of operation usageStatistics : Map handling a signal Object get(Key, Class) throws DBUnavailableException, FatalException put(Key, Object) { throws= (DBUnavailableException, FatalException) } ... exceptions thrown 玸ignal?SQLException() can be listed in 玸ignal?IOException() another compartment exceptions labeled FatalException "exceptions" DBUnavailableException 2018/1/25
44
更多模式 转换异常Convert Exceptions
对问题而不是抛出者命名Name the problem, not the thrower 集中错误日志Centralized error logging 错误会话Error Dialog 代理Proxy 抽象工厂Abstract factory 自力更生Do It Myself 2018/1/25
45
转换异常 将较低层的异常转换为本层次系统中有意义的异常 通过转换,高层次的异常提供了对低层次异常的子系统层次的解释 2018/1/25
46
命名问题,而不是抛出者 异常必须依据其抛出的理由进行命名 抛出者并不能表示问题所在 2018/1/25
47
集中错误日志 使用单实例类访问的集中错误日志对象,所有的异常都向它汇报 提供了一致性 对输出流和格式的柔性定义 2018/1/25
48
错误会话 使用标准的单实例类访问的、应用程序无关的、非用户界面的对象向用户通知错误。 对输出机制的变化实现了防止变异 一致的错误汇报风格
集中控制公共的错误通知策略 性能也有所改进 2018/1/25
49
处理异常 2018/1/25 notify(message, exception) ps := getSpec(id) continued
<<singleton>> :ErrorDialog notify (message, exception) * : notify(message) : Object INotifier -GUI dialog box -text console "dialog" -speech "dialog" :Log log(exception) IProductsAdapter Convert Exception pattern Error Dialog : DBProducts Adapter : Local Products IProductsAdapter :ProductCatalog ps := getSpec(id) :Register enterItem(id, qty) :ProcessSale Frame <<exception>> ProductInfoUnavailableException() <<singleton>> :ErrorDialog Centralized Error Logging pattern 2018/1/25
50
代理 (GoF) 问题: 不希望或不可能直接访问真正的主题对象时,应该如何
问题: 不希望或不可能直接访问真正的主题对象时,应该如何 解决方案: 通过代理对象增加一层间接性,代理对象实现与主题对象相同的接口,并且负责控制和增强对主题对象的访问 2018/1/25
51
Proxy 结构 2018/1/25 Client <<interface>> 1
ISubjectInterface foo() RealSubject { ... pre-processing realSubject.foo() ... post-processing } Client subject : ISubjectInterface doBar() 1 Proxy realSubject : ISubjectInterface ... whatever subject.foo() subject actually references an instance of Proxy, not RealSubject "realSubject" will actually reference an instance of RealSubject 2018/1/25
52
抽象工厂 (GoF) 可能需要与多种不同的物理设备打交道,…
这些设备可能来自不同的厂商,如IBM, Epson, 它们的驱动十分类似 (Java Classes) 问题: 如何创建实现相同接口的相关类的族? 解决方案: 定义一个公共接口 (abstract factory), 具体的工厂继承它 2018/1/25
53
Abstract factory 2018/1/25 <<interface>>
this is the Abstract Factory--an interface for IJavaPOSDevicesFactory creating a family of getNewCashDrawer() : jpos.CashDrawer related objects getNewCoinDispenser() : jpos.CoinDispenser ... IBMJavaPOSDevicesFactory NCRJavaPOSDevicesFactory ... ... getNewCashDrawer() : jpos.CashDrawer getNewCashDrawer() : jpos.CashDrawer getNewCoinDispenser() : jpos.CoinDispenser getNewCoinDispenser() : jpos.CoinDispenser ... ... { { return new com.ibm.pos.jpos.CashDrawer() return new com.ncr.posdevices.CashDrawer() } } <<interface>> jpos.CashDrawer com.ibm.pos.jpos.CashDrawer com.ncr.posdevices.CashDrawer isDrawerOpened() isDrawerOpened() ... isDrawerOpened() ... ... 2018/1/25
54
Do it myself 我是对实际对象的抽象,由我来完成这些通常由实际对象完成的事情
与信息专家模式相比较 (Text Object does spell-checking), 多态 (Circle Object draws itself) 2018/1/25
55
Do it myself (polymorphism)
Payment amount authorize() CashPayment CreditPayment DebitPayment CheckPayment authorize() authorize() authorize() authorize() By Polymorphism, each payment type should authorize itself. This is also in the spirit of "Do it Myself" (Coad) 2018/1/25
56
持久性框架 采用模式来设计持久化框架 某些与数据处理相关的模式: 将对象表示为表 对象标识
Representing object relationships as Tables 对象标识 数据库映射器Database Mapper/Broker 缓存管理Cache management 新的GoF 模式: Template, State, Command, Virtual Proxy 2018/1/25
57
持久化框架 What is a persistence service? What is a framework?
Basic requirements of a persistence service: Store and retrieve objects Commit and rollback 2018/1/25
58
Key ideas Schema Mapping (between class and persistent store)
Object identity Materialization and dematerialization Caching Transaction state Lazy materialization 2018/1/25
59
Problem: How to map classes to data in a RDB
Solution (Representing objects as tables): define a table for each persistent class Each attribute becomes a column New problem: How to deal with complex attributes (see “Representing object relationships as Tables”) 2018/1/25
60
Objects as Tables pattern
2018/1/25
61
How to consistently define the mapping between objects and db records
Solution: Define an object identifier (OID) for each object, and put the OID in corresponding row of table 2018/1/25
62
Object Identifier pattern
2018/1/25
63
One for each persistent class
Problem: Who should be responsible for materialization and dematerialization Info expert suggests the object should do this itself (i.e. direct mapping). But hard to program and to maintain. Solution: make a separate “database mapper” class responsible for materialization, dematerialization, object caching One for each persistent class 2018/1/25
64
Database mapper/broker pattern
each mapper gets and puts objects in its own unique way, depending on the kind of data store and format 1 PersistenceFacade getInstance() : PersistenceFacade get( OID, Class ) : Object put( OID, Object ) ... ProductSpecification RDBMapper get( OID) : Object FlatFileMapper Manufacturer note that the Class as a parameter is no longer needed in this version of get , as the class is "hardwired" for a particular persistent type «interface» IMapper get(OID) : Object Class UML notation : This is a qualified association. It means: 1. There is a 1-M association from PersistenceFacade to IMapper objects. 2. With a key of type Class, an IMapper is found (e.g., via a HashMap lookup) 2018/1/25
65
Template pattern Problem: How to implement a variations of an algorithm that combine generic and specialized functionality? Solution: Provide a template method in base class that implements skeleton of algorithm, override varying parts in subclasses (using “hook” methods) 2018/1/25
66
Template pattern 2018/1/25
67
Using template method pattern for materialization
Abstract RDBMapper tableName : String + «constructor» AbstractRDBMapper( tableName ) # getObjectFromStorage(OID) : Object {leaf} # getObjectFromRecord(OID, DBRecord) : Object {abstract} - getDBRecord(OID) : DBRecord PersistenceMapper + get( OID) : Object {leaf} # getObjectFromStorage(OID) : Object {abstract} ... { protected final Object getObjectFromStorage( OID oid ) dbRec = getDBRecord( oid ); // hook method return getObjectFromRecord( oid, dbRec ); } IMapper ProductSpecification + «constructor» ProductSpecificationRDBMapper(tabName) # getObjectFromRecord(OID, DBRecord) : Object // hook method override protected Object getObjectFromRecord( OID oid, DBRecord dbRec ) ProductSpecification ps = new ProductSpecification(); ps.setOID( oid ); ps.setPrice( dbRec.getColumn("PRICE") ); ps.setItemID( dbRec.getColumn("ITEM_ID") ); ps.setDescrip( dbRec.getColumn("DESC") ); return ps; private DBRecord getDBRecord OID oid ) String key = oid.toString(); dbRec = SQL execution result of: "Select * from "+ tableName + " where key =" + key return dbRec; 2018/1/25
68
Cache management pattern
Problem: How to efficiently materialize frequently accessed objects? database mappers maintain their own cache One cache per mapper class 2018/1/25
69
Transactional statechart diagram for persistent objects
2018/1/25
70
State Pattern Problem: Behavior depends on state of an object. How to avoid conditional logic? Solution: Create state-classes for each state, with a common interface. Delegate state-dependent operations to the state class 2018/1/25
71
State Pattern 2018/1/25
72
Command Pattern Problem: How to handle a multiplicity of requests/tasks that occur in a runtime-dependent order? (such as the various operations that can occur in a transaction) Solution: Make each request a class that implements the same interface 2018/1/25
73
Command Pattern 2018/1/25
74
Virtual Proxy Pattern A proxy that is not materialized until it is needed (uses lazy materialization) 2018/1/25
75
Virtual Proxy Pattern 2018/1/25
76
Representing object relationships as tables
One-to-one relationships: Put an OID in one or both tables for the objects in the relationship Or: create an associative table that records oid’s of objects in relationship One-to-many: Create an associative table for OID’s of all objects in relationship Many-to-many: 2018/1/25
Similar presentations