2. FOCUS ON REPAYING ARCHITECTURE DEBT HERE
âŠ
Code debt
Static
analysis tool
violations
Coding style
violations
Design debt
Design smells
Violations of
design rules
Test debt
Lack of tests
Inadequate
test coverage
Architecture debt
Lacking
structure (esp.
tangles)
Violation of
architecture
constraints
our focus is mainly hereâŠ
3. UNDERLYING PRINCIPLES
âą First: Prefer non-invasive
architecture restructuring
instead of invasive code
changes
âą Second: âAutomationâ â
rely on combination of tools
for automated improvement
âą Third: âAssureâ â prefactor
to practice and show its
safe and gives great
beneïŹts
4. LARGE (LEGACY) CODE
†Positives:
†Working code
†Tried and tested
†Stable & known
†âŠ
†Negatives:
†âTouch here breaks thereâ (lack of visibility &
deteriorating structure)
†No ONE knows how it works (but we do know
it works!)
†Limited resources (unclear investment beneïŹts)
†âŠ
5. CORE ISSUE: DIFFICULT TO UNDERSTAND & LACKS STRUCTURE
†Lack of shared understanding of the whole system
†Original developers have long left the team
†New developers take a long time to become productive
†Structure has deteriorated over time (existing structure works
against development)
†Accidental changes to the structure (on need basis) than
intentional changes that preserves structure
†Changing code is âperceived riskyâ - hard to predict impact
†As developers we donât know how to ïŹx the code or add
features; when we know, canât be sure if it wonât break
anything (lack of automated unit tests adds to the problem)
6. Source: Consortium of IT Software Quality (CISQ), Bill Curtis, Architecturally Complex Defects, 2012
7. WHICH ONE WOULD YOU LIKE TO WORK ON?
V 0.7.2
V 1.3.5
https://sourceforge.net/projects/ïŹndbugs/ïŹles/ïŹndbugs/
8. STARTS WITH AN UNDERSTANDABLE INTENSIONAL STRUCTURE
V 0.7.2
18. MODULARITY IS THE KEY: REMOVING TANGLES AND FAT
†Tangles - entities are directly or indirectly depending on each
other (classes, packages, etc)
†Fat - excessive complexity of an entity (methods, classes,
packages etc)
21. UNDERSTANDING PHYSICAL/CLASS TANGLES
Step 1: Separate the interface & implementation
Step 2: Depend on the interfaces (and not on the implementations)
(Reflection: Needs code-level changes)
22. UNDERSTANDING PACKAGE-LEVEL TANGLES
Step 1: Create a separate package for the interface(s)
Step 2: Separate the interface & implementation
(Reflection: Needs package-moves - no code level changes)
25. SEPARATE INTERFACE & IMPL - FOR âCLASSREALMâ (WITHOUT CYCLE)
Step: Separate the interfaces in âmaven-classrealmâ from the
implementation (concrete classes) into to a separate module
(âmaven-classrealm-apiâ)
(Reflection: NO CODE CHANGE(S) NEEDED!!)
26. STORY OF HOW BUILD TOOL GOT EXTRACTED
Smell Detector tool
(UI &
implementation
logic)
Request came in
for build-time
checking tool
Smell Detector Tool
(UI)
Smell Detector
Build Tool
(headless)
Smell Detector
Implementation
Logic (DLL)
Interface
28. WHAT IS PRESTRUCTURING?
†Jack is âchainedâ â aka âtangledâ ;-)
†Rose is scared to use axe because too risky and lacks experience â
aka âfear of breaking the working codeâ - hence practices ïŹrst!
†âRehearse restructuring the codebase without actually making the
code changes!â
†Safely try out the speciïŹc structural changes
†Evaluate beneïŹts & trade-oïŹs
†Undo if needed
†Discuss and brainstorm by âtrying out thingsâ
†Plan the actual restructuring
†To the speciïŹc / exact steps and details
29. REFACTORING VS. RESTRUCTURING
Code Refactoring Modular Restructuring
It is improving the underlying design of
existing code through code modiïŹcations to
improve quality of the software, esp.
maintainability.
Improving the structure of the code-base with
little or no modiïŹcations to the existing code to
improve software modularity.
Target of change: Code itself. Refactoring is
done directly to the code (physical level).
Target of change: Code base. Changes are
done largely at higher levels of abstractions
(logical level).
Extent of code changes: A lot of invasive
code editing.
No code editing in most scenarios; sometimes
minimal code editing is needed for speciïŹc
structural issues.
What to refactor: Smells (A code smell is a
surface indication that usually corresponds
to a deeper problem in the system).
What to restructure: Structural issues
(dependencies, levelization, placement, size,
grouping, etc.).
Small worlds of a few classes at a time; what
you see in the IDE (examples: data classes,
large methods, long parameter lists)
Whole codebase; what you donât see in the
IDE (examples: tangles and cycles, orphan
packages, misplaced class in a package)
30. BENEFITS - MODULAR RESTRUCTURING
Developer Productivity
(quickening mental
models when working
with code)
The time to understand the
structure of a large codebase
(especially for teams who have
been transferred responsibility
of an existing product) is
drastically reduced
The cost of transfer of
maintenance is lesser as
KT time reduced as much
as 75%
Developer Productivity
(modularization results in
reduced change impact)
The time to make a change
(new enhancement/bug fix) is
drastically reduced as the time
to do impact analysis is
drastically reduced
The bug density is lower
as developers can better
modularize and make
changes confidently
Developer Productivity
(improved build times)
Modularization results in
reduced time for compilation &
more modular components as
part of a modular build system
Faster build times (even
upto 90%) resulting in
quicker turnaround time
for developers for
changes + quicker unit
testing
32. âFATTY PACKAGEâ â TOO MANY CLASSES IN A PACKAGE
Potential cause
Missing packaging of classes
Restructuring
Step 1: Auto-group and levelized
Step 2: Identify technical or functional groups
Step 3: Wrap them into sub-packages
33. âMISSING PACKAGINGâ
When there are few / no tangles in a package and there are many classes, it
indicates that subpackaging is missing
Pulling from bottom or top as packaging exposes new opportunities for subpackaging
So perform restructuring iteratively (not in one go)
35. âTROUBLEMAKER CLASSâ
Structural issue: A class should logically belong to the current package but causes cyclic dependency if
left as it is!
Potential cause: Implementation code (perhaps inadvertently) results in a cycle;Â
Restructuring:Â Â
Option 1: Refactor the implementation code (not recommended in this case)
Option 2: Move it outside the package (simple and effective solution in this case)
36. âMISPLACED-TROUBLEMAKER CLASS!â
Structural issue: A class should logically belong to the suitable package but causes cyclic dependency if
moved to that package
Potential cause: Implementation code (perhaps inadvertently) results in a cycle
Restructuring:Â Â
Option 1: Refactor the implementation code (not recommended in this case)
Option 2: Move it outside the package (simple and effective solution in this case)
37. âORPHANSâ
Structural issue
Unreferenced entities in the code base
Potential causes
Historic nature â used earlier but not
anymore
Left-overs â created but never used
Caution
It may be actually used but does not
have dependencies visible at compiled-
code level
Through features like reïŹection or as APIs
Or using mechanisms external to the language
RestructuringÂ
Step 1: Determine that they are actually
unused
Step 2: Remove them
Your chance to commit âpre-mediated
murders of innocent orphansâ and
become a âkiller coderâ ;-)
38. âKNOTTY PACKAGESâ
Structural issue
Packages are too much tangledÂ
Potential cause
Haphazard organization without
thinking
Degradation over timeÂ
Restructuring â âunwrap and
regroupâ
Step 1: Unwrap packages
Step 2: Regroup classes (âAuto-
regroupâ)
Step 3: Wrap into proper packages
(âRealizeâ)
Tool hint: Try âauto-levelizationâ
magic!
39. âKNOTTY CLASSESâ
Structural issue
Classes within a package are too much tangledÂ
Potential cause
Lack of grouping/sub-packaging
RestructuringÂ
Step 1: Autogroup classes
Step 2: Wrap relevant groups into sub-packages (âRealizeâ)
40. âUNTIDY PACKAGEâ
Structural issue
Both fat and tangles in the package
Potential cause
Haphazard organization (putting things in a package without thinking about structure)
RestructuringÂ
Step 1: Unwrap everything the package to class level
Step 2: Identify groups / cohesive clusters
Step 3: Repackage with new packages
41. MAKING âPRAGMATIC CHOICESâ IN RESTRUCTURING
ThreadLocalUtility causes tangles
âUsed byâ: âasyncâ and âwebappâ
âUsesâ: âasyncâ, âcontextâ, and âwebappâÂ
Going by the names of the entities âthread-local-utilityâ best belongs to âasyncâ but
move it to âwebappâ
But if we move it there, it will cause tangle between âasyncâ and âwebappâ
Perfectionist approach will move it to âasyncâ and also do âcode refactoringâ to get rid of the tangle â why should
ThreadLocalUtility depend on âwebappâ or âcontextâ?
Arguably pragmatic approach: Move it to âwebappâ because it will resolve tangle though it doesnât belong there
43. âPrefer âa moveâ (code restructuring)
instead of âinvasive code
changeâ (code refactoring)
A BIG IDEA!
44. TOOLS FOR REFACTORING & RESTRUCTURING
†CodeScene
†Designite
†JArchitect / NDepend / CppDepend
†Lattix
†ReSharper
†Sotograph / SotoArc
†and more âŠ
45. BIG IDEAS AND TAKEAWAYS
†It is possible to modularize WITHOUT changing
any code!
†Prefer making non-invasive architecture
restructuring (e.g., class moves to remove a
package tangle) instead of making invasive code
changes (e.g., change the code inside a class to
remove the oïŹending dependency)
†Tools are your friends - befriend them :-)
47. CREDITS
†For the FindBugs example: Structure101 team
†For applying principles image: our book âRefactoring for
Software Design Smellsâ
†Module system in JDK 9 - blogs.oracle.com
†Modular restructuring beneïŹts: Manoj Ganapathi (CodeOps)
†For the âmaven class-realmâ module extraction case study:
Mike Swainston-Rainford
†Source for the quotation: Consortium of IT Software Quality
(CISQ), Bill Curtis, Architecturally Complex Defects, 2012