restructuring- improving the modularity of an existing code-base
TRANSCRIPT
Restructuring
Improving the modularity of an existing code-base
Chris Chedgey
Structure101
Structure101 - People
• Chris Chedgey, Dunmore East, Ireland
• Paul Hickey, Toulouse, France
• Paul O’Reilly, Enniscorthy, Ireland
• Raghvendra Sahu, Delhi, India
• + 3 contractors
• No VC’s, no suits
Structure101 - Products
• Restructure101
• Fix architecture
• Structure101
• Define it
• Structure101 Build
• Enforce it
• Java, .NET, C/C++, Actionscript, php, …
• 1,000’s users in 100’s companies
Topics
• What is “Restructuring”?
• Motivation
• Understanding structure
• Restructuring strategies
• Examples
What is restructuring?
Refactoring• “Changing code without
modifying behavior to improve nonfunctional attributes.”
• Code is readable
• A lot of invasive code editing
• Scope: small worlds of a few classes at a time; what you see in the IDE.
Restructuring• “Reorganizing a code-base
without modifying the code to improve modularity”
• Code-base is understandable
• Minimal invasive code editing
• Scope: whole code base; what you don’t see in the IDE
What is structure?
• Composition
• Dependencies that roll up through composition
• Nested “levels”
• Quality factors
• 1. Complexity
• 2. Modularity
ModularityComplexity
Why is structure important?
• Determines cost of development• Understandability
• Predictable impact of changes
• Testability
• Reusability
• Value of your code base• Asset or liability?
Structural quality 1: complexity• Fat
• Too much stuff in one place (method, class, package, bundle, …)
• Tangles
• Cyclic dependencies
• Cumulative Component Dependency (CCD, Lakos) goes through the roof
• Acyclic Dependency Principle (ADP, Bob Martin) – morning after syndrome
• Eliminate tangles by putting everything in one place - creates fat
• Eliminate fat by simplistically partitioning fat items – creates tangles
Checked automatically
Structural quality 2: modularity
• High cohesion
• Low coupling
• Information hiding
• Interfaces
• Clear responsibility
• …
• S/W-eng 101
• We ALL know about modularity!
Checked by human architect
Working with structure – core features• Composition + Dependency
• Flow of dependency
• Whole codebase
• Filtering
• Summarizing
• Comprehension
Working with structure
• Lists and treeview
• Directed graph
• Dependency Structure Matrix (DSM)
• Levelized Structure Map (LSM)
Working with structure: list & treeview• Good to discover specific
information
• No dependency flow, manipulation
Visualizing structure: directed graphs• Info points: #items +
#deps
• Levelizable – good flow
• #deps becomes a problem
• Indicate fat, not fix
• Infinite nesting not feasible
• Local comprehension, not for global/manipulation
Visualizing structure: DSM• Info points: #items2
• “Scalable” - can be rendered for v large graphs
• Infinite nesting possible
• Whole code-base
• Manipulation possible
• Grow v large
• Hard to read, bad for the neck
Visualizing structure - LSM
• Info points: #items
• Composition, dependency, flow, whole codebase, filtering, summarizing
• Goldilocks – designed specifically for restructuring
The modularity wasteland • Methods ok
• Classes ok
• Handfuls of classes ok
• Overlapping “small worlds”
• Plenty of guidelines
• Smells and refactoring
• But almost no logical organization of classes into higher level modules
• This is not scalable
“But we use Java packages!”• Bollox!!
• Hierarchical ok
• Support visibility ok
• BUT: used like a filesystem, not as an embodiment of module hierarchy
• Composition only
• No consideration of dependencies
• Little consideration of visibility
• Too easy to change (without rules/tools)
• Becomes a big tangled mess
Modularity stops at class level?
• Finite aggregation is not scalable
• Oceans of classes
• Still need to divide and conquer
• Even more – affects the whole team
• Is it inevitable?
Inevitable?
• No!
• Spring:
Restructuring strategies
• Merge parallel structure
• Top-down or bottom-up decision
• Tackle complexity before modularity
• Break v large class tangles early
• Address tangles top-down
• Do as much as possible by moving classes and packages
• Divide disjoint packages early
• Break up v. fat classes and packages early
• Disentangle
• Consider mixed granularity
• …
Merge parallel structures• Common to separate interfaces/api
from implementation
• Perhaps attempt to increase awareness of visibility
• Obscures module structure esp if higher in hierarchy
• Better to consider module sub-items as siblings with visibility
• Keep both if there is a strong need/desire for physical code to be separate
• Use of transformations
Merge parallel structures
Bust v large class tangles early• Often there is 1 or a few
v.large tangles spanning many packages
• Making those packages acyclic means busting the class tangle
• Does it span multiple higher-level layers?
• Break the feedback dependencies between the layers
• Can the class tangle be contained within a single package?
• At least for now?
• Not if classes span to much of the layering
• Not if it represents a significant portion of your code base
• Can you break the tangle into several acyclic subsets of tangles?
• Each subset can be contained within a single package
• Each subset can be contained within a narrow range of ideal leveling
Do as much as you can by moving classes/packages first• Low effort refactoring
• Less invasive surgery so less risk of impacting behavior
• Exception – static classes
• Biggest bang for the buck, unless there are v.large class tangles
• Option to manage architecture separate from physical code
• Map classes to physical components
• Can’t be done if model requires invasive class editing
Top-down or bottom-up?• Top-down
• Preserves as much of the package hierarchy as possible
• Team can still find classes
• Feasible if the target structure is close to the current
• Bottom-up
• Current packaging is of little use
• Target structure is far from current
• Often easiest to implement
• A bit of both
• Preserve top-level breakout
• May reflect team structure
• Often reflects initial architecture
• Sub-modules were not explicitly designed
• Preserve in regions where there is relatively small amount of restructuring
Make items only using or used by a tangle
Move only used/using child items
Split disjoint packages
Split fat packages and classes
Move feeback from/top
Move feedback to/bottom
Move tangles together
Tackle complexity before (other) modularity• A structure without tangles is much easier to manipulate
• A milestone in its own right
• A code-base that is much easier to understand
• Many simply focus on keeping (over-)complexity out
• Good basis for further modularization (coupling, cohesion, interfaces, …)
Summary
• The modularity wasteland is normal
• It costs
• It can be salvaged
• It is not easy, but the returns can be huge
• Questions?
• Thank you!