Architecture Refactoring Improving the Design of Existing Application

























![NInject (Attributes) public class Trade. Service : ITrade. Services { [Inject] public Trade. Service(IOrder NInject (Attributes) public class Trade. Service : ITrade. Services { [Inject] public Trade. Service(IOrder](https://slidetodoc.com/presentation_image_h2/861331efe4ab7ca6f2bfb2824260dd3f/image-26.jpg)




























- Slides: 54
Architecture Refactoring: Improving the Design of Existing Application Architectures Mark Pollack Principal Software Engineer Spring. Source ARC 305
Session Objectives and Agenda Architectural Decay Refactoring Overview Architectural Refactoring
The Problem: Architectural Decay System works but… Difficult to meet new requirements Lacks in quality attributes Maintainability Extensibility Performance "Brownfield" development Presentation Layer Component 1 Component 2 Component 4 Component 3 Component 5 Component 6 Data Access Layer
How did This Happen? As software evolves, architecture decays The original design Gets lost in sea of changes Compromised by shortcuts Was never meant to address current requirements New development is done 'fearfully' Design flaws are not addressed directly New features are added by cut-n-paste of old ones Those with the original system knowledge have Management fearful of cost/time to make changes
What can be done about it? Apply refactoring principals to the architecture Code refactorings are more well known Classify recurrent problems and apply 'recipes' to implement best practices Refactoring is part of an iterative development processes Aims for incremental improvements in each cycle Include the architecture during each cycle This talk will introduce architectural refactorings Show by example how to apply
Code Refactoring "…the process of changing a software system in such a way that it does not alter the external behavior of the code yet improves its internal structure" - Martin Fowler
Refactoring as a process Provides a well defined, generally applicable transformational process Catalogs common problems Specifies 'recipes' so that best practices can be incrementally applied Born out of experience Process can be applied to other artifacts UML Diagrams, databases, test plans Collectively … the architecture
Refactoring Categories Code Level – M. Fowler Databases – S. Ambler Design Patterns - J. Kerievsky Architecture – M. Stal Apply changes to structure but not functionality Distinct process from Reengineering Typically encompass several other refactoring categories
How a Refactoring is 'Born' They are discovered, not invented Come from 'smells' Smells that violate common principals Separation of Concerns Don't Repeat Yourself You Ain't Gonna Need It
Architecture Smells Shortcuts across application layers Application feels like a 'big ball of mud' An existing layer should be split into two or more logical layers Dependency cycles Business logic is tightly coupled to non-functional requirements
Architecural Refactoring Catalog (I) Courtesy: Michael Stal Rename Entities Remove Duplicates Introduce Abstraction Hierarchies Remove Unnecessary Abstractions Substitute Mediation with Adaptation Break Dependency Cycles Inject Dependencies Insert Transparency Layer Reduce Dependencies with Facades Merge Subsystems Split Subsystems Enforce Strict Layering Move Entities Add Strategies Enforce Symmetry Extract Interface Enforce Contract Provide Extension Interfaces Substitute Inheritance with Delegation Provide Interoperability Layers
Architecural Refactoring Catalog (II) Courtesy: Michael Stal Introduce Aspects Integrate DSLs Add Uniform Support to Runtime Aspects Add Configuration Subsystem Introduce the Open/Close Principle Optimize with Caching Replace Singleton Separate Synchronous and Asynchronous Processing Replace Remote Methods with Messages Add Object Manager Change Unidirectional Association to Bidirectional
Architectural Refactorings in action Apply as part of a controlled iterative development process Goal is to improve or introduce a set of quality attributes Architect's role to Determine the order of refactorings Apply the refactorings Ensure quality
Example Application Microsoft's Stock. Trader example application A WPF ASP. NET Trade Service Façade (ASMX) Trade Service Façade (WCF) Enforce Strict Layering Inject Dependencies Introduce Aspects A A A Trade Service Data Access Layer
Prequisite: Create Integration Tests One must take steps to ensure quality How do we know the refactorings are correct? Does new architecture still meet the specification Need integration tests to run as a regression Automation is essential Several tools and techniques can help Acts as a safety net
Automated Testing Toolbox Code focused testing frameworks MSTest, NUnit, mb. Unit, etc… UI focused testing products Win. Runner, Load. Test, Ranorex, Selenium, … Continuous Integration VSTS, Cruise. Control, Hudson Code coverage VSTS, NCover Build tools MSBuild, NAnt.
demo Integration Tests Mark Pollack Principal Software Engineer Spring. Source
Refactoring : Enforce Strict Layering Context Problem Solution Not clear to place new Redesign Lack Impediment of strict -where new to layering more layers, fine leads moving grained to functionality tight of functionality, testing coupling break data format dependencies Application Component 3. 1 Broken Layering Component 3. 1 Component 2. 1 Component 1. 1 Component 3. 1 Component 2. 2 Component 1. 1 Layer 3 Layer 2 Layer 1
Layering Toolbox Visualization and enforcement tools VSTS 2010 Soto. Arc Dependency Structure Matrix (DSM) NDepend Lattix Testing Frameworks
Refactoring: Inject Dependencies Context Problem Solution Object needs to create and usecreating collaborating objects The object Hand Separate coded the should factories responsibility notare be dependent impractical of on knowledge of how to create collaborating objects its collaborators to a Dependency Injection (DI) container Component 1 private Component 2 c 2; public Init() { public Component 1 Component 2 C 2 { S 1 set {(Component 2 =. . new. } S 1(. . . ); c 2){ } S 2 s 2 = new S 2(. . . ); c 2 = new=C 2(s 1, s 2); this. c 2; } } S 1 DI Container Component 2 S 2
The Quick Guide to DI DI containers act as generalized object factories How to configure a DI container with object creation and configuration rules? Provide metadata XML Attributes Fluent API
Autofac Configuration (XML) <autofac default. Assembly="Trade. DALSQLServer"> <components> <component type="Trade. BSI. Trade. Service, " service="Trade. BSC. ITrade. Services, Trade. BSC"/> <component type="Trade. DALSQLServer. Order" service="Trade. IDAL. IOrder, Trade. IDAL" /> <component type="Trade. DALSQLServer. Customer" service="Trade. IDAL. ICustomer, Trade. IDAL"/> <component type="Trade. DALSQLServer. Market. Summary" service="Trade. IDAL. IMarket. Summary, Trade. IDAL"/> </components> </autofac>
Autofac Configuration (Fluent API) var builder = new Container. Builder(); builder. Register<Trade. Service>(). As<ITrade. Services>(). Container. Scoped(); builder. Register<Order>(). As<IOrder>(). Container. Scoped(); builder. Register<Customer>(). As<ICustomer>(). Container. Scoped(); builder. Register<IMarket. Summary>(). As<Market. Summary>(). Container. Scoped();
NInject (Attributes) public class Trade. Service : ITrade. Services { [Inject] public Trade. Service(IOrder dal. Order, ICustomer dal. Customer, IMarket. Summary dal. Market. Summary) { this. dal. Order = dal. Order; this. dal. Customer = dal. Customer; this. dal. Market. Summary = dal. Market. Summary; } } IKernel kernel = new Standard. Kernel( new Inline. Module( x => x. Bind<ITrade. Services>(). To<Trade. Service>(), x => x. Bind<IOrder>(). To<Order>(), x => x. Bind<ICustomer>(). To<Customer>(), x => x. Bind<IMarket. Summary>(). To<Market. Summary>() ));
Unity Configuration (XML) <type="Trade. BSC. ITrade. Services, Trade. BSC" map. To="Trade. BSI. Trade. Service, Trade. BSI "> <lifetime type="singleton" /> <type. Config extension. Type="Type. Injection. Element, Unity. Configuration"> <constructor> <param name="order. Dal" parameter. Type="Trade. IDAL. IOrder, Trade. IDAL"/> </constructor> </type. Config> </type> <type="Trade. IDAL. IOrder" map. To="Trade. DALSQLServer. Order, Trade. DALSQLServer "> <lifetime type="singleton" /> </type>
Spring Configuration <object id="trade. Service" type="Trade. BSI. Trade. Service, Trade. BSI"> <constructor-arg ref="order. Dal"/> <constructor-arg ref="customer. Dal"/> <constructor-arg ref="market. Summary. Dal"/> </object> <object id="order. Dal" type="Trade. DALSQLServer. Order, Trade. DALSQLServer"> <property name="Conn. String" value="${order. Dal. Conn. Str}"/> </object> <object id="customer. Dal" type="Trade. DALSQLServer. Customer"> <property name="Conn. String" value="${customer. Dal. Conn. Str}"/> </object> <object id="market. Summary. Dal" type="Trade. DALSQLServer. Market. Summary"> <property name="Conn. String" value="${market. Dal. Conn. Str}"/> </object>
DI and the Runtime Environment DI containers provide integration support to many common runtime environments WCF Custom Service. Host ASP. NET Custom Http. Module/Page. Handler. Factory ASP. NET MVC Test frameworks Custom base class or attribute extensions
Example: DI for ASP. NET Register custom Http. Module and Http. Handler <object type="Stock. Trade. aspx"> <property name="Trade. Service" ref="trade. Service"/> </object>
Example: DI for ASP. NET MVC Register custom Controller Factory <object name="controller. Stock. Trade" type="Stock. Trader. Stock. Controller, Stock. Trader" singleton="false"> <property name="Trade. Service" ref="trade. Service"/> </object>
Example: DI for WCF Register custom Service Host <object name="wcf. Trade. Service" type="Trade. Stock. Trader. Web. Application. Business. Service. Client singleton="false"> <property name="Trade. Service" ref="trade. Service"/> </object>
demo Inject Dependencies Mark Pollack Principal Software Engineer Spring. Source
Benefits Application is more easily testable Components not responsible for self configuration No custom factories to maintain Application becomes collection of loosely coupled components Divide and conquer implementation approach Test layers individually, then assemble Can incrementally adopt dependency injection Improved design automatically 'creeps' in
Refactoring: Introduce Aspects Context Decouple components from the surrounding technical infrastructure Problem Business logic is tied to a technology decreasing its portability and 'life expectancy' Excessive cut-n-paste reuse Solution Implement concerns separately Bring concerns together using Aspect Oriented Programming (AOP)
Non Functional Requirements Often expressed in terms such as the service layer should be transactional A business service that fails with a particular exception failure can be retried Secure every business method invocation The 1: 1 principal "There should be a clear, simple, 1: 1 correspondence between design-level requirements and the implementation"
The AOP Value Proposition Achieve separation of concerns Cross cutting concerns in one component Business functionality in another component But still recombine business and technical requirements into a complete application
System Evolution Without AOP Security Transactions Logging Code scattering Code tangling Bank. Service Customer. Service Reporting. Service
System Evolution With AOP Bank. Service Security Aspect Customer. Service Transaction Aspect Reporting. Service Logging Aspect
AOP Terminology All the possible places one could 'insert' functionality Join point What is the functionality? Advice Where to insert? Pointcut What + Where = Aspect
AOP Implementation Approaches Dynamic Proxy Behavior added at run time 'Auto generation' of wrapper classes IL Weaving Behavior added at compile time Assembly rewriting AOP + DI in combination is natural and powerful
Example: Transation Management How to best satisfy the requirement that the service layer should be transactional Adding transactional boilerplate code in the service layer is prone to errors Solution: Declarative Transaction Management Use meta data to specify transactional boundary Select among several transaction APIs
Transaction Management Proxy Buy ITrade. Services AOP Proxy Transaction. Advice begin commit ADO. NET NHibernate System. Transactions Transaction Manager Trade. Service (target)
demo Introduce Aspects Mark Pollack Principal Software Engineer Spring. Source
Introduce Aspects: Benefits Clean simple business code Implementation looks more like requirements System now has 'conventions' in it "this namespace is transactional" Ensures we meet requirement No errors of omission Provides a contract with developers they know what to expect. Just the beginning… Add caching to DAO layer, monitoring etc.
Conclusion Refactoring is not constrained to code but is applicable to architecture You can change for the better incrementally Regression tests are essential Strict layering is the first things to tackle Use DI and AOP to aid in many architectural refactorings
Resources Refactoring: Improving the Design of Existing Code, Addison-Wesley, 1999 Refactoring Databases: Evolutionary Database Design, Addison-Wesley, 2006 Kerievsky, Joshua: Refactoring to Patterns, Addison-Wesley, 2004 http: //stal. blogspot. com OOPSLA Conference Tutorials/Podcasts
Resources Brownfield Application Development in. NET, Manning 2009
Related Content ARC 201 - A Lap aroudn Team System 2010 Architecture Edition ARC 303 – Architectural Strategies for Increased Discovery, Integration, and Modularity
Track Resources Michael Stahl's Blog - http: //stal. blogspot. com Wikipedia entries for Depenency Injection and Aspect Oriented Programming Spring for. NET Framework - http: //www. springframework. net
Resources www. microsoft. com/teched www. microsoft. com/learning Sessions On-Demand & Community Microsoft Certification & Training Resources http: //microsoft. com/technet http: //microsoft. com/msdn Resources for IT Professionals Resources for Developers www. microsoft. com/learning Microsoft Certification and Training Resources
question & answer
Complete an evaluation on Comm. Net and enter to win!
© 2009 Microsoft Corporation. All rights reserved. Microsoft, Windows Vista and other product names are or may be registered trademarks and/or trademarks in the U. S. and/or other countries. The information herein is for informational purposes only and represents the current view of Microsoft Corporation as of the date of this presentation. Because Microsoft must respond to changing market conditions, it should not be interpreted to be a commitment on the part of Microsoft, and Microsoft cannot guarantee the accuracy of any information provided after the date of this presentation. MICROSOFT MAKES NO WARRANTIES, EXPRESS, IMPLIED OR STATUTORY, AS TO THE INFORMATION IN THIS PRESENTATION.