KEMBAR78
Accu2010 archrefactoring | PDF
Dr. Michael Stal: Architecture Refactoring




                                    Architecture Refactoring –
                                    Motivation, Approach and Patterns


                                    accu 2010
                                    Dr. Michael Stal




                                    Panta rhei




                                                       There is nothing permanent except
                                                       change

                                                       [Heraclitus, 535–475 BC]




                           Page 2




© Dr. Michael Stal, 2010


                                                                                           1
Dr. Michael Stal: Architecture Refactoring




                                    Refactoring


                                    Learning objectives

                                     Understand about design erosion and how to avoid it

                                     Learn about the principles of refactoring

                                     Know about activities and best practices necessary for refactoring

                                     Understand how reengineering and rewriting differ from refactoring




                           Page 3




                                    Refactoring

                                    Agenda

                                                       Motivation and foundation


                                                       Refactoring


                                                       Reengineering


                                                       Rewriting


                                                       Comparison


                                                       Summary




                           Page 4




© Dr. Michael Stal, 2010


                                                                                                           2
Dr. Michael Stal: Architecture Refactoring




                                    Design erosion is the root of all evil


                                     In the lifecycle of a software system                     Detached Extensions
                                      changes                                               A                A Backpack
                                                                                         Backpack             Backpack
                                      are the rule and not the exception
                                                                     p
                                                                                                      Another
                                       New requirements or increments imply                         Backpack
                                        modifications or extensions
                                       Engineers must adopt their solutions to             A                 Someone
                                                                                         Component           Else's Comp
                                        new technologies
                                       Changes in business force changes in IT
                                                                                          Another               The Fifth
                                       Bug fixes require patches or local               Component              Element
                                        corrections
                                     Unsystematic approaches ( workarounds )
                                                               ("workarounds")
                                                                                         Yet Another         Component
                                      cure the symptom but not the problem               Component              42
                                     After applying several workarounds,
                                      software systems often suffer from design
                                                                                                        DB             Spaghetti
                                      erosion                                                       Access Layer       design
                                     Such systems are doomed to fail as work-          DB access
                                      arounds have a negative impact on opera-          shortcut

                                      tional and developmental properties
                           Page 5




                                    Refactoring is part of the architecture design
                                    process




                                                   Feedback Loop


                                            Refine & Assess         Refactor         Refactoring is integrated into
                                              Architecture         Architecture      the iterative-incremental
                                                                                     architecture design process:
                                                                                        It improves the structure
                                                                                        It supports a risk-,
                                                                                                  t     i k
                                              Executable      no    Complete   yes       requirements- and test-
                                               Increment               ?                 driven approach




                           Page 6




© Dr. Michael Stal, 2010


                                                                                                                                   3
Dr. Michael Stal: Architecture Refactoring




                                    Yes, but was is it?


                                     "Code refactoring is the process
                                      of changing a software system
                                               g g               y          Note: external interfaces
                                                                            remain unchanged!
                                                                                 i     h      d!
                                      in such a way that it does not
                                      alter the external behavior of
                                      the code yet improves its
                                      internal structure" [Martin Fowler]


                                     Put more generally: Refactoring
                                      is the process of changing a
                                      software system or process in
                                      such a way that it does not alter
                                      the external behavior, yet
                                      improves its internal structure




                           Page 7




                                    Why should we refactor?

                                     Architecture refactoring needs to
                                      achieve quality improvement in
                                      terms of
                                         structural as well as
                                         non-functional qualities
                                     Structural quality indicators
                                      include:
                                       Economy
                                       Visibility
                                       Spacing
                                       Symmetry
                                       Emergence
                                     Consequently, the goal of
                                      architecture refactoring is to
                                      achieve or improve such qualities
                           Page 8




© Dr. Michael Stal, 2010


                                                                                                        4
Dr. Michael Stal: Architecture Refactoring




                                    Refactoring

                                    Agenda

                                                        Motivation and foundation


                                                        Refactoring


                                                        Reengineering


                                                        Rewriting


                                                        Comparison


                                                        Summary




                           Page 9




                                    Code refactoring


                                     According to Martin Fowler, code         Reasons to use refactoring
                                      refactoring is                             Design improvement and
                                       … the process of changing a               maintenance
                                        software system in such a way            Better readability
                                        that it does not alter the external      Bugs
                                        behavior of the code yet
                                                                                 It is the third step in TDD
                                        improves its internal structure
                                       … a disciplined way to clean up
                                        code that minimizes the                The Rules of Three
                                        chances of introducing bugs              Refactor before adding new
                                                                                  functionality, e.g., when
                                                                                  structure prevents simple
                                                                                   t   t            t i     l
                                                                                  additions
                                                                                 Refactor when fixing bugs
                                                                                 Refactor after code reviews
                                                                                  to
                                                                                  apply improvements


                           Page 10




© Dr. Michael Stal, 2010


                                                                                                                5
Dr. Michael Stal: Architecture Refactoring




                                 Code smells


                                  Kent Beck's grandmother's
                                   saying:
                                      y g
                                   "If it stinks, change it"
                                  Thus, identify bad smells such as
                                      Code that is duplicated
                                      Methods that span several
                                       dozen lines
                                      Subclasses introducing the
                                       same method
                                      Usage of temporary variables
                                      Usage of switch statements
                                      Introduction of a "middleman"

                           Page 11




                                 Code Refactoring Example: Extract Method


                                  Make code fragment a method of its own

                                                void printFormatted(string text) {
                                                    System.out.println("Copyright (c) 2008, Siemens AG");
                                                    System.out.println("Author: Michael Stal");
                                                    printRest(text);
                                                }




                                                void printFormatted(string text) {
                                                    printHeader();
                                                      i tH d ()
                                                    printRest(text);
                                                }

                                                printHeader() {
                                                    System.out.println("Copyright (c) 2008, Siemens AG");
                                                    System.out.println("Author: Michael Stal");
                                                }


                           Page 12




© Dr. Michael Stal, 2010


                                                                                                            6
Dr. Michael Stal: Architecture Refactoring




                                 Refactoring to patterns


                                  Refactoring to patterns was
                                   introduced by Joshua Kerievsky
                                                y               y
                                  General idea: Patterns might give
                                   guidance how to refactor on the
                                   architectural level
                                      Replace your proprietary
                                       solution with a pattern that
                                       solves the same problem                  Kerievsky's book focuses
                                                                                 on design patterns
                                      Introduce symmetry by making
                                                                                However, we could also
                                       sure the same problem is
                                                                                 apply the same principle
                                       always solved using the same              to architecture patterns
                                       pattern / solution
                                                                                In the latter case, we'll obtain
                                  This represents a precursor of                architecture refactorings
                                   software architecture refactoring
                           Page 13




                                 Replace hard-coded notifications with Observer
                                 [Joshua Kerievsky]


                                                     Do it yourself                       Observer Pattern

                                      Subject                    EventSink     Subject                     *   Observer
                                                             *
                                                                 update        state                           update
                                      state
                                      observerList               doSomething   observerList

                                                                               attach              Dynamic
                                      notify                                   detach              Wiring  ConcreteObserver
                                      setData                                  notify
                                      getData                                  setData                         update
                                                                               getData                         doSomething




                                                                                              state = X;
                                     Subject                                                  notify();
                                     contains
                                     hardwired list                                                              s->getData()
                                     of interested                                for all observers
                                                                                  in observerList do
                                     components                                      update();




                           Page 14




© Dr. Michael Stal, 2010


                                                                                                                                7
Dr. Michael Stal: Architecture Refactoring




                                 Architecture refactoring


                                  Architecture refactoring is about              Architecture smells
                                   the semantic-preserving                           Duplicate design artifacts
                                   transformation of a software
                                   t     f      ti   f     ft
                                                                                     Unclear roles of entities
                                   design
                                                                                     Inexpressive or complex
                                  It changes structure but not                       architecture
                                   behavior                                          Everything centralized
                                  It applies to architecture-relevant               Home-grown solutions instead of
                                   design artifacts such as UML                       best practices
                                   diagrams, models, DSL                             Over-generic design
                                   expressions, aspects
                                                                                     Asymmetric structure or behavior
                                  Its goal is to improve quality. You               Dependency cycles
                                   got a "smell"? Use an architecture
                                                                                     Design violations (such as relaxed
                                   refactoring                                        instead of strict layering)
                                   pattern to solve it!
                                                                                     Inadequate partitioning of
                                                                                      functionality
                                                                                     Unnecessary dependencies
                                                                                     Missing orthogonality


                           Page 15




                                 Remove unnecessary abstractions (1)



                                                             Transport *                          Abstract                 Abstract
                                     A true story: In           Way
                                                                  y                               Storage
                                                                                                       g                   Strategy
                                                                                                                                 gy
                                                                                                             *
                                     this example
                                                                  *
                                     architects                Equip-                                            Composite Concrete
                                                                            Dump       Door          Bin
                                     introduced                 ment                                              Storage  Strategy
                                                         *
                                     Transport Way as
                                     an additional
                                     abstraction. But           Cart       Belt
                                     can't we consider
                                     transport ways as
                                     just as another
                                     kind of storage?
                                     As a consequence
                                                                                                  Abstract                 Abstract
                                     the unnecessary                                              Storage                  Strategy
                                     abstraction was                                          *              *
                                     removed, leading
                                                                                                                 Composite Concrete
                                     to a simpler and        Equipment     Dump       Door          Bin
                                                                                                                  Storage  Strategy
                                     cleaner design.

                           Page 16




© Dr. Michael Stal, 2010


                                                                                                                                      8
Dr. Michael Stal: Architecture Refactoring




                                 Remove unnecessary abstractions (2)


                                  Context
                                    Eliminating unnecessary design abstractions
                                                  g           y      g
                                  Problem
                                    Minimalism is an important goal of software architecture, because
                                     minimalism increases simplicity and expressiveness
                                    If the software architecture comprises abstractions that could also be
                                     considered abstractions derived from other abstractions, then it is
                                     better to remove these abstractions
                                  General solution idea
                                    Determine whether abstractions / design artifacts exist that could also
                                     be derived from other abstractions
                                    If this is the case, remove superfluous abstractions and derive
                                     dependent from other existing abstractions
                                  Caveat
                                    Don't generalize too much (such as introducing one single hierarchy
                                     level: "All classes are directly derived from Object")

                           Page 17




                                 Break dependency cycles (1)



                                                               GetState()                      GetState()
                                     In this example,          SetState {                      SetState {

                                     the monitor               ...                             ...
                                                                   M.GetDate()                     D.GetDate()
                                     invokes the state
                                                               }                               }
                                     getter / setter
                                     methods but also
                                                                     Sensor                          Sensor             GetDate()
                                     provides GetDate()
                                     to the sensor, lea-
                                     ding to a simple                            X Break
                                                                                   Cycle                         Date
                                     dependency cycle.
                                     Providing this me-
                                     thod to monitors
                                                                   Monitor                           Monitor
                                     was a bad design
                                     decision, anyway.
                                                                                           Draw() {
                                     Introducing a         GetDate()
                                                           Draw() {                        ...
                                     separate date                                         S.GetState();
                                                           ...
                                     object solves the     S.GetState();                   }

                                     problem.              }




                           Page 18




© Dr. Michael Stal, 2010


                                                                                                                                    9
Dr. Michael Stal: Architecture Refactoring




                                 Break dependency cycles (2)


                                  Context
                                      Dependencies between subsystems
                                  Problem
                                      Your system reveals at least one dependency cycle between
                                       subsystems
                                      Subsystem A may either depend directly or indirectly on subsystem B
                                       (e.g., A depends on C which depends on B) which is why we always
                                       need
                                       to consider the transitive hull
                                      Dependency cycles make systems less maintainable, changeable,
                                       reusable, testable, understandable
                                      Thus, dependency hierarchies should form DAGs (directed acyclic
                                       graphs)
                                  General solution idea
                                      Get rid of the dependency cycle by removing one of the dependencies
                           Page 19




                                 Merge Subsystems (1)

                                 Example: While tight coupling between subsystems is bad, high cohesion within
                                 subsystems is good. Thus, merge tightly coupled subsystems to form a highly
                                 cohesive subsystem .



                                                    Sensor



                                                                                      Sensor + Utilities




                                                    Utilities




                                 Special variant: Merge a layer in a layered system

                           Page 20




© Dr. Michael Stal, 2010


                                                                                                                 10
Dr. Michael Stal: Architecture Refactoring




                                 Merge Subsystems (2)


                                  Context
                                    Coupling between subsystems
                                  Problem
                                    Between two subsystems in a software architecture the degree of
                                     coupling should be rather loose
                                    Within a subsystem the number of interdependencies (cohesion)
                                     should be high
                                    If the coupling is too tight, then the many interdependencies between
                                     these two subsystems decrease qualities such as
                                    Changeability
                                    Performance (maybe)
                                    Reusability of one of the subsystems
                                  General solution idea
                                    Tight coupling between subsystems implies that the two subsystems
                                     in fact implement one subsystem
                                    Either merge both subsystems to form one, or
                                    Move functionality from one subsystem to the other


                           Page 21




                                 Split Subsystems (1)

                                 Example: When analyzing interdependencies between entities in a subsystem, two
                                 (or more) sets can be determined. Within these sets there is high cohesion; between
                                 these sets there is only low cohesion. Thus, split the subsystem into two (or more)
                                 parts.


                                                                                               Component
                                                                                                Container
                                                       High Cohesion

                                           Lifecycle
                                                        Persistence    Event Handling
                                          Management


                                                Component Container

                                                       Communication


                                                                                               Communi-
                                                                                                cation



                                 Special variant: Split layer in a layered system


                           Page 22




© Dr. Michael Stal, 2010


                                                                                                                       11
Dr. Michael Stal: Architecture Refactoring




                                 Split Subsystems (2)


                                  Context
                                    Cohesion within a subsystem
                                  Problem
                                    Within a subsystem the interdependencies (cohesion) should be high
                                    Between two subsystems in a software architecture, the degree of
                                     coupling should be rather loose
                                    If the cohesion between some parts is loose, then some design
                                     decisions seem to be questionable
                                    It is recommendable to change this to obtain better modularization and
                                     understandability
                                    Another potential problem are subsystems/components with too many
                                     responsibilities
                                  General solution idea
                                    Loose cohesion within a subsystem implies that the functionality can
                                     be split into multiple subsystems
                                    Thus, determine areas with high cohesion in a subsystem. All those
                                     areas with low cohesion are candidates for becoming subsystems of
                                     their own

                           Page 23




                                 Move Entities (1)

                                 Example



                                                 y      z                                     y      z
                                           x                                          x
                                               Game                                         Game

                                        getPlayerHistory(p)




                                                                                      getPlayerHistory()

                                               Player                                      Player




                           Page 24




© Dr. Michael Stal, 2010


                                                                                                              12
Dr. Michael Stal: Architecture Refactoring




                                 Move Entities (2)


                                  Context
                                      Moving entities between subsystems
                                  Problem
                                      This can be considered a generalization of the Split Subsystem
                                       refactoring
                                      In a subsystem an entity is defined that fits better semantically in
                                       another subsystem to which it has high coupling
                                  General solution idea
                                      Again, we should consider cohesion and coupling
                                      If entity e reveals low or zero cohesion to the rest of its subsystem A,
                                       but tight coupling to subsystem B, then move e from A to B
                                      Note: This may also help with breaking dependency cycles between
                                       subsystems
                           Page 25




                                 Move Entities (3)


                                 Some additional issues
                                  In many cases we can t apply the refactoring to single atomic entities
                                           cases,    can't
                                   such as a class, method, constant, interface
                                  It is more likely that there will be clusters of atomic entities that together
                                   build a complex entity
                                  In the example, it is very likely that there will be classes and interfaces
                                   related to the method to be moved
                                  Thus, always consider semantically related entities with high internal
                                             y                       y                        g
                                   cohesion but less cohesion to the rest of their subsystem. If some of
                                   them show tight coupling to another subsystem, move the whole group
                                  Moving may not always be a simple operation, but imply several smaller
                                   grained transformations (see example)


                           Page 26




© Dr. Michael Stal, 2010


                                                                                                                    13
Dr. Michael Stal: Architecture Refactoring




                                 Reduce Dependencies with Facades (1)

                                 Example

                                                                                1.3     Rental Car
                                                                                         Bookingg

                                                                                  1.2                 Hotel
                                           Client
                                                                                                     Booking

                                                                                          Flight
                                                                                1.1      Booking



                                                                                2.3     Rental Car
                                                                                         Booking
                                                                                         B ki

                                                              Facade
                                                     1                            2.2                 Hotel
                                           Client              Travel
                                                                                                     Booking
                                                              Booking

                                                                                         Flight
                                                                                2.1     Booking


                           Page 27




                                 Reduce Dependencies with Facades (2)


                                  Context
                                    Client implements workflows that mostly access other components
                                  Problem
                                    If a client needs to access different external components for each workflow, it
                                     becomes dependent on details such as the set of available components
                                    As soon as the configuration and / or interfaces of these components change,
                                     there will be a direct impact on the client
                                  General solution idea
                                    Introduce a Facade component that acts as the client's gateway into the set of
                                     required components
                                    Implement workflow methods within the facade that represent the different
                                        p                                                   p
                                     workflows
                                    The facade methods take over the responsibility for accessing the set of
                                     required components on behalf of the client, thus decoupling the client from the
                                     components
                                    If components are remote, performance is also improved (Session Facade)



                           Page 28




© Dr. Michael Stal, 2010


                                                                                                                        14
Dr. Michael Stal: Architecture Refactoring




                                 Substitute Mediation with Adaptation (1)

                                 Example

                                                     I_have
                                                 no_clue_sub_1
                                                 no clue sub 1


                                        I_have                        I_have         A              B               C
                                     no_clue_sub2                  no_clue_sub_3


                                                                                   Adapter       Adapter         Adapter
                                                 Do_Everything_
                                                      Class                                  Integration Layer
                                                 a.k.a. Mediator
                                                                                   Adapter       Adapter         Adapter


                                        I_have                     I_have
                                     no_clue_sub_4             no_clue_sub_5         D              E               F


                                                    I_have
                                                 no_clue_sub_6




                           Page 29




                                 Substitute Mediation with Adaptation (2)


                                  Context
                                    Centralized system using a mediation level between peers
                                  Problem
                                    When interaction between different peers is complex, a mediator
                                     may be the right solution
                                    However, extensive use of mediator may reduce scalability
                                    If mediation was just applied to build an extremely generic solution,
                                     design erosion is often the price
                                    How can we improve this situation?
                                  General solution idea
                                    Introduce adapters to uniformly plug in peers
                                    But make interaction explicit, i.e. subsystems themselves are in
                                     charge to interact with the appropriate peers using an integration
                                     layer
                                    Known use: Enterprise Application Integration (Hub and Spoke) =>
                                     Enterprise Service Bus


                           Page 30




© Dr. Michael Stal, 2010


                                                                                                                           15
Dr. Michael Stal: Architecture Refactoring




                                 Add Uniform Support for Runtime Aspects (1)



                                                 Subsys UI                               Subsys UI
                                      IUIAdmin                                  IAdmin




                                                 Subsys DB                               Subsys DB
                                      IDBAdmin                                  IAdmin




                                                 Subsys ATM                              Subsys ATM
                                     IATMAdmin                                  IAdmin



                                                                   Management
                                                                    Console




                           Page 31




                                 Add Uniform Support for Runtime Aspects (2)


                                  Context
                                    Software architecture that must support runtime aspects such as
                                     lifecycle management, management, configuration
                                       f                                       f
                                  Problem
                                    Each non-trivial software architecture consists of multiple
                                     components, each of which supports common aspects
                                    If every component implements its own interfaces for runtime aspects,
                                     the overall system will lack simplicity and expressiveness
                                    Is there a way to provide a uniform approach to support those kinds of
                                     runtime aspects?
                                  General solution idea
                                    For each aspect, define a common interface (e.g., an interface for
                                     runtime configuration)
                                    In each component supporting the aspect, provide this common
                                     interface (maybe using Extension Interfaces to prevent bloating)
                                    To achieve orthogonality, provide one runtime component that is in
                                     charge of accessing these common interfaces (e.g., a management
                                     console)

                           Page 32




© Dr. Michael Stal, 2010


                                                                                                              16
Dr. Michael Stal: Architecture Refactoring




                                 Add Configuration Subsystem (1)

                                 Example



                                                                                         Actor
                                                         Subsystem UI                                       Subsystem UI
                                              IConfig1                                            IConfig
                                                                         Configuration




                                                         Subsystem DB             Configuration             Subsystem DB
                                     Actor
                                             IConfig2                              Subsystem      IConfig




                                                         Subsystem ATM                                      Subsystem ATM
                                              IConfig3                                            IConfig




                                      Use patterns such as Component Configurator for this purpose

                           Page 33




                                 Add Configuration Subsystem (2)


                                  Context
                                    A system with many configurable variabilities
                                  Problem
                                    If a system contains a lot of configuration options, then configuration
                                     itself is often tedious and error-prone
                                    This holds in particular when the configuration options are (partially)
                                     related to each other
                                    How can we refactor the software system so that configuration is
                                     simplified and (partially) automated?
                                  General solution idea
                                    Instead of providing dozens of configuration options to external actors,
                                     we introduce a configuration subsystem that takes a declarative
                                     configuration (from a file or a wizard)
                                    The configuration subsystem reacts to configuration change events,
                                     reads the passed configuration, and then accesses the configuration
                                     interfaces of configurable subsystems
                                    Ideally, all subsystems provide the same generic configuration
                                     interface

                           Page 34




© Dr. Michael Stal, 2010


                                                                                                                            17
Dr. Michael Stal: Architecture Refactoring




                                 Where to obtain architecture refactorings?

                                                               A whole catalog of
                                                            architecture refactorings
                                                            is provided as a starting
                                                                      point
                                                                         i t
                            1.       Rename Entities                                17. Enforce Contract
                                                                                    18. Provide Extension Interfaces
                            2.       Remove Duplicates
                                                                                    19. Substitute Inheritance with Delegation
                            3.       Introduce Abstraction Hierarchies              20. Provide Interoperability Layers
                            4.       Remove Unncessary Abstractions                 21. Aspectify
                            5.       Substitute Mediation with Adaptation           22. Integrate DSLs
                            6.       Break Dependency Cycles                        23. Add Uniform Support to Runtime Aspects
                                                                                    24. Add Configuration Subsystem
                            7.       Inject Dependencies
                                                                                    25. Introduce the Open/Close Principle
                            8.       Insert Transparency Layer                      26. Optimize with Caching
                            9.       Reduce Dependencies with Facades
                                                 p                                  27. Replace Singleton
                            10.      Merge Subsystems                               28. Separate Synchronous and Asynchronous
                                                                                        Processing
                            11.      Split Subsystems
                                                                                    29. Replace Remote Methods with Messages
                            12.      Enforce Strict Layering                        30. Add Object Manager
                            13.      Move Entities                                  31. Change Unidirectional Association to Bidirectional
                            14.      Add Strategies
                            15.      Enforce Symmetry
                            16.      Extract Interface



                           Page 35




                                 Checking correctness


                                  To check the correctness of refactorings, we
                                   use the test-driven approach that we
                                   introduced.
                                  Available options:
                                      Formal approach: Prove semantics and
                                       correctness of program transformation
                                      Implementation approach: Leverage unit
                                       and regression tests to verify that the
                                       resulting implementation still meets the
                                       specification
                                      Architect re analysis: Check the resulting
                                       Architecture anal sis               res lting
                                       software architecture for its equivalence
                                       with the initial architecture (consider
                                       requirements) – see also CQM methods and
                                       tools
                                  Use at least the latter two methods to ensure
                                   quality

                           Page 36




© Dr. Michael Stal, 2010


                                                                                                                                             18
Dr. Michael Stal: Architecture Refactoring




                                 Refactoring – responsibilities and communication


                                 The process of refactoring requires communication with testers and
                                 developers
                                                                                                        Product Lifecycle Manager
                                     SW Project Manager
                                                                                                         Control product development
                                      Define detailed project plans                                      across lifecycles
                                      Assign resources
                                                                                                                                     Requirements Engineer
                                                                                                                                      Review system
                                                                                                                                       architecture
                                                                        Detailed project                                               documents
                                                                           planning



                                     Head of R&D                                                                   SW Design
                                      Control SW                          Testability
                                                                                     y
                                       process
                                      Act as escalation                                   Software Architect
                                       point                                                Analyze architecture smells                Software Developer
                                                                                            Identify appropriate software               Identify code
                                     Test Manager                                            architecture refactorings e.g., using        smells
                                      Review product architecture                           refactoring catalogs                        Apply code
                                      Refine master test plan                              Apply software architecture                  refactorings
                                      Set up test strategy for integration and              refactorings
                                       system test                                          Verify correctness of refactorings
                                      Define test environment                              Be involved in design reviews
                                      Define verification and validation                   Leverage CQM tools
                                       procedure
                           Page 37




                                 Application of architecture refactorings


                                  The usage of a concrete application
                                   refactoring should never happen in an
                                   ad-hoc, unsystematic way. I t d
                                    dh            t     ti      Instead,
                                   the architect's role is to
                                    Check the applicability of refactorings
                                      Would the refactoring affect parts that
                                       need to remain unchanged, such as
                                       integration of third-party APIs?
                                      Could the refactoring impact require-
                                       ments in a negative way?
                                    Define the order of refactoring
                                      Strategic before tactical aspects
                                      Requirement priorities drive order!
                                    Apply the refactorings
                                    Ensure the quality of the software
                                     architecture after the refactoring (in
                                     conjunction with the test manager)
                           Page 38




© Dr. Michael Stal, 2010


                                                                                                                                                             19
Dr. Michael Stal: Architecture Refactoring




                                 Obstacles to refactoring (1)

                                  Organization / management
                                    Considering improvement by refactoring
                                     as less important than providing new
                                                p            p         g
                                     features
                                    Ignorance of refactoring necessity
                                     typically causes design erosion
                                    “Organization drives architecture”
                                     problem
                                  Process support
                                    No steps / activities defined in process
                                     for architecture refactoring: Refactoring
                                     should be addressed explicitly in the
                                      h ld b dd           d     li itl i th
                                     process; responsibilities must be
                                     assigned to different roles
                                    Refactorings are not checked for
                                     correctness, test manager not involved:
                                     Architects should work hand in hand
                                     with test manager and leverage means
                                     such as tests, architecture reviews
                           Page 39




                                 Obstacles to refactoring (2)

                                  Technologies and tools
                                    Unavailability of tools: Refactoring must
                                     be done manually, which can be tedious
                                                       y,
                                     and error-prone
                                    Unavailability of refactoring catalog: It is
                                     important to collect refactorings and
                                     document them
                                  Applicability
                                    Refactoring used instead of
                                     reengineering, and vice versa
                                    Wrong order of refactorings: Should be
                                     determined by requirements priority and
                                     d t    i db          i      t   i it       d
                                     relevance




                           Page 40




© Dr. Michael Stal, 2010


                                                                                    20
Dr. Michael Stal: Architecture Refactoring




                                 Refactoring

                                 Agenda

                                                    Motivation and foundation


                                                    Refactoring


                                                    Reengineering


                                                    Rewriting


                                                    Comparison


                                                    Summary




                           Page 41




                                 Reengineering – how it differs from refactoring


                                  Scope: Reengineering always
                                   affects the entire system;
                                   refactoring has typically
                                     f t i      h t i ll
                                   (many) local effects
                                  Process: Reengineering
                                   follows a disassembly /
                                   reassembly approach;
                                   refactoring is a behavior-
                                   preserving, structure
                                   transforming process
                                  Result: Reengineering can
                                   create a whole new system
                                    – with different structure,
                                   behavior, and functionality;
                                   refactoring improves the
                                   structure of an existing
                                   system – leaving its behavior
                                   and functionality unchanged

                           Page 42




© Dr. Michael Stal, 2010


                                                                                   21
Dr. Michael Stal: Architecture Refactoring




                                 Reengineering – when and how to use it


                                  Use reengineering when                Process
                                                                           Phase I: Reverse engineering
                                                                                                 g      g
                                      The system s documentation
                                           system's
                                                                             Analysis / recovery: determine
                                       is missing or obsolete
                                                                              existing architecture (consider
                                      The team has only limited              using CQM)
                                       understanding of the                  SWOT analysis
                                       system, its architecture, and         Decisions: what to keep, what
                                       implementation                         to change or throw away
                                                                         Phase II: Forward engineering
                                      A bug fix in one place
                                       causes bugs in other places                               Reverse                                                       Forward
                                                                                                 engineering                                                   engineering
                                      New system-level require-                                                                                      Requirements
                                       ments and functions cannot                  Conference
                                                                                    Organizer
                                                                                                       uses
                                                                                                              Conference
                                                                                                               Manager


                                                                                                                  *
                                                                                                                                   uses




                                                                                                                                 manages
                                                                                                                                          Scheduler

                                                                                                                                                                              Telegram
                                                                                                                                                                              Forwarder
                                                                                                                                                                                                           Telegram
                                                                                                                                                                                                           Receiver
                                                                                                                                                                                                                           The network




                                                                                                 organizes




                                       be addressed or integrated
                                                                                                                                         Media                                passes telegrams to
                                                                                                 participates Conference           uses Manager                                                                           passes telegrams to
                                                                                                                                                                                            Telegram




                                                                                                                                                      Design
                                                                                                                                                                                           Converter
                                                                                   Conference
                                                                                   Participant
                                                                                                                      *    has
                                                                                                                                                                                                                                  applies           passes
                                                                                                              Conference            *                                                       Command                   Logging
                                                                                                                                        Documents                                                                                               Logger
                                                                                                                                                                                                                                                    commands to
                                                                                                               Session                                                                      Processor                 Strategy



                                                                                                                                                                                                executes
                                                                                                                                                                                                                       Log
                                                                                                                                                                                            Command
                                                                                                                                                                                                                      Alarms

                                                                                                                                                                                          creates



                                                                                                                                                                    Pick                    SetPoint
                                                                                                                                                                 W orkpiece                Calculation




                                       appropriately
                                                                                                                                                        Code


                           Page 43




                                 Refactoring

                                 Agenda

                                                      Motivation and foundation


                                                      Refactoring


                                                      Reengineering


                                                      Rewriting


                                                      Comparison


                                                      Summary




                           Page 44




© Dr. Michael Stal, 2010


                                                                                                                                                                                                                                                                  22
Dr. Michael Stal: Architecture Refactoring




                                 Rewriting in a Nutshell

                                 Rewriting is a radical and fresh restart: existing design and code is
                                 trashed and replaced by a whole new design and implementation.
                                 Depending on focus:
                                  Improves structure regarding:
                                       Simplicity, visibility, spacing, symmetry,
                                        emergence
                                       Maintainability, readability, extensibility
                                       Bug fixing
                                  Provides new functionality
                                  Improves its operational qualities
                                     p           p          q
                                  Improves design and code stability

                                     As a consequence, rewriting addresses all
                                     types of software quality: functional,
                                     operational, and the various developmental
                                     qualities.

                           Page 45




                                 Learning from failure


                                 Failure and understanding failure is a key
                                 factor for successful design!


                                 [Henry Petroski]




                                     Before you’re going to rewrite, check what
                                     went wrong in the project that developed the
                                     previous application


                           Page 46




© Dr. Michael Stal, 2010


                                                                                                         23
Dr. Michael Stal: Architecture Refactoring




                                 Refactoring

                                 Agenda

                                                      Motivation and foundation


                                                      Refactoring


                                                      Reengineering


                                                      Rewriting


                                                      Comparison


                                                      Summary




                           Page 47




                                 Refactoring, reengineering, and rewriting comparison (1)


                                 Refactoring, reengineering, and rewriting are complementary approaches
                                 to sustain architecture and code quality
                                  Start with refactoring – it is cheap and (mostly) under the radar
                                  Consider reengineering when refactoring does not help – but it is expensive
                                  Consider rewriting when reengineering does not help – but it is expensive and
                                   often risky
                                                                                                                                                                                           Command
                                                                                                                                                                                           Processor                Strategy
                                                           Reverse                                        Forward                                                                    Command             Logging
                                                                                                                                                                       Client
                                                           engineering                                    engineering                                                                Processor           Strategy


                                                                                                                                                                                                         Concrete
                                                                                                    Requirements
                                                                                                      q                                                                                                  Logging
                                                                                                                                                                                                         Strategy
                                                                                                                                                                      Command &
                                                                                                                                                                      Composite
                                                                        uses         uses
                                                                          Conference   Scheduler                                         The network
                                                                           Manager                                  Telegram      Telegram
                                                           Conference
                                                            Organizer
                                                                            *
                                                                    organizes
                                                                    participates
                                                                                    manages

                                                                           Conference uses
                                                                                          Media
                                                                                                                   Forwarder      Receiver
                                                                                                                   passes telegrams to    passes telegrams to
                                                                                                                                                                                      Command            Memento
                                                                                                     Design                                                                                        *
                                                                                         Manager                          Telegram
                                                           Conference                                                    Converter
                                                           Participant        *    has
                                                                                                                                                applies passes
                                                                           Conference *                                    Command       Logging
                                                                                        Documents                                                      Logger
                                                                                                                                                        commands to
                                                                             Session                                       Processor     Strategy
                                                                                                                              executes    Log
                                                                                                                           Command
                                                                                                                                         Alarms
                                                                                                                          creates

                                                                                                                Pick       SetPoint
                                                                                                              Workpiece   Calculation
                                                                                                                                                                                                                    Memento
                                                                                                                                                                                Concrete    Composite
                                                                                                                                                                                Command     Command




                                                                                                      Code                                                                                 Application




                           Page 48




© Dr. Michael Stal, 2010


                                                                                                                                                                                                                               24
Dr. Michael Stal: Architecture Refactoring




                                 Refactoring, reengineering, and rewriting comparison (2)

                                                   Refactoring                     Reengineering                          Rewriting
                                Scope        Many local effects              Systemic effect                    Systemic or local effect

                                Process      Structure transforming          Disassembly / reassambly           Replacement
                                             Behavior / semantics
                                              preserving

                                Results      Improved structure              New system                         New system or new
                                             Identical behavior                                                   component

                                Improved     Developmental                   Functional                         Functional
                                qualities                                     Operational                        Operational
                                                                              Developmental                      Developmental

                                Drivers      Complicated design / code       Refactoring is insufficient        Refactoring and
                                              evolution                       Bug fixes cause rippling effect     reengineering are insufficient
                                             Wh fi i b
                                              When fixing bugs                New functional and                  or inappropriate
                                             When design and code smell       operational requirements           Unstable code and design
                                              bad                             Changed business case              New functional and
                                                                                                                   operational requirements
                                                                                                                  Changed business case
                                             Part of daily work              Requires a dedicated project       Requires dedicated effort or a
                                             At the end of each iteration                                         dedicated project, depending
                                When         Dedicated refactoring                                                on scope
                                              iterations in response to
                                              reviews
                           Page 49           It is the 3rd step of TDD




                                 Refactoring

                                 Agenda

                                                           Motivation and foundation


                                                           Refactoring


                                                           Reengineering


                                                           Rewriting


                                                           Comparison


                                                           Summary




                           Page 50




© Dr. Michael Stal, 2010


                                                                                                                                                    25
Dr. Michael Stal: Architecture Refactoring




                                 What we learned


                                  Refactoring changes artifacts without changing
                                   external behavior. It helps with quality improvement
                                   and necessary changes
                                       d            h
                                  In contrast, reengineering is a complete redesign of
                                   a complete architecture and typically changes
                                   external behavior
                                  If reengineering is not appropriate, it is often the
                                   best alternative to rewrite a system or its parts
                                  All methods are essential. Use the right one for the
                                   right purpose
                                  Testing and architecture introspections are
                                   important when refactoring, reengineering,
                                   i      t t h       f t i            i     i
                                   rewriting

                                  You as a software architect are responsible to
                                      Detect architecture smells
                                      Find and apply appropriate refactorings
                                      Perform QA of refactoring activities

                           Page 51




                                 A departing thought




                                 Each problem that I solved became a rule
                                 which served afterwards to solve other
                                 problems.

                                 [René Descartes, 1596–1650, in "Discours
                                 de la Methode"]




                           Page 52




© Dr. Michael Stal, 2010


                                                                                          26
Dr. Michael Stal: Architecture Refactoring




                                 Backup




                                                           Backup




                           Page 53




                                 Rename Entities (1)

                                 Example




                                                Comp                ShareTicker




                                             AnotherComp            ShareObserver




                           Page 54




© Dr. Michael Stal, 2010


                                                                                    27
Dr. Michael Stal: Architecture Refactoring




                                 Rename Entities (2)


                                  Context
                                      Using non intuitive names
                                             non-intuitive
                                  Problem
                                      Your software architecture contains entities named in such a way
                                       that the whole architecture lacks expressiveness
                                  General solution idea
                                      Introduce intuitive names so that stakeholders can easily
                                       understand the role of each subsystem
                                      Change the names of the entities and also consider references to
                                       these entities
                                      Change only one entity name at a time
                                      Use one predefined naming scheme / strategy throughout the
                                       project


                           Page 55




                                 Remove Duplicates (1)

                                 Example


                                                                                     Extract:
                                                                                     call locateBean(X)

                                     Client A     Extract:             Client A'
                                     main() {      Connect JNDI       main() {
                                      ...                               ...
                                     }             Get Home           }

                                                   Locate bean X

                                                                                    Bean                  1. Connect JNDI
                                                                                    Location              2. Get Home
                                                                                    Component
                                                                                                          3. Locate bean




                                     Client B     Extract:             Client B'
                                     main() {      Connect JNDI       main() {
                                      ...                               ...
                                     }             Get Home           }

                                                   Locate bean Y
                                                                                     Extract:
                                                                                     call locateBean(Y)




                           Page 56




© Dr. Michael Stal, 2010


                                                                                                                            28
Dr. Michael Stal: Architecture Refactoring




                                 Remove Duplicates (2)


                                  Context
                                    Equivalent design artifacts are replicated throughout the
                                       q              g                p             g
                                     architecture
                                  Problem
                                    DRY (Don't Repeat Yourself) is an essential means to increase
                                     simplicity, expressiveness, orthogonality and reuse
                                    On the other hand, if the same design artifacts are repeatedly
                                     implemented and used in a software architecture, then
                                     manageability and productivity will suffer
                                    How can we prevent the introduction of equivalent design artifacts?
                                  General solution idea
                                    Identify common (sequences of) tasks or sequences of tasks
                                     repeatedly used throughout your software system
                                    Analyze whether these common (sequences of tasks) can be
                                     provided as a generic component
                                    If that's the case, remove duplicates and introduce one common
                                     design artifact instead
                           Page 57




                                 Introduce Abstraction Hierarchies (1)

                                 Example: Class hierarchy



                                                Window
                                                Wi d                              Window
                                                                                  Wi d
                                                display()                         display()




                                                Panel                             Panel
                                                display()
                                                                                  drawPixel()
                                                drawPixel()




                                                Button                            Button
                                                display()                         onClick()
                                                drawPixel()
                                                onClick()




                                                Separate                         Related
                                                abstractions                     abstractions
                                                                                 "is-a" relation


                           Page 58




© Dr. Michael Stal, 2010


                                                                                                           29
Dr. Michael Stal: Architecture Refactoring




                                 Introduce Abstraction Hierarchies (2)


                                  Context
                                    Entities representing related concepts
                                                p         g               p
                                  Problem
                                    In the architecture design entities appear that implement almost the
                                     same functionality
                                    This leads to design and code replication, as well as to less
                                     expressiveness and simplicity
                                  General solution idea
                                    Leverage the Liskov Substitution Principle
                                      Introduce general abstractions containing the common parts of
                                       these entities
                                      Define hierarchy of abstractions
                                      Derive entities from the most specific abstraction
                                    Different possibilities
                                      Adding superclass
                                      Adding common interfaces

                           Page 59




                                 Remove Unnecessary Abstractions (1)

                                 Example

                                               Transport *                       Abstract                   Abstract
                                                  Way                            Storage                    Strategy
                                                                                            *

                                                    *
                                                 Equip-                                         Composite   Concrete
                                                              Dump    Door          Bin
                                                  ment                                           Storage    Strategy
                                           *



                                                  Cart       Belt




                                                                                 Abstract                   Abstract
                                                                                 Storage                    Strategy
                                                                             *              *


                                                                                                Composite   Concrete
                                               Equipment     Dump    Door          Bin
                                                                                                 Storage    Strategy


                           Page 60




© Dr. Michael Stal, 2010


                                                                                                                       30
Dr. Michael Stal: Architecture Refactoring




                                 Remove Unnecessary Abstractions (2)


                                  Context
                                    Eliminating unnecessary design abstractions
                                  Problem
                                    Minimalism is an important goal of software architecture, because
                                     minimalism increases simplicity and expressiveness
                                    If the software architecture comprises abstractions that could also
                                     be considered abstractions derived from other abstractions, then it
                                     is better to remove these abstractions
                                  General solution idea
                                    Determine whether abstractions / design artifacts exist that could
                                     also be derived from other abstractions
                                    If this is the case,
                                      remove superfluous abstractions;
                                      derive entities that depend from removed abstractions to derive
                                        from abstractions being left
                                    Challenge: Don't generalize too much (such as introducing one
                                     single hierarchy level: "All classes are directly derived from Object")

                           Page 61




                                 Substitute Mediation with Adaptation (1)

                                 Example

                                                     I_have
                                                 no_clue_sub_1
                                                 no clue sub 1


                                        I_have                        I_have         A              B               C
                                     no_clue_sub2                  no_clue_sub_3


                                                                                   Adapter       Adapter         Adapter
                                                 Do_Everything_
                                                      Class                                  Integration Layer
                                                 a.k.a. Mediator
                                                                                   Adapter       Adapter         Adapter


                                        I_have                     I_have
                                     no_clue_sub_4             no_clue_sub_5         D              E               F


                                                    I_have
                                                 no_clue_sub_6




                           Page 62




© Dr. Michael Stal, 2010


                                                                                                                           31
Dr. Michael Stal: Architecture Refactoring




                                 Substitute Mediation with Adaptation (2)


                                  Context
                                    Centralized system using a mediation level between peers
                                  Problem
                                    When interaction between different peers is complex, a mediator
                                     may be the right solution
                                    However, extensive use of mediator may reduce scalability
                                    If mediation was just applied to build an extremely generic solution,
                                     design erosion is often the price
                                    How can we improve this situation?
                                  General solution idea
                                    Introduce adapters to uniformly plug in peers
                                    But make interaction explicit, i.e. subsystems themselves are in
                                     charge to interact with the appropriate peers using an integration
                                     layer
                                    Known use: Enterprise Application Integration (Hub and Spoke) =>
                                     Enterprise Service Bus


                           Page 63




                                 Break dependency cycles (1)



                                                               GetState()                      GetState()
                                     In this example,          SetState {                      SetState {

                                     the monitor               ...                             ...
                                                                   M.GetDate()                     D.GetDate()
                                     invokes the state
                                                               }                               }
                                     getter / setter
                                     methods but also
                                                                     Sensor                          Sensor             GetDate()
                                     provides GetDate()
                                     to the sensor, lea-
                                     ding to a simple                            X Break
                                                                                   Cycle                         Date
                                     dependency cycle.
                                     Providing this me-
                                     thod to monitors
                                                                   Monitor                           Monitor
                                     was a bad design
                                     decision, anyway.
                                                                                           Draw() {
                                     Introducing a         GetDate()
                                                           Draw() {                        ...
                                     sepa-rate date                                        S.GetState();
                                                           ...
                                     object solves the     S.GetState();                   }

                                     problem.              }




                           Page 64




© Dr. Michael Stal, 2010


                                                                                                                                    32
Dr. Michael Stal: Architecture Refactoring




                                 Break dependency cycles (2)


                                  Context
                                       Dependencies between subsystems
                                  Problem
                                       Your system reveals at least one dependency cycle between
                                        subsystems
                                       Subsystem A may either depend directly or indirectly on subsystem B
                                        (e.g., A depends on C which depends on B) which is why we always
                                        need
                                        to consider the transitive hull
                                       Dependency cycles make systems less maintainable, changeable,
                                        reusable, testable, understandable
                                       Thus, dependency hierarchies should form DAGs (directed acyclic
                                        graphs)
                                  General solution idea
                                       Get rid of the dependency cycle by removing one of the dependencies
                           Page 65




                                 Break dependency cycles – Dependency Inversion


                                                                                   interface IObserver { Handle() }
                                                           Attach(Observer)        Attach(IObserver)
                                                           Notify(                 Notify(
                                     Dependency inver-     observer.Handle();      iObserver.Handle();
                                     sion constitutes      )                       )

                                     another variant
                                                               Subject'                            Subject




                                                               Observer'                           Observer

                                                           Handle()                class Obs implements IObserver {
                                                           StartUp() {                 Handle() { ...}   }
                                                           subj.Attach(obs);       StartUp(
                                                           )                           subj.Attach(obs);
                                                                                   )




                           Page 66




© Dr. Michael Stal, 2010


                                                                                                                      33
Dr. Michael Stal: Architecture Refactoring




                                 Inject Dependencies (1)

                                 Example

                                           Component c {                   Component c {
                                           S s = new S(.....);             inject(S p){ s=p;}
                                           s.m();                          s.m();
                                           }                               }




                                               Component c                     Component c




                                               Component s                     Container m       Component s


                                                                           C c = new C();
                                                                           S.S = new S(.....);
                                                                           c.inject(s);




                           Page 67




                                 Inject Dependencies (2)


                                  Context
                                      Components that need to create and use other components
                                  Problem
                                      If a component c needs access to other components, it most
                                       somehow create these components or locate them
                                      However, this makes c too dependent on the knowledge about
                                       specific component location or factory mechanisms
                                      How can we avoid these additional dependencies?
                                  General solution idea
                                      Move functionality for discovery and creation of components to
                                       separate component m
                                      Introduce configuration to let component c specify its requirements
                                       and let m be responsible for creating, discovering and then injecting
                                       required component references to c

                           Page 68




© Dr. Michael Stal, 2010


                                                                                                               34
Dr. Michael Stal: Architecture Refactoring




                                 Insert Transparency Layer (1)

                                 Example




                                                   Subsystem B                                     Subsystem B
                                                                                    TRANSPARENCY
                                     Client                               Client        LAYER




                           Page 69




                                 Insert Transparency Layer (2)


                                  Context
                                    Decoupling clients or from subsystems and vice-versa
                                  P bl
                                   Problem
                                    When a client accesses subsystems directly, some dependencies are
                                     introduced, e.g.,
                                      On the exact physical location of the subsystems, or
                                      On specific data or document formats the subsystem expects
                                    The client must have knowledge about how to locate and access the
                                     subsystems
                                    Finally, the client also becomes dependent on subsystem
                                     implementation aspects
                                  General solution idea
                                    To avoid such dependencies, we introduce transparency layers to
                                     decouple these dependencies from clients
                                    Transparency layers also open additional optimization possibilities
                                    This is basically a whole class of architecture refactorings, because for
                                     the implementation of transparency layers we rely on patterns such as
                                     Proxy, Facade, Wrapper-Facade, Business Delegate, Service Locator,
                                     Proxy
                           Page 70




© Dr. Michael Stal, 2010


                                                                                                                 35
Dr. Michael Stal: Architecture Refactoring




                                 Example: Introducing Protection Layers


                                    Typically, an architectural entity depends directly
                                     on other architectural entities
                                                                                                              Client
                                    This becomes a problem when the target of the
                                                      p                     g
                                     dependency is subject to change (volatility)
                                    In this case add a layer to protect your entity
                                     from directly depending on a volatile entity
                                    Note: this decreases inter-component coupling
                                                                                                      Protection Layer




                                                                                                              Server




                           Page 71




                                 Reduce Dependencies with Facades (1)

                                 Example

                                                                                           1.3     Rental Car
                                                                                                    Bookingg

                                                                                             1.2                    Hotel
                                              Client
                                                                                                                   Booking

                                                                                                     Flight
                                                                                           1.1      Booking



                                                                                           2.3     Rental Car
                                                                                                    Booking
                                                                                                    B ki

                                                                        Facade
                                                              1                              2.2                    Hotel
                                              Client                     Travel
                                                                                                                   Booking
                                                                        Booking

                                                                                                    Flight
                                                                                           2.1     Booking


                           Page 72




© Dr. Michael Stal, 2010


                                                                                                                             36
Dr. Michael Stal: Architecture Refactoring




                                 Reduce Dependencies with Facades (2)


                                  Context
                                    Client implements workflows that mostly access other components
                                                p                              y                 p
                                  Problem
                                    If a client needs to access different external components for each
                                     workflow, it becomes dependent on details such as the set of available
                                     components
                                    As soon as the configuration and / or interfaces of these components
                                     change, there will be a direct impact on the client
                                  General solution idea
                                    Introduce a Facade component that acts as the client s gateway into
                                                                                       client's
                                     the set of required components
                                    Implement workflow methods within the facade that represent the
                                     different workflows
                                    The facade methods take over the responsibility for accessing the set
                                     of required components on behalf of the client, thus decoupling the
                                     client from the components
                                    If components are remote, performance is also improved (Session
                           Page 73
                                     Facade)




                                 Merge Subsystems (1)

                                 Example: While tight coupling between subsystems is bad, high cohesion within
                                 subsystems is good. Thus, merge tightly coupled subsystems to form a highly
                                 cohesive subsystem .



                                                    Sensor



                                                                                      Sensor + Utilities




                                                    Utilities




                                 Special variant: Merge a layer in a layered system

                           Page 74




© Dr. Michael Stal, 2010


                                                                                                                 37
Dr. Michael Stal: Architecture Refactoring




                                 Merge Subsystems (2)


                                  Context
                                    Coupling between subsystems
                                  Problem
                                    Between two subsystems in a software architecture the degree of
                                     coupling should be rather loose
                                    Within a subsystem the number of interdependencies (cohesion)
                                     should be high
                                    If the coupling is too tight, then the many interdependencies between
                                     these two subsystems decrease qualities such as
                                    Changeability
                                    Performance (maybe)
                                    Reusability of one of the subsystems
                                  General solution idea
                                    Tight coupling between subsystems implies that the two subsystems
                                     in fact implement one subsystem
                                    Either merge both subsystems to form one, or
                                    Move functionality from one subsystem to the other


                           Page 75




                                 Split Subsystems (1)

                                 Example: When analyzing interdependencies between entities in a subsystem, two
                                 (or more) sets can be determined. Within these sets there is high cohesion; between
                                 these sets there is only low cohesion. Thus, split the subsystem into two (or more)
                                 parts.


                                                                                               Component
                                                                                                Container
                                                       High Cohesion

                                           Lifecycle
                                                        Persistence    Event Handling
                                          Management


                                                Component Container

                                                       Communication


                                                                                               Communi-
                                                                                                cation



                                 Special variant: Split layer in a layered system


                           Page 76




© Dr. Michael Stal, 2010


                                                                                                                       38
Dr. Michael Stal: Architecture Refactoring




                                 Split Subsystems (2)


                                  Context
                                    Cohesion within a subsystem
                                  Problem
                                    Within a subsystem the interdependencies (cohesion) should be high
                                    Between two subsystems in a software architecture, the degree of
                                     coupling should be rather loose
                                    If the cohesion between some parts is loose, then some design
                                     decisions seem to be questionable
                                    It is recommendable to change this to obtain better modularization and
                                     understandability
                                    Another potential problem are subsystems/components with too many
                                     responsibilities
                                  General solution idea
                                    Loose cohesion within a subsystem implies that the functionality can
                                     be split into multiple subsystems
                                    Thus, determine areas with high cohesion in a subsystem. All those
                                     areas with low cohesion are candidates for becoming subsystems of
                                     their own

                           Page 77




                                 Enforce Strict layering (1)

                                 Example


                                           Application
                                            pp                                               Application



                                          Layer 3                                           Layer 3

                                                Component       Component       Component       Component         Component       Component
                                                   3.1             3.2             3.3             3.1               3.2             3.3


                                          Layer 2                                           Layer 2

                                     Broken         Component               Component                 Component               Component
                                     layering          2.1                     2.2                       2.1                     2.2


                                          Layer 1                                           Layer 1

                                                Component       Component       Component       Component         Component       Component
                                                   1.1             1.2             1.3             1.1               1.2             1.3




                           Page 78




© Dr. Michael Stal, 2010


                                                                                                                                              39
Dr. Michael Stal: Architecture Refactoring




                                 Enforce Strict Layering (2)


                                  Context
                                      An architecture with broken layering
                                  Problem
                                      Layers are introduced to reduce dependencies, increase adaptability
                                       and reusability, as well as maintainability
                                      Sometimes relaxed layering is used intentionally to solve problems
                                       such as performance issues
                                      At other times relaxed layering is used accidentally without any
                                                                y    g                    y           y
                                       justification and value
                                      In the latter case, how can we cure the broker layering?
                                  General solution idea
                                      Redesign so that the broken layering is substituted with strict layering


                           Page 79




                                 Enforce Strict Layering (3)


                                  Unfortunately, broken layering is often hard to cure
                                  To resolve the broken layering between component 3.1 and component
                                   1.1, we must differentiate the following cases:
                                    Case 1: All the types of functionality of component 1.1 that component
                                      3.1 uses are also available in layer 2
                                       In component 3.1, substitute all usages of component 1.1 by
                                        equivalent functionality of layer 2
                                    Case 2: Not all the types of functionality of component 1.1 that
                                      component 3.1 uses are available in layer 2
                                       Substitute all those component 1.1 invocations with equivalent
                                        invocations of layer 2 For the rest of the invocations move
                                                              2.                    invocations,
                                        functionality from layer 3 to layer 2
                                  In case 2 it is sometimes not advisable to move functionality from layer 3
                                   to layer 2. Consider reengineering activities instead!
                                  Note: This is one of the refactorings that can also be applied in the
                                   opposite direction. If strict layering is not feasible (e.g., due to
                                   performance), relax the strict layering!

                           Page 80




© Dr. Michael Stal, 2010


                                                                                                                  40
Dr. Michael Stal: Architecture Refactoring




                                 Move Entities (1)

                                 Example



                                                  y       z                                        y      z
                                           x                                               x
                                                Game                                             Game

                                          getPlayerHistory(p)




                                                                                           getPlayerHistory()

                                                Player                                          Player




                           Page 81




                                 Move Entities (2)


                                  Context
                                      Moving entities between subsystems
                                  Problem
                                      This can be considered a generalization of the Split Subsystem
                                       refactoring
                                      In a subsystem an entity is defined that fits better semantically in
                                       another subsystem to which it has high coupling
                                  General solution idea
                                      Again, we should consider cohesion and coupling
                                      If entity e reveals low or zero cohesion to the rest of its subsystem A,
                                       but tight coupling to subsystem B, then move e from A to B
                                      Note: This may also help with breaking dependency cycles between
                                       subsystems
                           Page 82




© Dr. Michael Stal, 2010


                                                                                                                  41
Dr. Michael Stal: Architecture Refactoring




                                 Move Entities (3)


                                 Some additional issues
                                  In many cases we can t apply the refactoring to single atomic entities
                                           cases,    can't
                                   such as a class, method, constant, interface
                                  It is more likely that there will be clusters of atomic entities that together
                                   build a complex entity
                                  In the example, it is very likely that there will be classes and interfaces
                                   related to the method to be moved
                                  Thus, always consider semantically related entities with high internal
                                             y                       y                        g
                                   cohesion but less cohesion to the rest of their subsystem. If some of
                                   them show tight coupling to another subsystem, move the whole group
                                  Moving may not always be a simple operation, but imply several smaller
                                   grained transformations (see example)


                           Page 83




                                 Add Strategies (1)

                                 Example


                                                                                           Warning
                                          Client                          Client            Never introduce
                                                                                             strategies in an
                                                                                             uncontrolled way

                                                                                            A strategy basically
                                                                       Middleware            means "I have no idea
                                       Middleware
                                                                                             which option to use at
                                                                     DispatcherStrategy
                                                                                             runtime"
                                     Request Dispatcher

                                                                                            St t
                                                                                             Strategy S d
                                                                                                      Syndrome isi
                                                                     ConcreteDispatcher
                                                                                             a serious disease that
                                                                                             leads to an over-
                                                                                             generic architecture
                                                                                             which is doomed to
                                          Protocol                        Protocol
                                                                                             design erosion




                           Page 84




© Dr. Michael Stal, 2010


                                                                                                                      42
Dr. Michael Stal: Architecture Refactoring




                                 Add Strategies (2)


                                  Context
                                      Enable selection and exchange of implementations
                                  Problem
                                      Services and algorithms in a component can be implemented in
                                       various ways. Their implementation often also depend on client
                                       requirements
                                      The client should not depend on the concrete implementations used
                                      Hard-coding a service or algorithm and then exchanging it at source
                                       code level is a possible solution
                                      Unfortunately, this does not hold for runtime configurability
                                      How can we refactor a component to support this kind of runtime
                                       configuration?
                                  General solution idea
                                      Use the Strategy pattern

                           Page 85




                                 Enforce Symmetry (1)

                                 Examples for structural symmetry




                                                                                          Some places in
                                       Subsystem UI                   Subsystem UI         the architecture
                                       Based on MVC                   Based on MVC         throw exceptions,
                                       and Observer                   and Observer         while other return
                                                                                           error codes
                                                                                          One subsystem
                                                                                           leverages the
                                     Subsystem Accounts
                                          y                                                Observer pattern,
                                                                                                      pattern
                                       Uses hardwired               Subsystem Accounts
                                       configuration of               Uses Observer        another one a
                                        event handlers                                     hardwired event
                                                                                           notification
                                                                                           strategy



                           Page 86




© Dr. Michael Stal, 2010


                                                                                                                43
Dr. Michael Stal: Architecture Refactoring




                                 Enforce Symmetry (2)


                                  Context
                                    Refactor an asymmetric solution
                                  Problem
                                    Asymmetry reduces conceptual integrity and simplicity
                                    Structural asymmetry deals with the usage of the same solution
                                     concepts throughout an architecture
                                    Functional asymmetry is relevant on the method level ("When there is
                                     an open, there should be a close operation")
                                  General solution idea
                                    Prioritize strategy over tactics
                                    For identical problem contexts in your architecture, apply the same
                                     solutions (e.g., the same patterns)
                                    Use refactoring-to-patterns where applicable
                                    All unmotivated asymmetries should be removed step-by-step

                           Page 87




                                 Enforce Symmetry (3)

                                 Example for functional symmetry: Abstract Factory with missing dispose method

                                                       AbstractFactory       AbstractProductA
                                                     create_productA
                                                     create productA        ProductA




                                                       ConcreteFactory       ConcreteProductA
                                                     create_productA        ProductA




                                                       AbstractFactory       AbstractProductA
                                                     create_productA        ProductA
                                                     dispose_productA



                                                       ConcreteFactory       ConcreteProductA
                                                     create_productA        ProductA
                                                     dispose_productA

                           Page 88




© Dr. Michael Stal, 2010


                                                                                                                 44
Dr. Michael Stal: Architecture Refactoring




                                 Extract Interface (1)

                                 Example

                                                                  << interface >>
                                                                    ISensor
                                                                getTemperature(UNIT)




                                     Sensor                         Adapter
                                                                                        if (UNIT == CELSIUS)
                                     temperature()             Sensor
                                     useCelsius()                                       useCelsius();
                                     useFahrenheit()           temperature()            else
                                     initialize()              useCelsius()
                                     reset()                   useFahrenheit()          useFarhrenheit();
                                     getAverage(from,to)       initialize()             return temperature();
                                     storeRecord()             reset()
                                     getRecord(DateTime)       getAverage(from,to)
                                     getDateTime()             storeRecord()
                                                               getRecord(DateTime)
                                                               getDateTime()




                           Page 89




                                 Extract Interface (2)


                                  Context
                                    (Sub)system needs to export functionality
                                  Problem
                                    An existing (sub)system needs to export some of its internal
                                     functionality to external users
                                    How can the (sub)system developer make internal functionality
                                     available externally?
                                  General solution idea
                                    Define abstract interface and contract
                                    Provide wiring of interface methods to internal functionality
                                    Apply patterns such as Bridge, Decorator, or Adapter to separate
                                     interface from implementation
                                    Optionally, use the Extension Interface pattern to manage multiple
                                     interfaces


                           Page 90




© Dr. Michael Stal, 2010


                                                                                                                45
Dr. Michael Stal: Architecture Refactoring




                                 Enforce Contract (1)

                                 Example


                                     << interface >>            << interface >>
                                           IFile                     IFile
                                     Handle open(File)          Handle open(File)
                                     Write(Handle, buf)            Write(buf)
                                      close(Handle)                 close()

                                                                                                               Write/
                                                                                                               notEmpty(buf)
                                                                                               Open/
                                                                  Contract                     IsValid(File)
                                                               Implementation
                                                                                                                        Close
                                                                                    Open/
                                                                                    not IsValid(File)
                                                                                               (    )
                                      File System               File System




                           Page 91




                                 Enforce Contract (2)


                                  Context
                                    Enforcing contract of an interface
                                  Problem
                                    A contract defines what the user of an interface must provide and what
                                     the user can expect in turn, e.g., preconditions, postconditions,
                                     required order of method execution
                                    Often, interface implementations do not enforce the contract
                                    A contract that is never enforced is of limited value
                                    How can we enforce the interface contract?
                                  General solution idea
                                    Define contract explicitly: For example, use a state machine to define
                                     method execution order. Specify interface invariants. For each method,
                                     determine preconditions and postconditions
                                    Enrich interface implementation to enforce contract

                           Page 92




© Dr. Michael Stal, 2010


                                                                                                                                46
Dr. Michael Stal: Architecture Refactoring




                                 Provide Extension Interfaces (1)


                                                                                                           Client
                                                                             Factory

                                                                          create()
                                          Interface1                      find()

                                      service_1.1();
                                      service_1.2();
                                      service_1.3();
                                      service_1.4();                                    RootInterface
                                      .                                                 get_extension()
                                      .
                                      .
                                      .
                                      .
                                      .                                       Extension                Extension
                                      .                                       Interface1               Interface2
                                      service_1.n();                      service_1()            service_2()



                                                       Component                           Component
                                                                                        svc_1_impl()
                                                                                        svc_2_impl()


                           Page 93




                                 Provide Extension Interfaces (2)


                                  Context
                                    Managing interfaces of a component
                                  Problem
                                    If a component evolves over time, often new functionality is added to
                                     the component's interfaces
                                    This may lead to severe interface bloating, which has a negative impact
                                     on quality attributes such as usability and manageability (Swiss Army
                                     Knife anti-pattern)
                                    Unsystematic interface evolution may also break client code
                                    How can we add an interface management for systematically evolving
                                     and providing interfaces?
                                  General solution idea
                                    Apply Extension Interface Patterns [POSA2]
                                    Introduce a common protocol for all provided interfaces (including
                                     interface navigation)
                                    Integrate additional functionality so that clients can discover existing
                                     component interfaces and navigate between them

                           Page 94




© Dr. Michael Stal, 2010


                                                                                                                    47
Dr. Michael Stal: Architecture Refactoring




                                 Provide Extension Interfaces (3)


                                     Client                Factory
                                                                                                                             Notes
                                              Interface
                                                 ID1
                                                                                       Root
                                                                                                  Ext        Ext              This refactoring alters
                                                                         Comp.                   Inter-     Inter-
                                               create                                Interface
                                                                                                 face1      face2
                                                                                                                               components and
                                                                         Interface
                                                                                                                               clients. Thus, handle
                                                                            ID1
                                                                                                                               with care!
                                               Interface
                                                                         Interface                                            Interface navigation
                                                                             1
                                                   1
                                                                                           service1                            should be reflexive,
                                                                                                                               symmetric, transitive
                                                                                                                              But you may also
                                                             Interface
                                                                ID2           get_extension

                                                             Interface
                                                                                                                               introduce a dedicated
                                                                 2
                                                                                                      service2                 interface that includes
                                                                                                                               the navigation
                                                                                                                               functionality



                           Page 95




                                 Substitute Inheritance with Delegation (1)

                                 Example




                                                          Player                                                                 IPlayer
                                                          play()                                                                 play()




                                                                                                             Player                                  Ninja
                                                                                                                                                     lookupExperience()
                                     Ninja                                                                   play(IPlayer)                           play()
                                     lookupExperience()                                                      play()                                  Player p
                                                                                                                                          delegate




                                                                                                                 play(IPlayer ip) {
                                                                                                                  // pre-processing
                                                                                                                   this.play();
                                                                                                                  // post-processing
                                                                                                                 }




                           Page 96




© Dr. Michael Stal, 2010


                                                                                                                                                                          48
Dr. Michael Stal: Architecture Refactoring




                                 Substitute Inheritance with Delegation (2)


                                  Context
                                    Using delegation when inheritance is not available or not suitable
                                  Problem
                                    Assume an entity D should logically inherit from entity B, but
                                     inheritance is not available on component or subsystem level, or
                                     inheritance cannot be used due to other restrictions
                                    In these cases, using inheritance is not the right approach
                                    How can we get rid of (the necessity to use) inheritance but get the
                                     same possibilities?
                                  General solution idea
                                    Keep B as it is
                                    Within entity D add reference to B
                                    Provide public interface of B also in D but forward all invocations to
                                     referred B (optionally passing a reference to D for back calls)
                                  Additional note
                                    This is another one of the reversible patterns that may also be
                                     applicable in the opposite direction!

                           Page 97




                                 Provide Interoperability Layers (1)

                                 Example




                                                                                              Application layer




                                                                                             Adapter layer




                                      Provide bidirectional interoperability between two subsystems using
                                       Web Services
                                      Extract subsystem interfaces and use adapters (e.g., session facades,
                                       business delegates) to integrate them with their subsystems



                           Page 98




© Dr. Michael Stal, 2010


                                                                                                                  49
Dr. Michael Stal: Architecture Refactoring




                                 Provide Interoperability Layers (2)


                                  Context
                                    Enable interoperability between two subsystems
                                  Problem
                                    Sometimes formerly collocated subsystems need to be distributed, or
                                    An application needs to interoperate with other legacy applications
                                    Unfortunately, both of them were not designed to interoperate
                                  General solution idea
                                    Insert adapter layers to provide interoperability
                                    Adapt subsystem A to B or subsystem B to A or use a bidirectional
                                                                                 A,
                                     adaptation
                                    Adaptation is a holistic approach. You may adapt communication, data,
                                     policies
                                    Use patterns such as Adapter or Wrapper Facade. In other words,
                                     apply the Insert Transparency Layer refactoring

                           Page 99




                                 Provide Interoperability (3)


                                  Aspects for interoperability in object-oriented, distributed systems
                                       Interoperability is not restricted to data transformation and
                                        communication
                                       For example, we also need to adapt error management
                                       Likewise, object models must be mapped onto each other
                                       Policies (e.g., security, memory management) must be mapped onto
                                        each other
                                  The simpler the adaptation layers provided, the more work developers
                                          p           p         y    p       ,                     p
                                   must spend to close the semantic gap
                                  Integration products such as EAI solutions just provide a set of
                                   proprietary interoperability solutions




                           Page 100




© Dr. Michael Stal, 2010


                                                                                                             50
Dr. Michael Stal: Architecture Refactoring




                                 Aspectify (1)

                                 Example




                                                                                        +




                                            Logging                                    Logging
                                            functionality                              functionality




                           Page 101




                                 Aspectify (2)


                                  Context
                                    Dealing with cross-cutting concerns
                                            g                  g
                                  Problem
                                    Cross-cutting concerns such as security mechanisms, distribution
                                     mechanisms and other invasive functionalities lead to extensive
                                     replication of design and code
                                    OO mechanisms such as inheritance can't solve the problem, due to
                                     infeasible centralization of these concerns
                                    Nonetheless, separation of concerns should be supported
                                  General solution idea
                                    Express concern as a centralized package
                                    Introduce injection mechanism to integrate wrapped concern in all
                                     required places of software architecture
                                    If cross-cutting concerns are interdependent, allow injection
                                     mechanism to take care of interdependencies, for example by using
                                     prioritization or a generative approach

                           Page 102




© Dr. Michael Stal, 2010


                                                                                                         51
Dr. Michael Stal: Architecture Refactoring




                                 Integrate DSLs (1)

                                 Example
                                      Interface                 Root                    Monitor       Interface                 Root                    Monitor
                                       Factory                Interface                                Factory                Interface

                                 StorageMgr       Capacity    ServiceX                   Abstract    StorageMgr   Capacity    ServiceX                   Abstract
                                  Interface       Interface   Interface                Interceptor    Interface   Interface   Interface                Interceptor
                                                                                            *                                                               *
                                                  Storage      Leafs      LoadIn                                  Storage      Leafs       LoadIn
                                                  Capacity     Only       Layers                                  Capacity     Only        Layers

                                      Storage     Abstract    Abstract    Abstract                    Storage     Abstract    Abstract     Abstract
                                                                                         Hook                                                            Hook
                                      Manager      Visitor    Iterator    Strategy                    Manager      Visitor    Iterator     Strategy
                                                    *           *      Abstract
                                                                                            *                       *           *                           *
                                                                                                                                       Abstract
                                                                       Storage        Successor                                                       Successor
                                                                                                                                       Storage
                                                                                  *                                                               *
                                       SOC                    Atomic          Composite                 SOC                   Atomic           Composite
                                      Factory                 Storage          Storage                 Factory                Storage           Storage
                                       *
                                 Hazardous                                 Ware-
                                                                                                            *
                                                                Bin                      Aisle        Hazardous
                                        SOC                                house                                                Bin       Warehouse      Aisle
                                                                                                         SOC

                                 Hazardous                      Real      Thread                     Hazardous                  Real       Thread
                                                                                         Socket                                                          Socket
                                   Value                        Bin       Mutex                        Value                    Bin        Mutex




                                        Microsoft's XAML (eXtensible Application Markup Language) is used
                                         for specifying workflows declaratively within and between
                                         applications
                                        In the past, developers had to hardcode these workflows in the
                                         architecture using implementation languages such as C#
                           Page 103




                                 Integrate DSLs (2)


                                  Context
                                    A system that covers many different domains
                                  Problem
                                    Mastering complexity in a software system is an important challenge.
                                     Complexity is often cause by the usage of multiple domains (based on
                                     different concepts and paradigms)
                                    If many domains are involved, such as the business logic itself,
                                     accessing databases, specifying workflows, UI design, then impedance
                                     mismatch becomes an essential issue
                                    In addition, the work of different domain experts is more difficult,
                                     because all domain experts must understand the full software system
                                  General solution idea
                                    Instead of hard-coding domain-specific functionality manually, define a
                                     metamodel / DSL that allows domain experts to define their logic
                                    Implement generators that transform models / DSLs to implementation
                                     artifacts
                                    Define an integration subsystem for each of these domains that
                                     integrates the generated artifacts with the rest of the system

                           Page 104




© Dr. Michael Stal, 2010


                                                                                                                                                                     52
Dr. Michael Stal: Architecture Refactoring




                                 Add Uniform Support for Runtime Aspects (1)



                                                  Subsys UI                              Subsys UI
                                      IUIAdmin                                  IAdmin




                                                  Subsys DB                              Subsys DB
                                      IDBAdmin                                  IAdmin




                                                  Subsys ATM                             Subsys ATM
                                      IATMAdmin                                 IAdmin



                                                                   Management
                                                                    Console




                           Page 105




                                 Add Uniform Support for Runtime Aspects (2)


                                  Context
                                    Software architecture that must support runtime aspects such as
                                     lifecycle management, management, configuration
                                       f                                       f
                                  Problem
                                    Each non-trivial software architecture consists of multiple
                                     components, each of which supports common aspects
                                    If every component implements its own interfaces for runtime aspects,
                                     the overall system will lack simplicity and expressiveness
                                    Is there a way to provide a uniform approach to support those kinds of
                                     runtime aspects?
                                  General solution idea
                                    For each aspect, define a common interface (e.g., an interface for
                                     runtime configuration)
                                    In each component supporting the aspect, provide this common
                                     interface (maybe using Extension Interfaces to prevent bloating)
                                    To achieve orthogonality, provide one runtime component that is in
                                     charge
                                     of accessing these common interfaces (e.g., a management console)

                           Page 106




© Dr. Michael Stal, 2010


                                                                                                              53
Dr. Michael Stal: Architecture Refactoring




                                 Add Configuration Subsystem (1)

                                 Example



                                                                                          Actor
                                                          Subsystem UI                                       Subsystem UI
                                               IConfig1                                            IConfig
                                                                          Configuration




                                                          Subsystem DB             Configuration             Subsystem DB
                                      Actor
                                              IConfig2                              Subsystem      IConfig




                                                          Subsystem ATM                                      Subsystem ATM
                                               IConfig3                                            IConfig




                                       Use patterns such as Component Configurator for this purpose

                           Page 107




                                 Add Configuration Subsystem (2)


                                  Context
                                    A system with many configurable variabilities
                                  Problem
                                    If a system contains a lot of configuration options, then configuration
                                     itself is often tedious and error-prone
                                    This holds in particular when the configuration options are (partially)
                                     related to each other
                                    How can we refactor the software system so that configuration is
                                     simplified and (partially) automated?
                                  General solution idea
                                    Instead of providing dozens of configuration options to external actors,
                                     we introduce a configuration subsystem that takes a declarative
                                     configuration (from a file or a wizard)
                                    The configuration subsystem reacts to configuration change events,
                                     reads the passed configuration, and then accesses the configuration
                                     interfaces of configurable subsystems
                                    Ideally, all subsystems provide the same generic configuration
                                     interface

                           Page 108




© Dr. Michael Stal, 2010


                                                                                                                             54
Dr. Michael Stal: Architecture Refactoring




                                 Introduce the Open/Close Principle (1)

                                 Example




                                              Sensor                                 Sensor




                                                                                          ObserverInterface




                                                                                  SensorMonitor




                           Page 109




                                 Introduce the Open / Close Principle (2)


                                  Context
                                    Opening a subsystem for external monitoring or modification (e.g.,
                                     eventing or interception) )
                                  Problem
                                    An existing subsystem needs to be opened to let other subsystems
                                     observe this subsystem or intercept specific behavior
                                    So far, the subsystem has been a black box
                                    How can we introduce mechanisms for opening our architecture in a
                                     controlled way?
                                  General solution idea
                                    Apply the Open / Close Principle
                                      Design the states and state transitions of the subsystem and decide
                                       which transitions should be observable or interceptable
                                      For all these observation and interception points, introduce
                                       appropriate hooks with which other subsystems can register for
                                       observation or interception
                                      If interception is required, design the required context object and
                                       subsystem internal functionality required for interception

                           Page 110




© Dr. Michael Stal, 2010


                                                                                                              55
Dr. Michael Stal: Architecture Refactoring




                                 Optimize with Caching (1)

                                 Example




                                      Client           Subsystem                Client             Subsystem

                                                     getResource()                                getResource()

                                                 allocates and
                                                 creates
                                                                 *
                                                        Resource                                      Cache
                                                                                                  acquire()
                                                                                                  release()

                                                                                                maintains

                                                                                                              *
                                                                                                    Resource




                           Page 111




                                 Optimize with Caching (2)


                                  Context
                                    Optimize access to reusable resources using caching
                                  Problem
                                    When a subsystem provides resources to other parties, resource
                                     access becomes a potential bottleneck
                                    If high usage frequency of the same resources leads to performance
                                     bottlenecks due to costs for resource creation, allocation, initialization,
                                     additional means of accelerating resource access are necessary
                                    How can we optimize resource access?
                                  General solution idea
                                    Introduce a fast cache where reusable resources are maintained
                                    Define an appropriate resource allocation (activation) and a de-
                                     allocation (eviction) strategy
                                    Provide a transparency layer to resource users




                           Page 112




© Dr. Michael Stal, 2010


                                                                                                                   56
Dr. Michael Stal: Architecture Refactoring




                                 Optimize with Caching (3)


                                  The choice of allocation / de-allocation strategy is important
                                  Example
                                    A web site that returns weather maps based on zip codes
                                    Suppose zip-based maps and weather data are stored in databases.
                                     When a new request arrives
                                      A servlet reads the map
                                      reads the weather data
                                      then uses image processing to calculate the map with weather
                                       information
                                      which it finally returns to the client
                                    When we introduce a cache, how do we decide which maps to store?
                                     Should we always remove the least frequently used maps? Or could we
                                     just store the "empty" map in the cache?
                                    How should we deal with updates (weather changes)? For example,
                                     can we introduce timeout values (leasing)?




                           Page 113




                                 Replace Singleton (first variant) (1)

                                 Example


                                                  Singleton                              MethodClass
                                               +m1();                                +m1();
                                               +m2();                                +m2();
                                               +m3();                                +m3();

                                               state




                                                                                            state
                                                                                             t t




                                       State is now a singleton, while behavior isn't
                                       In the end it's all about identity
                                       Known use: EJB Entity Beans

                           Page 114




© Dr. Michael Stal, 2010


                                                                                                           57
Dr. Michael Stal: Architecture Refactoring




                                 Replace Singleton (first variant) (2)


                                  Context
                                    Resources / objects with state that should be available at most once
                                  Problem
                                    Assume that a resource type (objects within a class, threads in a
                                     thread pool, …) that represents a particular state should only contain
                                     one single instance
                                    For this purpose, the Singleton Pattern is often applied
                                    Unfortunately, the Singleton pattern acts like a global declaration
                                    Are there any alternatives for our problem context?
                                  General solution idea
                                    In a singleton, state and behavior are integrated. The non-transient
                                     parts of the state represent the identity of the singleton object
                                    Thus, the singleton mustn't be replicated, as this would duplicate its
                                     identity
                                    Replace the singleton class with a class that provides the same public
                                     interface (value class), but store all the non-transient state in a central
                                     place (database, TSS, hash table, …) with the key known to the new
                                     class. The behavior and transient state, however, may be replicated

                           Page 115




                                 Replace Singleton (first variant) (3)


                                 Virtual Objects                              HalfObject1              HalfObject2
                                  The same concept is applicable to         se ce ()
                                                                             service1()               se ce ()
                                                                                                      service1()
                                   introduce operational qualities such      service2()               service3()
                                   as availability or fault-tolerance        protocol()               protocol()
                                   through replication
                                  In this case a number of objects
                                   provide the same services but store                       Half Objects
                                   their state in a central place
                                                                            Here                              There
                                  For clients all objects appear as
                                   one single (virtual) object                            local
                                  For state synchronization between
                                   physical objects (that represent the
                                   same virtual object), a protocol is
                                   required                                               remote
                                  Patterns to be applied:
                                    Half-Sync-Plus-Protocol
                                                                                                   Protoco
                                    Object Group
                                                                                                   l
                           Page 116




© Dr. Michael Stal, 2010


                                                                                                                      58
Dr. Michael Stal: Architecture Refactoring




                                 Replace Singleton (second variant)


                                  Another possible way to remove singletons is to introduce a wrapper,
                                   such as an object manager or factory
                                  The wrapper is in control of lifecycle management and thus able to
                                                               f f
                                   ensure that a specific type has only one instance

                                                                                                                     Singleton
                                              User                                                                   +m1();
                                                                                                                     +m2();
                                                                                                                     +m3();

                                                                                                                     state

                                           The wrapper ensures that at most
                                           one instance of the singleton is
                                           created. Note that a singleton                                 Wrapper
                                           might be removed and then
                                           reactivated, e.g., due to leasing.




                           Page 117




                                 Separate Synchronous and Asynchronous
                                 Processing (1)

                                 Example

                                                                       sy_svc_1        sy_svc_2     sy_svc_3




                                                                       as_svc_1        as_svc_2     as_svc_3




                                                   Synchronous Service Layer
                                                                                                     Async                          Sync
                                                                                                                     Queue
                                                 sy_svc_1      sy_svc_2     sy_svc_3                 Service                       Service

                                                                                              interrupt
                                                                                                               msg

                                                                                                           enqueue           notify
                                                            Queuing Layer


                                                                                                                         de-queue

                                                 as_svc_1       as_svc_2    as_svc_3                                         msg        work


                                                        interrupt

                                                  Asynchronous Service Layer



                           Page 118




© Dr. Michael Stal, 2010


                                                                                                                                               59
Dr. Michael Stal: Architecture Refactoring




                                 Separate Synchronous and Asynchronous
                                 Processing (2)


                                  Context
                                    Distributed systems that include a mixture of synchronous and
                                                   y                                  y
                                     asynchronous processing
                                  Problem
                                    Both asynchronous and synchronous services should be decoupled,
                                     so that neither suffers from the deficiencies of the other
                                    Both asynchronous and synchronous services should be able to
                                     communicate with one another efficiently using their own
                                     communication paradigm
                                    How can we refactor an architecture where synchronous and
                                     asynchronous services are tightly coupled?
                                  Solution
                                    Separate synchronous and asynchronous services from one another
                                     by dedicated layers and add a queuing layer between them to mediate
                                     communication between services
                                     (Half Sync / Half Async Pattern)

                           Page 119




                                 Replace Remote Methods with Messages (1)

                                 Example


                                           Client             C_Side_Proxy
                                                              C Side Proxy                    C_Side_Proxy
                                                                                              C Side Pro
                                           service_c()        service_s()                     service_s()

                                                              snd_request()                   snd_request()
                                                              rcv_response()                  rcv_response()
                                                                       *

                                                              Broker                               Queue
                                           Bridge                                Direct
                                                              est_connection()
                                                                                 connection        listen()
                                           est_connection()   find_server()
                                                                                                   enqueue()
                                           find_server()      register_svt()
                                                                                                   dequeue()
                                                              unregister_svt()


                                                                       *
                                           Servant            S_Side_Proxy                    S_Side_Proxy
                                           service_s()        rcv_request()                   rcv_request()
                                                              snd_response()                  snd_response()




                           Page 120




© Dr. Michael Stal, 2010


                                                                                                               60
Dr. Michael Stal: Architecture Refactoring




                                 Replace Remote Methods with Messages (2)


                                  Context
                                    Asynchronous problem using synchronous remote methods
                                  Problem
                                    In many distributed systems remote method invocation is the primary
                                     choice of communication. Asynchronicity is often introduced in the
                                     application layer, but implemented on top of remote methods
                                    However, message-oriented middleware is often the better choice for
                                     dealing with event-based or asynchronous communication
                                    Is there a migration path to move from synchronous to asynchronous
                                     communication without huge impact?
                                  General solution idea
                                    Keep the Broker-based architecture unchanged but integrate an
                                     additional asynchronous layer that relies on messaging middleware
                                    For synchronous communication, still use the synchronous layer
                                    For asynchronous communication, use the asynchronous layer instead
                                     (message queues, asynchronous completion tokens, …)
                                    Future functionality may then directly rely on asynchronous
                                     messaging
                           Page 121




                                 Add Object Manager (1)

                                 Example



                                      Client       Factory              Object Manager      Client

                                                   create()             createObject()
                                                   delete()             deleteObject()
                                                   find()               insertObject()
                                                                        removeObject()
                                                                        findObject()
                                                                        objectIterator()


                                                   Object

                                                                                    *
                                                   service()            ManagedObject
                                                                        service()




                           Page 122




© Dr. Michael Stal, 2010


                                                                                                           61
Dr. Michael Stal: Architecture Refactoring




                                 Add Object Manager (2)


                                  Context
                                    Management support for objects
                                  Problem
                                    Objects (and resources) for client usage often need to implement
                                     management functionality in addition to business logic, e.g., lifecycle
                                     management, persistence management
                                    This burden leads to memory usage and responsibility overload
                                    Clients shouldn't be responsible for object management either
                                    Different applications may require different management policies
                                    How can we provide such additional management?
                                  General solution idea
                                    Separate object usage from object management
                                    Introduce an manager component that manages objects throughout
                                     their lifetime


                           Page 123




                                 Change Unidirectional Association to Bidirectional (1)
                                 (Fowler)

                                 Example

                                                             Order                       Order

                                                                  *                           *


                                                                  1                           1
                                                          Customer                    Customer


                                            class Order...                     class Customer...
                                            Customer getCustomer() {           private Set _orders = new HashSet;
                                             return _customer;                 void addOrder(Order arg) {
                                            }                                    arg.SetCustomer(this);
                                            void setCustomer(Customer arg) {   }
                                             _customer = arg;                  Set friendOrders() {
                                            }                                   return _orders;
                                            Customer customer;                 }

                                                                               class Order...
                                                                               void setCustomer(Customer arg) {
                                                                                _if (_customer != NULL)
                                                                                 customer.friendOrders().add(this);
                                                                               }




                           Page 124




© Dr. Michael Stal, 2010


                                                                                                                      62
Dr. Michael Stal: Architecture Refactoring




                                 Change Unidirectional Association to Bidirectional
                                 (2) (Fowler)


                                  Context
                                    Two classes referring to each other
                                  Problem
                                    Class A refers to a class B, but there is no backward navigation from B
                                     to A
                                    However, after some development activities, you recognize that B also
                                     requires a reference to all A objects referring to it
                                    How can we transform the unidirectional to a bidirectional navigation?
                                  General solution idea
                                    Add a back link in class B that allows navigation from B to the referring
                                     A object(s)
                                    Decide which class is in charge of controlling the association, e.g.
                                      The composite controls its constituents
                                      In one-to-many relationships, make the one-side (i.e., side with
                                        multiplicity of one) the controller
                                    Introduce helper method in the non-controlling side
                                    If the existing modifier is on the controlling side, modify it to update
                                     back references, otherwise create a controlling method on the
                                     controlling side and call it from the existing modifier
                           Page 125




                                 Refactoring

                                 References




                           Page 126




© Dr. Michael Stal, 2010


                                                                                                                 63
Dr. Michael Stal: Architecture Refactoring




                                 Refactoring

                                 References


                                  Fowler Martin et al. 1999. Refactoring: Improving
                                   Fowler,          al 1999
                                   the Design of Existing Code. Addison-Wesley

                                  Demeyer, S; Ducasse, S; Nierstrasz, O. 2002.
                                   Object-Oriented Reengineering Patterns. Morgan
                                   Kaufmann

                                  Kerievsky, Joshua. 2004. Refactoring to Patterns.
                                   Addison-Wesley

                                  Ambler, Scott W.; Sadalage, Pramodkumar J, 2006.
                                   Refactoring Databases: Evolutionary Database
                                   Design. Addison-Wesley

                                  Thanks to Dr. Michael Stal for his permission to use
                                   his material in this presentation


                           Page 127




© Dr. Michael Stal, 2010


                                                                                          64

Accu2010 archrefactoring

  • 1.
    Dr. Michael Stal:Architecture Refactoring Architecture Refactoring – Motivation, Approach and Patterns accu 2010 Dr. Michael Stal Panta rhei There is nothing permanent except change [Heraclitus, 535–475 BC] Page 2 © Dr. Michael Stal, 2010 1
  • 2.
    Dr. Michael Stal:Architecture Refactoring Refactoring Learning objectives  Understand about design erosion and how to avoid it  Learn about the principles of refactoring  Know about activities and best practices necessary for refactoring  Understand how reengineering and rewriting differ from refactoring Page 3 Refactoring Agenda  Motivation and foundation  Refactoring  Reengineering  Rewriting  Comparison  Summary Page 4 © Dr. Michael Stal, 2010 2
  • 3.
    Dr. Michael Stal:Architecture Refactoring Design erosion is the root of all evil  In the lifecycle of a software system Detached Extensions changes A A Backpack Backpack Backpack are the rule and not the exception p Another  New requirements or increments imply Backpack modifications or extensions  Engineers must adopt their solutions to A Someone Component Else's Comp new technologies  Changes in business force changes in IT Another The Fifth  Bug fixes require patches or local Component Element corrections  Unsystematic approaches ( workarounds ) ("workarounds") Yet Another Component cure the symptom but not the problem Component 42  After applying several workarounds, software systems often suffer from design DB Spaghetti erosion Access Layer design  Such systems are doomed to fail as work- DB access arounds have a negative impact on opera- shortcut tional and developmental properties Page 5 Refactoring is part of the architecture design process Feedback Loop Refine & Assess Refactor Refactoring is integrated into Architecture Architecture the iterative-incremental architecture design process:  It improves the structure  It supports a risk-, t i k Executable no Complete yes requirements- and test- Increment ? driven approach Page 6 © Dr. Michael Stal, 2010 3
  • 4.
    Dr. Michael Stal:Architecture Refactoring Yes, but was is it?  "Code refactoring is the process of changing a software system g g y Note: external interfaces remain unchanged! i h d! in such a way that it does not alter the external behavior of the code yet improves its internal structure" [Martin Fowler]  Put more generally: Refactoring is the process of changing a software system or process in such a way that it does not alter the external behavior, yet improves its internal structure Page 7 Why should we refactor?  Architecture refactoring needs to achieve quality improvement in terms of  structural as well as  non-functional qualities  Structural quality indicators include:  Economy  Visibility  Spacing  Symmetry  Emergence  Consequently, the goal of architecture refactoring is to achieve or improve such qualities Page 8 © Dr. Michael Stal, 2010 4
  • 5.
    Dr. Michael Stal:Architecture Refactoring Refactoring Agenda  Motivation and foundation  Refactoring  Reengineering  Rewriting  Comparison  Summary Page 9 Code refactoring  According to Martin Fowler, code  Reasons to use refactoring refactoring is  Design improvement and  … the process of changing a maintenance software system in such a way  Better readability that it does not alter the external  Bugs behavior of the code yet  It is the third step in TDD improves its internal structure  … a disciplined way to clean up code that minimizes the  The Rules of Three chances of introducing bugs  Refactor before adding new functionality, e.g., when structure prevents simple t t t i l additions  Refactor when fixing bugs  Refactor after code reviews to apply improvements Page 10 © Dr. Michael Stal, 2010 5
  • 6.
    Dr. Michael Stal:Architecture Refactoring Code smells  Kent Beck's grandmother's saying: y g "If it stinks, change it"  Thus, identify bad smells such as  Code that is duplicated  Methods that span several dozen lines  Subclasses introducing the same method  Usage of temporary variables  Usage of switch statements  Introduction of a "middleman" Page 11 Code Refactoring Example: Extract Method  Make code fragment a method of its own void printFormatted(string text) { System.out.println("Copyright (c) 2008, Siemens AG"); System.out.println("Author: Michael Stal"); printRest(text); } void printFormatted(string text) { printHeader(); i tH d () printRest(text); } printHeader() { System.out.println("Copyright (c) 2008, Siemens AG"); System.out.println("Author: Michael Stal"); } Page 12 © Dr. Michael Stal, 2010 6
  • 7.
    Dr. Michael Stal:Architecture Refactoring Refactoring to patterns  Refactoring to patterns was introduced by Joshua Kerievsky y y  General idea: Patterns might give guidance how to refactor on the architectural level  Replace your proprietary solution with a pattern that solves the same problem  Kerievsky's book focuses on design patterns  Introduce symmetry by making  However, we could also sure the same problem is apply the same principle always solved using the same to architecture patterns pattern / solution  In the latter case, we'll obtain  This represents a precursor of architecture refactorings software architecture refactoring Page 13 Replace hard-coded notifications with Observer [Joshua Kerievsky] Do it yourself Observer Pattern Subject EventSink Subject * Observer * update state update state observerList doSomething observerList attach Dynamic notify detach Wiring ConcreteObserver setData notify getData setData update getData doSomething state = X; Subject notify(); contains hardwired list s->getData() of interested for all observers in observerList do components update(); Page 14 © Dr. Michael Stal, 2010 7
  • 8.
    Dr. Michael Stal:Architecture Refactoring Architecture refactoring  Architecture refactoring is about Architecture smells the semantic-preserving  Duplicate design artifacts transformation of a software t f ti f ft  Unclear roles of entities design  Inexpressive or complex  It changes structure but not architecture behavior  Everything centralized  It applies to architecture-relevant  Home-grown solutions instead of design artifacts such as UML best practices diagrams, models, DSL  Over-generic design expressions, aspects  Asymmetric structure or behavior  Its goal is to improve quality. You  Dependency cycles got a "smell"? Use an architecture  Design violations (such as relaxed refactoring instead of strict layering) pattern to solve it!  Inadequate partitioning of functionality  Unnecessary dependencies  Missing orthogonality Page 15 Remove unnecessary abstractions (1) Transport * Abstract Abstract A true story: In Way y Storage g Strategy gy * this example * architects Equip- Composite Concrete Dump Door Bin introduced ment Storage Strategy * Transport Way as an additional abstraction. But Cart Belt can't we consider transport ways as just as another kind of storage? As a consequence Abstract Abstract the unnecessary Storage Strategy abstraction was * * removed, leading Composite Concrete to a simpler and Equipment Dump Door Bin Storage Strategy cleaner design. Page 16 © Dr. Michael Stal, 2010 8
  • 9.
    Dr. Michael Stal:Architecture Refactoring Remove unnecessary abstractions (2)  Context  Eliminating unnecessary design abstractions g y g  Problem  Minimalism is an important goal of software architecture, because minimalism increases simplicity and expressiveness  If the software architecture comprises abstractions that could also be considered abstractions derived from other abstractions, then it is better to remove these abstractions  General solution idea  Determine whether abstractions / design artifacts exist that could also be derived from other abstractions  If this is the case, remove superfluous abstractions and derive dependent from other existing abstractions  Caveat  Don't generalize too much (such as introducing one single hierarchy level: "All classes are directly derived from Object") Page 17 Break dependency cycles (1) GetState() GetState() In this example, SetState { SetState { the monitor ... ... M.GetDate() D.GetDate() invokes the state } } getter / setter methods but also Sensor Sensor GetDate() provides GetDate() to the sensor, lea- ding to a simple X Break Cycle Date dependency cycle. Providing this me- thod to monitors Monitor Monitor was a bad design decision, anyway. Draw() { Introducing a GetDate() Draw() { ... separate date S.GetState(); ... object solves the S.GetState(); } problem. } Page 18 © Dr. Michael Stal, 2010 9
  • 10.
    Dr. Michael Stal:Architecture Refactoring Break dependency cycles (2)  Context  Dependencies between subsystems  Problem  Your system reveals at least one dependency cycle between subsystems  Subsystem A may either depend directly or indirectly on subsystem B (e.g., A depends on C which depends on B) which is why we always need to consider the transitive hull  Dependency cycles make systems less maintainable, changeable, reusable, testable, understandable  Thus, dependency hierarchies should form DAGs (directed acyclic graphs)  General solution idea  Get rid of the dependency cycle by removing one of the dependencies Page 19 Merge Subsystems (1) Example: While tight coupling between subsystems is bad, high cohesion within subsystems is good. Thus, merge tightly coupled subsystems to form a highly cohesive subsystem . Sensor Sensor + Utilities Utilities Special variant: Merge a layer in a layered system Page 20 © Dr. Michael Stal, 2010 10
  • 11.
    Dr. Michael Stal:Architecture Refactoring Merge Subsystems (2)  Context  Coupling between subsystems  Problem  Between two subsystems in a software architecture the degree of coupling should be rather loose  Within a subsystem the number of interdependencies (cohesion) should be high  If the coupling is too tight, then the many interdependencies between these two subsystems decrease qualities such as  Changeability  Performance (maybe)  Reusability of one of the subsystems  General solution idea  Tight coupling between subsystems implies that the two subsystems in fact implement one subsystem  Either merge both subsystems to form one, or  Move functionality from one subsystem to the other Page 21 Split Subsystems (1) Example: When analyzing interdependencies between entities in a subsystem, two (or more) sets can be determined. Within these sets there is high cohesion; between these sets there is only low cohesion. Thus, split the subsystem into two (or more) parts. Component Container High Cohesion Lifecycle Persistence Event Handling Management Component Container Communication Communi- cation Special variant: Split layer in a layered system Page 22 © Dr. Michael Stal, 2010 11
  • 12.
    Dr. Michael Stal:Architecture Refactoring Split Subsystems (2)  Context  Cohesion within a subsystem  Problem  Within a subsystem the interdependencies (cohesion) should be high  Between two subsystems in a software architecture, the degree of coupling should be rather loose  If the cohesion between some parts is loose, then some design decisions seem to be questionable  It is recommendable to change this to obtain better modularization and understandability  Another potential problem are subsystems/components with too many responsibilities  General solution idea  Loose cohesion within a subsystem implies that the functionality can be split into multiple subsystems  Thus, determine areas with high cohesion in a subsystem. All those areas with low cohesion are candidates for becoming subsystems of their own Page 23 Move Entities (1) Example y z y z x x Game Game getPlayerHistory(p) getPlayerHistory() Player Player Page 24 © Dr. Michael Stal, 2010 12
  • 13.
    Dr. Michael Stal:Architecture Refactoring Move Entities (2)  Context  Moving entities between subsystems  Problem  This can be considered a generalization of the Split Subsystem refactoring  In a subsystem an entity is defined that fits better semantically in another subsystem to which it has high coupling  General solution idea  Again, we should consider cohesion and coupling  If entity e reveals low or zero cohesion to the rest of its subsystem A, but tight coupling to subsystem B, then move e from A to B  Note: This may also help with breaking dependency cycles between subsystems Page 25 Move Entities (3) Some additional issues  In many cases we can t apply the refactoring to single atomic entities cases, can't such as a class, method, constant, interface  It is more likely that there will be clusters of atomic entities that together build a complex entity  In the example, it is very likely that there will be classes and interfaces related to the method to be moved  Thus, always consider semantically related entities with high internal y y g cohesion but less cohesion to the rest of their subsystem. If some of them show tight coupling to another subsystem, move the whole group  Moving may not always be a simple operation, but imply several smaller grained transformations (see example) Page 26 © Dr. Michael Stal, 2010 13
  • 14.
    Dr. Michael Stal:Architecture Refactoring Reduce Dependencies with Facades (1) Example 1.3 Rental Car Bookingg 1.2 Hotel Client Booking Flight 1.1 Booking 2.3 Rental Car Booking B ki Facade 1 2.2 Hotel Client Travel Booking Booking Flight 2.1 Booking Page 27 Reduce Dependencies with Facades (2)  Context  Client implements workflows that mostly access other components  Problem  If a client needs to access different external components for each workflow, it becomes dependent on details such as the set of available components  As soon as the configuration and / or interfaces of these components change, there will be a direct impact on the client  General solution idea  Introduce a Facade component that acts as the client's gateway into the set of required components  Implement workflow methods within the facade that represent the different p p workflows  The facade methods take over the responsibility for accessing the set of required components on behalf of the client, thus decoupling the client from the components  If components are remote, performance is also improved (Session Facade) Page 28 © Dr. Michael Stal, 2010 14
  • 15.
    Dr. Michael Stal:Architecture Refactoring Substitute Mediation with Adaptation (1) Example I_have no_clue_sub_1 no clue sub 1 I_have I_have A B C no_clue_sub2 no_clue_sub_3 Adapter Adapter Adapter Do_Everything_ Class Integration Layer a.k.a. Mediator Adapter Adapter Adapter I_have I_have no_clue_sub_4 no_clue_sub_5 D E F I_have no_clue_sub_6 Page 29 Substitute Mediation with Adaptation (2)  Context  Centralized system using a mediation level between peers  Problem  When interaction between different peers is complex, a mediator may be the right solution  However, extensive use of mediator may reduce scalability  If mediation was just applied to build an extremely generic solution, design erosion is often the price  How can we improve this situation?  General solution idea  Introduce adapters to uniformly plug in peers  But make interaction explicit, i.e. subsystems themselves are in charge to interact with the appropriate peers using an integration layer  Known use: Enterprise Application Integration (Hub and Spoke) => Enterprise Service Bus Page 30 © Dr. Michael Stal, 2010 15
  • 16.
    Dr. Michael Stal:Architecture Refactoring Add Uniform Support for Runtime Aspects (1) Subsys UI Subsys UI IUIAdmin IAdmin Subsys DB Subsys DB IDBAdmin IAdmin Subsys ATM Subsys ATM IATMAdmin IAdmin Management Console Page 31 Add Uniform Support for Runtime Aspects (2)  Context  Software architecture that must support runtime aspects such as lifecycle management, management, configuration f f  Problem  Each non-trivial software architecture consists of multiple components, each of which supports common aspects  If every component implements its own interfaces for runtime aspects, the overall system will lack simplicity and expressiveness  Is there a way to provide a uniform approach to support those kinds of runtime aspects?  General solution idea  For each aspect, define a common interface (e.g., an interface for runtime configuration)  In each component supporting the aspect, provide this common interface (maybe using Extension Interfaces to prevent bloating)  To achieve orthogonality, provide one runtime component that is in charge of accessing these common interfaces (e.g., a management console) Page 32 © Dr. Michael Stal, 2010 16
  • 17.
    Dr. Michael Stal:Architecture Refactoring Add Configuration Subsystem (1) Example Actor Subsystem UI Subsystem UI IConfig1 IConfig Configuration Subsystem DB Configuration Subsystem DB Actor IConfig2 Subsystem IConfig Subsystem ATM Subsystem ATM IConfig3 IConfig  Use patterns such as Component Configurator for this purpose Page 33 Add Configuration Subsystem (2)  Context  A system with many configurable variabilities  Problem  If a system contains a lot of configuration options, then configuration itself is often tedious and error-prone  This holds in particular when the configuration options are (partially) related to each other  How can we refactor the software system so that configuration is simplified and (partially) automated?  General solution idea  Instead of providing dozens of configuration options to external actors, we introduce a configuration subsystem that takes a declarative configuration (from a file or a wizard)  The configuration subsystem reacts to configuration change events, reads the passed configuration, and then accesses the configuration interfaces of configurable subsystems  Ideally, all subsystems provide the same generic configuration interface Page 34 © Dr. Michael Stal, 2010 17
  • 18.
    Dr. Michael Stal:Architecture Refactoring Where to obtain architecture refactorings? A whole catalog of architecture refactorings is provided as a starting point i t 1. Rename Entities 17. Enforce Contract 18. Provide Extension Interfaces 2. Remove Duplicates 19. Substitute Inheritance with Delegation 3. Introduce Abstraction Hierarchies 20. Provide Interoperability Layers 4. Remove Unncessary Abstractions 21. Aspectify 5. Substitute Mediation with Adaptation 22. Integrate DSLs 6. Break Dependency Cycles 23. Add Uniform Support to Runtime Aspects 24. Add Configuration Subsystem 7. Inject Dependencies 25. Introduce the Open/Close Principle 8. Insert Transparency Layer 26. Optimize with Caching 9. Reduce Dependencies with Facades p 27. Replace Singleton 10. Merge Subsystems 28. Separate Synchronous and Asynchronous Processing 11. Split Subsystems 29. Replace Remote Methods with Messages 12. Enforce Strict Layering 30. Add Object Manager 13. Move Entities 31. Change Unidirectional Association to Bidirectional 14. Add Strategies 15. Enforce Symmetry 16. Extract Interface Page 35 Checking correctness  To check the correctness of refactorings, we use the test-driven approach that we introduced.  Available options:  Formal approach: Prove semantics and correctness of program transformation  Implementation approach: Leverage unit and regression tests to verify that the resulting implementation still meets the specification  Architect re analysis: Check the resulting Architecture anal sis res lting software architecture for its equivalence with the initial architecture (consider requirements) – see also CQM methods and tools  Use at least the latter two methods to ensure quality Page 36 © Dr. Michael Stal, 2010 18
  • 19.
    Dr. Michael Stal:Architecture Refactoring Refactoring – responsibilities and communication The process of refactoring requires communication with testers and developers Product Lifecycle Manager SW Project Manager  Control product development  Define detailed project plans across lifecycles  Assign resources Requirements Engineer  Review system architecture Detailed project documents planning Head of R&D SW Design  Control SW Testability y process  Act as escalation Software Architect point  Analyze architecture smells Software Developer  Identify appropriate software  Identify code Test Manager architecture refactorings e.g., using smells  Review product architecture refactoring catalogs  Apply code  Refine master test plan  Apply software architecture refactorings  Set up test strategy for integration and refactorings system test  Verify correctness of refactorings  Define test environment  Be involved in design reviews  Define verification and validation  Leverage CQM tools procedure Page 37 Application of architecture refactorings  The usage of a concrete application refactoring should never happen in an ad-hoc, unsystematic way. I t d dh t ti Instead, the architect's role is to  Check the applicability of refactorings  Would the refactoring affect parts that need to remain unchanged, such as integration of third-party APIs?  Could the refactoring impact require- ments in a negative way?  Define the order of refactoring  Strategic before tactical aspects  Requirement priorities drive order!  Apply the refactorings  Ensure the quality of the software architecture after the refactoring (in conjunction with the test manager) Page 38 © Dr. Michael Stal, 2010 19
  • 20.
    Dr. Michael Stal:Architecture Refactoring Obstacles to refactoring (1)  Organization / management  Considering improvement by refactoring as less important than providing new p p g features  Ignorance of refactoring necessity typically causes design erosion  “Organization drives architecture” problem  Process support  No steps / activities defined in process for architecture refactoring: Refactoring should be addressed explicitly in the h ld b dd d li itl i th process; responsibilities must be assigned to different roles  Refactorings are not checked for correctness, test manager not involved: Architects should work hand in hand with test manager and leverage means such as tests, architecture reviews Page 39 Obstacles to refactoring (2)  Technologies and tools  Unavailability of tools: Refactoring must be done manually, which can be tedious y, and error-prone  Unavailability of refactoring catalog: It is important to collect refactorings and document them  Applicability  Refactoring used instead of reengineering, and vice versa  Wrong order of refactorings: Should be determined by requirements priority and d t i db i t i it d relevance Page 40 © Dr. Michael Stal, 2010 20
  • 21.
    Dr. Michael Stal:Architecture Refactoring Refactoring Agenda  Motivation and foundation  Refactoring  Reengineering  Rewriting  Comparison  Summary Page 41 Reengineering – how it differs from refactoring  Scope: Reengineering always affects the entire system; refactoring has typically f t i h t i ll (many) local effects  Process: Reengineering follows a disassembly / reassembly approach; refactoring is a behavior- preserving, structure transforming process  Result: Reengineering can create a whole new system – with different structure, behavior, and functionality; refactoring improves the structure of an existing system – leaving its behavior and functionality unchanged Page 42 © Dr. Michael Stal, 2010 21
  • 22.
    Dr. Michael Stal:Architecture Refactoring Reengineering – when and how to use it  Use reengineering when  Process  Phase I: Reverse engineering g g  The system s documentation system's  Analysis / recovery: determine is missing or obsolete existing architecture (consider  The team has only limited using CQM) understanding of the  SWOT analysis system, its architecture, and  Decisions: what to keep, what implementation to change or throw away  Phase II: Forward engineering  A bug fix in one place causes bugs in other places Reverse Forward engineering engineering  New system-level require- Requirements ments and functions cannot Conference Organizer uses Conference Manager * uses manages Scheduler Telegram Forwarder Telegram Receiver The network organizes be addressed or integrated Media passes telegrams to participates Conference uses Manager passes telegrams to Telegram Design Converter Conference Participant * has applies passes Conference * Command Logging Documents Logger commands to Session Processor Strategy executes Log Command Alarms creates Pick SetPoint W orkpiece Calculation appropriately Code Page 43 Refactoring Agenda  Motivation and foundation  Refactoring  Reengineering  Rewriting  Comparison  Summary Page 44 © Dr. Michael Stal, 2010 22
  • 23.
    Dr. Michael Stal:Architecture Refactoring Rewriting in a Nutshell Rewriting is a radical and fresh restart: existing design and code is trashed and replaced by a whole new design and implementation. Depending on focus:  Improves structure regarding:  Simplicity, visibility, spacing, symmetry, emergence  Maintainability, readability, extensibility  Bug fixing  Provides new functionality  Improves its operational qualities p p q  Improves design and code stability As a consequence, rewriting addresses all types of software quality: functional, operational, and the various developmental qualities. Page 45 Learning from failure Failure and understanding failure is a key factor for successful design! [Henry Petroski] Before you’re going to rewrite, check what went wrong in the project that developed the previous application Page 46 © Dr. Michael Stal, 2010 23
  • 24.
    Dr. Michael Stal:Architecture Refactoring Refactoring Agenda  Motivation and foundation  Refactoring  Reengineering  Rewriting  Comparison  Summary Page 47 Refactoring, reengineering, and rewriting comparison (1) Refactoring, reengineering, and rewriting are complementary approaches to sustain architecture and code quality  Start with refactoring – it is cheap and (mostly) under the radar  Consider reengineering when refactoring does not help – but it is expensive  Consider rewriting when reengineering does not help – but it is expensive and often risky Command Processor Strategy Reverse Forward Command Logging Client engineering engineering Processor Strategy Concrete Requirements q Logging Strategy Command & Composite uses uses Conference Scheduler The network Manager Telegram Telegram Conference Organizer * organizes participates manages Conference uses Media Forwarder Receiver passes telegrams to passes telegrams to Command Memento Design * Manager Telegram Conference Converter Participant * has applies passes Conference * Command Logging Documents Logger commands to Session Processor Strategy executes Log Command Alarms creates Pick SetPoint Workpiece Calculation Memento Concrete Composite Command Command Code Application Page 48 © Dr. Michael Stal, 2010 24
  • 25.
    Dr. Michael Stal:Architecture Refactoring Refactoring, reengineering, and rewriting comparison (2) Refactoring Reengineering Rewriting Scope  Many local effects  Systemic effect  Systemic or local effect Process  Structure transforming  Disassembly / reassambly  Replacement  Behavior / semantics preserving Results  Improved structure  New system  New system or new  Identical behavior component Improved  Developmental  Functional  Functional qualities  Operational  Operational  Developmental  Developmental Drivers  Complicated design / code  Refactoring is insufficient  Refactoring and evolution  Bug fixes cause rippling effect reengineering are insufficient  Wh fi i b When fixing bugs  New functional and or inappropriate  When design and code smell operational requirements  Unstable code and design bad  Changed business case  New functional and operational requirements  Changed business case  Part of daily work  Requires a dedicated project  Requires dedicated effort or a  At the end of each iteration dedicated project, depending When  Dedicated refactoring on scope iterations in response to reviews Page 49  It is the 3rd step of TDD Refactoring Agenda  Motivation and foundation  Refactoring  Reengineering  Rewriting  Comparison  Summary Page 50 © Dr. Michael Stal, 2010 25
  • 26.
    Dr. Michael Stal:Architecture Refactoring What we learned  Refactoring changes artifacts without changing external behavior. It helps with quality improvement and necessary changes d h  In contrast, reengineering is a complete redesign of a complete architecture and typically changes external behavior  If reengineering is not appropriate, it is often the best alternative to rewrite a system or its parts  All methods are essential. Use the right one for the right purpose  Testing and architecture introspections are important when refactoring, reengineering, i t t h f t i i i rewriting  You as a software architect are responsible to  Detect architecture smells  Find and apply appropriate refactorings  Perform QA of refactoring activities Page 51 A departing thought Each problem that I solved became a rule which served afterwards to solve other problems. [René Descartes, 1596–1650, in "Discours de la Methode"] Page 52 © Dr. Michael Stal, 2010 26
  • 27.
    Dr. Michael Stal:Architecture Refactoring Backup Backup Page 53 Rename Entities (1) Example Comp ShareTicker AnotherComp ShareObserver Page 54 © Dr. Michael Stal, 2010 27
  • 28.
    Dr. Michael Stal:Architecture Refactoring Rename Entities (2)  Context  Using non intuitive names non-intuitive  Problem  Your software architecture contains entities named in such a way that the whole architecture lacks expressiveness  General solution idea  Introduce intuitive names so that stakeholders can easily understand the role of each subsystem  Change the names of the entities and also consider references to these entities  Change only one entity name at a time  Use one predefined naming scheme / strategy throughout the project Page 55 Remove Duplicates (1) Example Extract: call locateBean(X) Client A Extract: Client A' main() {  Connect JNDI main() { ... ... }  Get Home }  Locate bean X Bean 1. Connect JNDI Location 2. Get Home Component 3. Locate bean Client B Extract: Client B' main() {  Connect JNDI main() { ... ... }  Get Home }  Locate bean Y Extract: call locateBean(Y) Page 56 © Dr. Michael Stal, 2010 28
  • 29.
    Dr. Michael Stal:Architecture Refactoring Remove Duplicates (2)  Context  Equivalent design artifacts are replicated throughout the q g p g architecture  Problem  DRY (Don't Repeat Yourself) is an essential means to increase simplicity, expressiveness, orthogonality and reuse  On the other hand, if the same design artifacts are repeatedly implemented and used in a software architecture, then manageability and productivity will suffer  How can we prevent the introduction of equivalent design artifacts?  General solution idea  Identify common (sequences of) tasks or sequences of tasks repeatedly used throughout your software system  Analyze whether these common (sequences of tasks) can be provided as a generic component  If that's the case, remove duplicates and introduce one common design artifact instead Page 57 Introduce Abstraction Hierarchies (1) Example: Class hierarchy Window Wi d Window Wi d display() display() Panel Panel display() drawPixel() drawPixel() Button Button display() onClick() drawPixel() onClick() Separate Related abstractions abstractions "is-a" relation Page 58 © Dr. Michael Stal, 2010 29
  • 30.
    Dr. Michael Stal:Architecture Refactoring Introduce Abstraction Hierarchies (2)  Context  Entities representing related concepts p g p  Problem  In the architecture design entities appear that implement almost the same functionality  This leads to design and code replication, as well as to less expressiveness and simplicity  General solution idea  Leverage the Liskov Substitution Principle  Introduce general abstractions containing the common parts of these entities  Define hierarchy of abstractions  Derive entities from the most specific abstraction  Different possibilities  Adding superclass  Adding common interfaces Page 59 Remove Unnecessary Abstractions (1) Example Transport * Abstract Abstract Way Storage Strategy * * Equip- Composite Concrete Dump Door Bin ment Storage Strategy * Cart Belt Abstract Abstract Storage Strategy * * Composite Concrete Equipment Dump Door Bin Storage Strategy Page 60 © Dr. Michael Stal, 2010 30
  • 31.
    Dr. Michael Stal:Architecture Refactoring Remove Unnecessary Abstractions (2)  Context  Eliminating unnecessary design abstractions  Problem  Minimalism is an important goal of software architecture, because minimalism increases simplicity and expressiveness  If the software architecture comprises abstractions that could also be considered abstractions derived from other abstractions, then it is better to remove these abstractions  General solution idea  Determine whether abstractions / design artifacts exist that could also be derived from other abstractions  If this is the case,  remove superfluous abstractions;  derive entities that depend from removed abstractions to derive from abstractions being left  Challenge: Don't generalize too much (such as introducing one single hierarchy level: "All classes are directly derived from Object") Page 61 Substitute Mediation with Adaptation (1) Example I_have no_clue_sub_1 no clue sub 1 I_have I_have A B C no_clue_sub2 no_clue_sub_3 Adapter Adapter Adapter Do_Everything_ Class Integration Layer a.k.a. Mediator Adapter Adapter Adapter I_have I_have no_clue_sub_4 no_clue_sub_5 D E F I_have no_clue_sub_6 Page 62 © Dr. Michael Stal, 2010 31
  • 32.
    Dr. Michael Stal:Architecture Refactoring Substitute Mediation with Adaptation (2)  Context  Centralized system using a mediation level between peers  Problem  When interaction between different peers is complex, a mediator may be the right solution  However, extensive use of mediator may reduce scalability  If mediation was just applied to build an extremely generic solution, design erosion is often the price  How can we improve this situation?  General solution idea  Introduce adapters to uniformly plug in peers  But make interaction explicit, i.e. subsystems themselves are in charge to interact with the appropriate peers using an integration layer  Known use: Enterprise Application Integration (Hub and Spoke) => Enterprise Service Bus Page 63 Break dependency cycles (1) GetState() GetState() In this example, SetState { SetState { the monitor ... ... M.GetDate() D.GetDate() invokes the state } } getter / setter methods but also Sensor Sensor GetDate() provides GetDate() to the sensor, lea- ding to a simple X Break Cycle Date dependency cycle. Providing this me- thod to monitors Monitor Monitor was a bad design decision, anyway. Draw() { Introducing a GetDate() Draw() { ... sepa-rate date S.GetState(); ... object solves the S.GetState(); } problem. } Page 64 © Dr. Michael Stal, 2010 32
  • 33.
    Dr. Michael Stal:Architecture Refactoring Break dependency cycles (2)  Context  Dependencies between subsystems  Problem  Your system reveals at least one dependency cycle between subsystems  Subsystem A may either depend directly or indirectly on subsystem B (e.g., A depends on C which depends on B) which is why we always need to consider the transitive hull  Dependency cycles make systems less maintainable, changeable, reusable, testable, understandable  Thus, dependency hierarchies should form DAGs (directed acyclic graphs)  General solution idea  Get rid of the dependency cycle by removing one of the dependencies Page 65 Break dependency cycles – Dependency Inversion interface IObserver { Handle() } Attach(Observer) Attach(IObserver) Notify( Notify( Dependency inver- observer.Handle(); iObserver.Handle(); sion constitutes ) ) another variant Subject' Subject Observer' Observer Handle() class Obs implements IObserver { StartUp() { Handle() { ...} } subj.Attach(obs); StartUp( ) subj.Attach(obs); ) Page 66 © Dr. Michael Stal, 2010 33
  • 34.
    Dr. Michael Stal:Architecture Refactoring Inject Dependencies (1) Example Component c { Component c { S s = new S(.....); inject(S p){ s=p;} s.m(); s.m(); } } Component c Component c Component s Container m Component s C c = new C(); S.S = new S(.....); c.inject(s); Page 67 Inject Dependencies (2)  Context  Components that need to create and use other components  Problem  If a component c needs access to other components, it most somehow create these components or locate them  However, this makes c too dependent on the knowledge about specific component location or factory mechanisms  How can we avoid these additional dependencies?  General solution idea  Move functionality for discovery and creation of components to separate component m  Introduce configuration to let component c specify its requirements and let m be responsible for creating, discovering and then injecting required component references to c Page 68 © Dr. Michael Stal, 2010 34
  • 35.
    Dr. Michael Stal:Architecture Refactoring Insert Transparency Layer (1) Example Subsystem B Subsystem B TRANSPARENCY Client Client LAYER Page 69 Insert Transparency Layer (2)  Context  Decoupling clients or from subsystems and vice-versa  P bl Problem  When a client accesses subsystems directly, some dependencies are introduced, e.g.,  On the exact physical location of the subsystems, or  On specific data or document formats the subsystem expects  The client must have knowledge about how to locate and access the subsystems  Finally, the client also becomes dependent on subsystem implementation aspects  General solution idea  To avoid such dependencies, we introduce transparency layers to decouple these dependencies from clients  Transparency layers also open additional optimization possibilities  This is basically a whole class of architecture refactorings, because for the implementation of transparency layers we rely on patterns such as Proxy, Facade, Wrapper-Facade, Business Delegate, Service Locator, Proxy Page 70 © Dr. Michael Stal, 2010 35
  • 36.
    Dr. Michael Stal:Architecture Refactoring Example: Introducing Protection Layers  Typically, an architectural entity depends directly on other architectural entities Client  This becomes a problem when the target of the p g dependency is subject to change (volatility)  In this case add a layer to protect your entity from directly depending on a volatile entity  Note: this decreases inter-component coupling Protection Layer Server Page 71 Reduce Dependencies with Facades (1) Example 1.3 Rental Car Bookingg 1.2 Hotel Client Booking Flight 1.1 Booking 2.3 Rental Car Booking B ki Facade 1 2.2 Hotel Client Travel Booking Booking Flight 2.1 Booking Page 72 © Dr. Michael Stal, 2010 36
  • 37.
    Dr. Michael Stal:Architecture Refactoring Reduce Dependencies with Facades (2)  Context  Client implements workflows that mostly access other components p y p  Problem  If a client needs to access different external components for each workflow, it becomes dependent on details such as the set of available components  As soon as the configuration and / or interfaces of these components change, there will be a direct impact on the client  General solution idea  Introduce a Facade component that acts as the client s gateway into client's the set of required components  Implement workflow methods within the facade that represent the different workflows  The facade methods take over the responsibility for accessing the set of required components on behalf of the client, thus decoupling the client from the components  If components are remote, performance is also improved (Session Page 73 Facade) Merge Subsystems (1) Example: While tight coupling between subsystems is bad, high cohesion within subsystems is good. Thus, merge tightly coupled subsystems to form a highly cohesive subsystem . Sensor Sensor + Utilities Utilities Special variant: Merge a layer in a layered system Page 74 © Dr. Michael Stal, 2010 37
  • 38.
    Dr. Michael Stal:Architecture Refactoring Merge Subsystems (2)  Context  Coupling between subsystems  Problem  Between two subsystems in a software architecture the degree of coupling should be rather loose  Within a subsystem the number of interdependencies (cohesion) should be high  If the coupling is too tight, then the many interdependencies between these two subsystems decrease qualities such as  Changeability  Performance (maybe)  Reusability of one of the subsystems  General solution idea  Tight coupling between subsystems implies that the two subsystems in fact implement one subsystem  Either merge both subsystems to form one, or  Move functionality from one subsystem to the other Page 75 Split Subsystems (1) Example: When analyzing interdependencies between entities in a subsystem, two (or more) sets can be determined. Within these sets there is high cohesion; between these sets there is only low cohesion. Thus, split the subsystem into two (or more) parts. Component Container High Cohesion Lifecycle Persistence Event Handling Management Component Container Communication Communi- cation Special variant: Split layer in a layered system Page 76 © Dr. Michael Stal, 2010 38
  • 39.
    Dr. Michael Stal:Architecture Refactoring Split Subsystems (2)  Context  Cohesion within a subsystem  Problem  Within a subsystem the interdependencies (cohesion) should be high  Between two subsystems in a software architecture, the degree of coupling should be rather loose  If the cohesion between some parts is loose, then some design decisions seem to be questionable  It is recommendable to change this to obtain better modularization and understandability  Another potential problem are subsystems/components with too many responsibilities  General solution idea  Loose cohesion within a subsystem implies that the functionality can be split into multiple subsystems  Thus, determine areas with high cohesion in a subsystem. All those areas with low cohesion are candidates for becoming subsystems of their own Page 77 Enforce Strict layering (1) Example Application pp Application Layer 3 Layer 3 Component Component Component Component Component Component 3.1 3.2 3.3 3.1 3.2 3.3 Layer 2 Layer 2 Broken Component Component Component Component layering 2.1 2.2 2.1 2.2 Layer 1 Layer 1 Component Component Component Component Component Component 1.1 1.2 1.3 1.1 1.2 1.3 Page 78 © Dr. Michael Stal, 2010 39
  • 40.
    Dr. Michael Stal:Architecture Refactoring Enforce Strict Layering (2)  Context  An architecture with broken layering  Problem  Layers are introduced to reduce dependencies, increase adaptability and reusability, as well as maintainability  Sometimes relaxed layering is used intentionally to solve problems such as performance issues  At other times relaxed layering is used accidentally without any y g y y justification and value  In the latter case, how can we cure the broker layering?  General solution idea  Redesign so that the broken layering is substituted with strict layering Page 79 Enforce Strict Layering (3)  Unfortunately, broken layering is often hard to cure  To resolve the broken layering between component 3.1 and component 1.1, we must differentiate the following cases:  Case 1: All the types of functionality of component 1.1 that component 3.1 uses are also available in layer 2  In component 3.1, substitute all usages of component 1.1 by equivalent functionality of layer 2  Case 2: Not all the types of functionality of component 1.1 that component 3.1 uses are available in layer 2  Substitute all those component 1.1 invocations with equivalent invocations of layer 2 For the rest of the invocations move 2. invocations, functionality from layer 3 to layer 2  In case 2 it is sometimes not advisable to move functionality from layer 3 to layer 2. Consider reengineering activities instead!  Note: This is one of the refactorings that can also be applied in the opposite direction. If strict layering is not feasible (e.g., due to performance), relax the strict layering! Page 80 © Dr. Michael Stal, 2010 40
  • 41.
    Dr. Michael Stal:Architecture Refactoring Move Entities (1) Example y z y z x x Game Game getPlayerHistory(p) getPlayerHistory() Player Player Page 81 Move Entities (2)  Context  Moving entities between subsystems  Problem  This can be considered a generalization of the Split Subsystem refactoring  In a subsystem an entity is defined that fits better semantically in another subsystem to which it has high coupling  General solution idea  Again, we should consider cohesion and coupling  If entity e reveals low or zero cohesion to the rest of its subsystem A, but tight coupling to subsystem B, then move e from A to B  Note: This may also help with breaking dependency cycles between subsystems Page 82 © Dr. Michael Stal, 2010 41
  • 42.
    Dr. Michael Stal:Architecture Refactoring Move Entities (3) Some additional issues  In many cases we can t apply the refactoring to single atomic entities cases, can't such as a class, method, constant, interface  It is more likely that there will be clusters of atomic entities that together build a complex entity  In the example, it is very likely that there will be classes and interfaces related to the method to be moved  Thus, always consider semantically related entities with high internal y y g cohesion but less cohesion to the rest of their subsystem. If some of them show tight coupling to another subsystem, move the whole group  Moving may not always be a simple operation, but imply several smaller grained transformations (see example) Page 83 Add Strategies (1) Example Warning Client Client  Never introduce strategies in an uncontrolled way  A strategy basically Middleware means "I have no idea Middleware which option to use at DispatcherStrategy runtime" Request Dispatcher  St t Strategy S d Syndrome isi ConcreteDispatcher a serious disease that leads to an over- generic architecture which is doomed to Protocol Protocol design erosion Page 84 © Dr. Michael Stal, 2010 42
  • 43.
    Dr. Michael Stal:Architecture Refactoring Add Strategies (2)  Context  Enable selection and exchange of implementations  Problem  Services and algorithms in a component can be implemented in various ways. Their implementation often also depend on client requirements  The client should not depend on the concrete implementations used  Hard-coding a service or algorithm and then exchanging it at source code level is a possible solution  Unfortunately, this does not hold for runtime configurability  How can we refactor a component to support this kind of runtime configuration?  General solution idea  Use the Strategy pattern Page 85 Enforce Symmetry (1) Examples for structural symmetry  Some places in Subsystem UI Subsystem UI the architecture Based on MVC Based on MVC throw exceptions, and Observer and Observer while other return error codes  One subsystem leverages the Subsystem Accounts y Observer pattern, pattern Uses hardwired Subsystem Accounts configuration of Uses Observer another one a event handlers hardwired event notification strategy Page 86 © Dr. Michael Stal, 2010 43
  • 44.
    Dr. Michael Stal:Architecture Refactoring Enforce Symmetry (2)  Context  Refactor an asymmetric solution  Problem  Asymmetry reduces conceptual integrity and simplicity  Structural asymmetry deals with the usage of the same solution concepts throughout an architecture  Functional asymmetry is relevant on the method level ("When there is an open, there should be a close operation")  General solution idea  Prioritize strategy over tactics  For identical problem contexts in your architecture, apply the same solutions (e.g., the same patterns)  Use refactoring-to-patterns where applicable  All unmotivated asymmetries should be removed step-by-step Page 87 Enforce Symmetry (3) Example for functional symmetry: Abstract Factory with missing dispose method AbstractFactory AbstractProductA create_productA create productA ProductA ConcreteFactory ConcreteProductA create_productA ProductA AbstractFactory AbstractProductA create_productA ProductA dispose_productA ConcreteFactory ConcreteProductA create_productA ProductA dispose_productA Page 88 © Dr. Michael Stal, 2010 44
  • 45.
    Dr. Michael Stal:Architecture Refactoring Extract Interface (1) Example << interface >> ISensor getTemperature(UNIT) Sensor Adapter if (UNIT == CELSIUS) temperature() Sensor useCelsius() useCelsius(); useFahrenheit() temperature() else initialize() useCelsius() reset() useFahrenheit() useFarhrenheit(); getAverage(from,to) initialize() return temperature(); storeRecord() reset() getRecord(DateTime) getAverage(from,to) getDateTime() storeRecord() getRecord(DateTime) getDateTime() Page 89 Extract Interface (2)  Context  (Sub)system needs to export functionality  Problem  An existing (sub)system needs to export some of its internal functionality to external users  How can the (sub)system developer make internal functionality available externally?  General solution idea  Define abstract interface and contract  Provide wiring of interface methods to internal functionality  Apply patterns such as Bridge, Decorator, or Adapter to separate interface from implementation  Optionally, use the Extension Interface pattern to manage multiple interfaces Page 90 © Dr. Michael Stal, 2010 45
  • 46.
    Dr. Michael Stal:Architecture Refactoring Enforce Contract (1) Example << interface >> << interface >> IFile IFile Handle open(File) Handle open(File) Write(Handle, buf) Write(buf) close(Handle) close() Write/ notEmpty(buf) Open/ Contract IsValid(File) Implementation Close Open/ not IsValid(File) ( ) File System File System Page 91 Enforce Contract (2)  Context  Enforcing contract of an interface  Problem  A contract defines what the user of an interface must provide and what the user can expect in turn, e.g., preconditions, postconditions, required order of method execution  Often, interface implementations do not enforce the contract  A contract that is never enforced is of limited value  How can we enforce the interface contract?  General solution idea  Define contract explicitly: For example, use a state machine to define method execution order. Specify interface invariants. For each method, determine preconditions and postconditions  Enrich interface implementation to enforce contract Page 92 © Dr. Michael Stal, 2010 46
  • 47.
    Dr. Michael Stal:Architecture Refactoring Provide Extension Interfaces (1) Client Factory create() Interface1 find() service_1.1(); service_1.2(); service_1.3(); service_1.4(); RootInterface . get_extension() . . . . . Extension Extension . Interface1 Interface2 service_1.n(); service_1() service_2() Component Component svc_1_impl() svc_2_impl() Page 93 Provide Extension Interfaces (2)  Context  Managing interfaces of a component  Problem  If a component evolves over time, often new functionality is added to the component's interfaces  This may lead to severe interface bloating, which has a negative impact on quality attributes such as usability and manageability (Swiss Army Knife anti-pattern)  Unsystematic interface evolution may also break client code  How can we add an interface management for systematically evolving and providing interfaces?  General solution idea  Apply Extension Interface Patterns [POSA2]  Introduce a common protocol for all provided interfaces (including interface navigation)  Integrate additional functionality so that clients can discover existing component interfaces and navigate between them Page 94 © Dr. Michael Stal, 2010 47
  • 48.
    Dr. Michael Stal:Architecture Refactoring Provide Extension Interfaces (3) Client Factory Notes Interface ID1 Root Ext Ext  This refactoring alters Comp. Inter- Inter- create Interface face1 face2 components and Interface clients. Thus, handle ID1 with care! Interface Interface  Interface navigation 1 1 service1 should be reflexive, symmetric, transitive  But you may also Interface ID2 get_extension Interface introduce a dedicated 2 service2 interface that includes the navigation functionality Page 95 Substitute Inheritance with Delegation (1) Example Player IPlayer play() play() Player Ninja lookupExperience() Ninja play(IPlayer) play() lookupExperience() play() Player p delegate play(IPlayer ip) { // pre-processing this.play(); // post-processing } Page 96 © Dr. Michael Stal, 2010 48
  • 49.
    Dr. Michael Stal:Architecture Refactoring Substitute Inheritance with Delegation (2)  Context  Using delegation when inheritance is not available or not suitable  Problem  Assume an entity D should logically inherit from entity B, but inheritance is not available on component or subsystem level, or inheritance cannot be used due to other restrictions  In these cases, using inheritance is not the right approach  How can we get rid of (the necessity to use) inheritance but get the same possibilities?  General solution idea  Keep B as it is  Within entity D add reference to B  Provide public interface of B also in D but forward all invocations to referred B (optionally passing a reference to D for back calls)  Additional note  This is another one of the reversible patterns that may also be applicable in the opposite direction! Page 97 Provide Interoperability Layers (1) Example Application layer Adapter layer  Provide bidirectional interoperability between two subsystems using Web Services  Extract subsystem interfaces and use adapters (e.g., session facades, business delegates) to integrate them with their subsystems Page 98 © Dr. Michael Stal, 2010 49
  • 50.
    Dr. Michael Stal:Architecture Refactoring Provide Interoperability Layers (2)  Context  Enable interoperability between two subsystems  Problem  Sometimes formerly collocated subsystems need to be distributed, or  An application needs to interoperate with other legacy applications  Unfortunately, both of them were not designed to interoperate  General solution idea  Insert adapter layers to provide interoperability  Adapt subsystem A to B or subsystem B to A or use a bidirectional A, adaptation  Adaptation is a holistic approach. You may adapt communication, data, policies  Use patterns such as Adapter or Wrapper Facade. In other words, apply the Insert Transparency Layer refactoring Page 99 Provide Interoperability (3)  Aspects for interoperability in object-oriented, distributed systems  Interoperability is not restricted to data transformation and communication  For example, we also need to adapt error management  Likewise, object models must be mapped onto each other  Policies (e.g., security, memory management) must be mapped onto each other  The simpler the adaptation layers provided, the more work developers p p y p , p must spend to close the semantic gap  Integration products such as EAI solutions just provide a set of proprietary interoperability solutions Page 100 © Dr. Michael Stal, 2010 50
  • 51.
    Dr. Michael Stal:Architecture Refactoring Aspectify (1) Example + Logging Logging functionality functionality Page 101 Aspectify (2)  Context  Dealing with cross-cutting concerns g g  Problem  Cross-cutting concerns such as security mechanisms, distribution mechanisms and other invasive functionalities lead to extensive replication of design and code  OO mechanisms such as inheritance can't solve the problem, due to infeasible centralization of these concerns  Nonetheless, separation of concerns should be supported  General solution idea  Express concern as a centralized package  Introduce injection mechanism to integrate wrapped concern in all required places of software architecture  If cross-cutting concerns are interdependent, allow injection mechanism to take care of interdependencies, for example by using prioritization or a generative approach Page 102 © Dr. Michael Stal, 2010 51
  • 52.
    Dr. Michael Stal:Architecture Refactoring Integrate DSLs (1) Example Interface Root Monitor Interface Root Monitor Factory Interface Factory Interface StorageMgr Capacity ServiceX Abstract StorageMgr Capacity ServiceX Abstract Interface Interface Interface Interceptor Interface Interface Interface Interceptor * * Storage Leafs LoadIn Storage Leafs LoadIn Capacity Only Layers Capacity Only Layers Storage Abstract Abstract Abstract Storage Abstract Abstract Abstract Hook Hook Manager Visitor Iterator Strategy Manager Visitor Iterator Strategy * * Abstract * * * * Abstract Storage Successor Successor Storage * * SOC Atomic Composite SOC Atomic Composite Factory Storage Storage Factory Storage Storage * Hazardous Ware- * Bin Aisle Hazardous SOC house Bin Warehouse Aisle SOC Hazardous Real Thread Hazardous Real Thread Socket Socket Value Bin Mutex Value Bin Mutex  Microsoft's XAML (eXtensible Application Markup Language) is used for specifying workflows declaratively within and between applications  In the past, developers had to hardcode these workflows in the architecture using implementation languages such as C# Page 103 Integrate DSLs (2)  Context  A system that covers many different domains  Problem  Mastering complexity in a software system is an important challenge. Complexity is often cause by the usage of multiple domains (based on different concepts and paradigms)  If many domains are involved, such as the business logic itself, accessing databases, specifying workflows, UI design, then impedance mismatch becomes an essential issue  In addition, the work of different domain experts is more difficult, because all domain experts must understand the full software system  General solution idea  Instead of hard-coding domain-specific functionality manually, define a metamodel / DSL that allows domain experts to define their logic  Implement generators that transform models / DSLs to implementation artifacts  Define an integration subsystem for each of these domains that integrates the generated artifacts with the rest of the system Page 104 © Dr. Michael Stal, 2010 52
  • 53.
    Dr. Michael Stal:Architecture Refactoring Add Uniform Support for Runtime Aspects (1) Subsys UI Subsys UI IUIAdmin IAdmin Subsys DB Subsys DB IDBAdmin IAdmin Subsys ATM Subsys ATM IATMAdmin IAdmin Management Console Page 105 Add Uniform Support for Runtime Aspects (2)  Context  Software architecture that must support runtime aspects such as lifecycle management, management, configuration f f  Problem  Each non-trivial software architecture consists of multiple components, each of which supports common aspects  If every component implements its own interfaces for runtime aspects, the overall system will lack simplicity and expressiveness  Is there a way to provide a uniform approach to support those kinds of runtime aspects?  General solution idea  For each aspect, define a common interface (e.g., an interface for runtime configuration)  In each component supporting the aspect, provide this common interface (maybe using Extension Interfaces to prevent bloating)  To achieve orthogonality, provide one runtime component that is in charge of accessing these common interfaces (e.g., a management console) Page 106 © Dr. Michael Stal, 2010 53
  • 54.
    Dr. Michael Stal:Architecture Refactoring Add Configuration Subsystem (1) Example Actor Subsystem UI Subsystem UI IConfig1 IConfig Configuration Subsystem DB Configuration Subsystem DB Actor IConfig2 Subsystem IConfig Subsystem ATM Subsystem ATM IConfig3 IConfig  Use patterns such as Component Configurator for this purpose Page 107 Add Configuration Subsystem (2)  Context  A system with many configurable variabilities  Problem  If a system contains a lot of configuration options, then configuration itself is often tedious and error-prone  This holds in particular when the configuration options are (partially) related to each other  How can we refactor the software system so that configuration is simplified and (partially) automated?  General solution idea  Instead of providing dozens of configuration options to external actors, we introduce a configuration subsystem that takes a declarative configuration (from a file or a wizard)  The configuration subsystem reacts to configuration change events, reads the passed configuration, and then accesses the configuration interfaces of configurable subsystems  Ideally, all subsystems provide the same generic configuration interface Page 108 © Dr. Michael Stal, 2010 54
  • 55.
    Dr. Michael Stal:Architecture Refactoring Introduce the Open/Close Principle (1) Example Sensor Sensor ObserverInterface SensorMonitor Page 109 Introduce the Open / Close Principle (2)  Context  Opening a subsystem for external monitoring or modification (e.g., eventing or interception) )  Problem  An existing subsystem needs to be opened to let other subsystems observe this subsystem or intercept specific behavior  So far, the subsystem has been a black box  How can we introduce mechanisms for opening our architecture in a controlled way?  General solution idea  Apply the Open / Close Principle  Design the states and state transitions of the subsystem and decide which transitions should be observable or interceptable  For all these observation and interception points, introduce appropriate hooks with which other subsystems can register for observation or interception  If interception is required, design the required context object and subsystem internal functionality required for interception Page 110 © Dr. Michael Stal, 2010 55
  • 56.
    Dr. Michael Stal:Architecture Refactoring Optimize with Caching (1) Example Client Subsystem Client Subsystem getResource() getResource() allocates and creates * Resource Cache acquire() release() maintains * Resource Page 111 Optimize with Caching (2)  Context  Optimize access to reusable resources using caching  Problem  When a subsystem provides resources to other parties, resource access becomes a potential bottleneck  If high usage frequency of the same resources leads to performance bottlenecks due to costs for resource creation, allocation, initialization, additional means of accelerating resource access are necessary  How can we optimize resource access?  General solution idea  Introduce a fast cache where reusable resources are maintained  Define an appropriate resource allocation (activation) and a de- allocation (eviction) strategy  Provide a transparency layer to resource users Page 112 © Dr. Michael Stal, 2010 56
  • 57.
    Dr. Michael Stal:Architecture Refactoring Optimize with Caching (3)  The choice of allocation / de-allocation strategy is important  Example  A web site that returns weather maps based on zip codes  Suppose zip-based maps and weather data are stored in databases. When a new request arrives  A servlet reads the map  reads the weather data  then uses image processing to calculate the map with weather information  which it finally returns to the client  When we introduce a cache, how do we decide which maps to store? Should we always remove the least frequently used maps? Or could we just store the "empty" map in the cache?  How should we deal with updates (weather changes)? For example, can we introduce timeout values (leasing)? Page 113 Replace Singleton (first variant) (1) Example Singleton MethodClass +m1(); +m1(); +m2(); +m2(); +m3(); +m3(); state state t t  State is now a singleton, while behavior isn't  In the end it's all about identity  Known use: EJB Entity Beans Page 114 © Dr. Michael Stal, 2010 57
  • 58.
    Dr. Michael Stal:Architecture Refactoring Replace Singleton (first variant) (2)  Context  Resources / objects with state that should be available at most once  Problem  Assume that a resource type (objects within a class, threads in a thread pool, …) that represents a particular state should only contain one single instance  For this purpose, the Singleton Pattern is often applied  Unfortunately, the Singleton pattern acts like a global declaration  Are there any alternatives for our problem context?  General solution idea  In a singleton, state and behavior are integrated. The non-transient parts of the state represent the identity of the singleton object  Thus, the singleton mustn't be replicated, as this would duplicate its identity  Replace the singleton class with a class that provides the same public interface (value class), but store all the non-transient state in a central place (database, TSS, hash table, …) with the key known to the new class. The behavior and transient state, however, may be replicated Page 115 Replace Singleton (first variant) (3) Virtual Objects HalfObject1 HalfObject2  The same concept is applicable to se ce () service1() se ce () service1() introduce operational qualities such service2() service3() as availability or fault-tolerance protocol() protocol() through replication  In this case a number of objects provide the same services but store Half Objects their state in a central place Here There  For clients all objects appear as one single (virtual) object local  For state synchronization between physical objects (that represent the same virtual object), a protocol is required remote  Patterns to be applied:  Half-Sync-Plus-Protocol Protoco  Object Group l Page 116 © Dr. Michael Stal, 2010 58
  • 59.
    Dr. Michael Stal:Architecture Refactoring Replace Singleton (second variant)  Another possible way to remove singletons is to introduce a wrapper, such as an object manager or factory  The wrapper is in control of lifecycle management and thus able to f f ensure that a specific type has only one instance Singleton User +m1(); +m2(); +m3(); state The wrapper ensures that at most one instance of the singleton is created. Note that a singleton Wrapper might be removed and then reactivated, e.g., due to leasing. Page 117 Separate Synchronous and Asynchronous Processing (1) Example sy_svc_1 sy_svc_2 sy_svc_3 as_svc_1 as_svc_2 as_svc_3 Synchronous Service Layer Async Sync Queue sy_svc_1 sy_svc_2 sy_svc_3 Service Service interrupt msg enqueue notify Queuing Layer de-queue as_svc_1 as_svc_2 as_svc_3 msg work interrupt Asynchronous Service Layer Page 118 © Dr. Michael Stal, 2010 59
  • 60.
    Dr. Michael Stal:Architecture Refactoring Separate Synchronous and Asynchronous Processing (2)  Context  Distributed systems that include a mixture of synchronous and y y asynchronous processing  Problem  Both asynchronous and synchronous services should be decoupled, so that neither suffers from the deficiencies of the other  Both asynchronous and synchronous services should be able to communicate with one another efficiently using their own communication paradigm  How can we refactor an architecture where synchronous and asynchronous services are tightly coupled?  Solution  Separate synchronous and asynchronous services from one another by dedicated layers and add a queuing layer between them to mediate communication between services (Half Sync / Half Async Pattern) Page 119 Replace Remote Methods with Messages (1) Example Client C_Side_Proxy C Side Proxy C_Side_Proxy C Side Pro service_c() service_s() service_s() snd_request() snd_request() rcv_response() rcv_response() * Broker Queue Bridge Direct est_connection() connection listen() est_connection() find_server() enqueue() find_server() register_svt() dequeue() unregister_svt() * Servant S_Side_Proxy S_Side_Proxy service_s() rcv_request() rcv_request() snd_response() snd_response() Page 120 © Dr. Michael Stal, 2010 60
  • 61.
    Dr. Michael Stal:Architecture Refactoring Replace Remote Methods with Messages (2)  Context  Asynchronous problem using synchronous remote methods  Problem  In many distributed systems remote method invocation is the primary choice of communication. Asynchronicity is often introduced in the application layer, but implemented on top of remote methods  However, message-oriented middleware is often the better choice for dealing with event-based or asynchronous communication  Is there a migration path to move from synchronous to asynchronous communication without huge impact?  General solution idea  Keep the Broker-based architecture unchanged but integrate an additional asynchronous layer that relies on messaging middleware  For synchronous communication, still use the synchronous layer  For asynchronous communication, use the asynchronous layer instead (message queues, asynchronous completion tokens, …)  Future functionality may then directly rely on asynchronous messaging Page 121 Add Object Manager (1) Example Client Factory Object Manager Client create() createObject() delete() deleteObject() find() insertObject() removeObject() findObject() objectIterator() Object * service() ManagedObject service() Page 122 © Dr. Michael Stal, 2010 61
  • 62.
    Dr. Michael Stal:Architecture Refactoring Add Object Manager (2)  Context  Management support for objects  Problem  Objects (and resources) for client usage often need to implement management functionality in addition to business logic, e.g., lifecycle management, persistence management  This burden leads to memory usage and responsibility overload  Clients shouldn't be responsible for object management either  Different applications may require different management policies  How can we provide such additional management?  General solution idea  Separate object usage from object management  Introduce an manager component that manages objects throughout their lifetime Page 123 Change Unidirectional Association to Bidirectional (1) (Fowler) Example Order Order * * 1 1 Customer Customer class Order... class Customer... Customer getCustomer() { private Set _orders = new HashSet; return _customer; void addOrder(Order arg) { } arg.SetCustomer(this); void setCustomer(Customer arg) { } _customer = arg; Set friendOrders() { } return _orders; Customer customer; } class Order... void setCustomer(Customer arg) { _if (_customer != NULL) customer.friendOrders().add(this); } Page 124 © Dr. Michael Stal, 2010 62
  • 63.
    Dr. Michael Stal:Architecture Refactoring Change Unidirectional Association to Bidirectional (2) (Fowler)  Context  Two classes referring to each other  Problem  Class A refers to a class B, but there is no backward navigation from B to A  However, after some development activities, you recognize that B also requires a reference to all A objects referring to it  How can we transform the unidirectional to a bidirectional navigation?  General solution idea  Add a back link in class B that allows navigation from B to the referring A object(s)  Decide which class is in charge of controlling the association, e.g.  The composite controls its constituents  In one-to-many relationships, make the one-side (i.e., side with multiplicity of one) the controller  Introduce helper method in the non-controlling side  If the existing modifier is on the controlling side, modify it to update back references, otherwise create a controlling method on the controlling side and call it from the existing modifier Page 125 Refactoring References Page 126 © Dr. Michael Stal, 2010 63
  • 64.
    Dr. Michael Stal:Architecture Refactoring Refactoring References  Fowler Martin et al. 1999. Refactoring: Improving Fowler, al 1999 the Design of Existing Code. Addison-Wesley  Demeyer, S; Ducasse, S; Nierstrasz, O. 2002. Object-Oriented Reengineering Patterns. Morgan Kaufmann  Kerievsky, Joshua. 2004. Refactoring to Patterns. Addison-Wesley  Ambler, Scott W.; Sadalage, Pramodkumar J, 2006. Refactoring Databases: Evolutionary Database Design. Addison-Wesley  Thanks to Dr. Michael Stal for his permission to use his material in this presentation Page 127 © Dr. Michael Stal, 2010 64