1. Don’t rewrite – Reengineer!
SOFTWARE REENGINEERING:
INJECTING QUALITY INTO
EXISTING SYSTEMS
2. Who Am I?
Brad Irby
http://twitter.com/bradirby
Brad@BradIrby.com
Blog: BradIrby.com
New Book: Reengineering .NET
25 Years Experience in Application Design and
Architecture
Specialist in Application Reengineering and
Architecture for .NET Applications
Brad Irby Reengineering Series
3. Who are You?
Who is religiously using Unit Tests?
Who has a Continuous Integration Server?
Who is using an IoC Container?
Who is working on a Legacy App?
Brad Irby Reengineering Series
4. Agenda
Quickly Review the Business Case
Why Reengineer instead of Rewrite
Laying the Groundwork
Prerequisites and Suggestions
Basic Workflow
What to do first
Specific Techniques
How to handle some situations that will arise
during the project
Brad Irby Reengineering Series
5. Goal of Reengineering
Continuous Release with No Feature Freeze
Continued Revenue Stream
Continuous Improvement
SOLID
DRY
Fix the Plane in the Air
Brad Irby Reengineering Series
6. Advantages of Reengineering
Maintains Existing Logic
Business Logic
Established Processes
Side Effects
Go at your own pace
Fits well with Agile
Fewer Errors Interpreting Existing System
Outdated documentation
Code spelunking
Continuous QA
Reduced Risk
Brad Irby Reengineering Series
7. Advantages of Reengineering
Business logic already complete
No need to recreate it
Can use outside talent
In house team can continue adding features
Shorter Timeline to establish patterns
Medium size solution: 6 months
Large Solution: 9 months
25% of the cost of a Rewrite
Brad Irby Reengineering Series
8. Starting Out - Code Review
Establish validity of MVC or MVP
Everybody claims it, few have it
Where does business logic live? Should be in Controller/Presenter
Count Number of Static Classes
Pure constant or enum classes don’t count
Count Activator Calls
Often used to get around bad references and circular references
The more you have, the more time you should budget
Count Average Num References per Project
Look at validity of references
Should one project reference another?
Many Other Metrics
Know WhatYou Are Up Against Brad Irby Reengineering Series
9. Lay Groundwork (Basics)
Decide Unit Test Framework
External GUI runner
Integrated into VS2008/2010/2012 (ReSharper)
Integrates with Code Coverage
Integrates with TFS/Perforce/SVN/Git?
Has Command Line
Reporting
Possibly needs data export
Possibilities: NUnit, MbUnit, MSTest
Spend the time to do this right
Brad Irby Reengineering Series
10. Lay Groundwork (Basics)
Setup Build Server
Nightly build a must
Email build Success/Fail
Continuous Integration helps a lot
Cruise Control and CCTray
Nightly runs of integration tests
Unit tests run on each check-in
Peer Pressure Not To Break Builds Brad Irby Reengineering Series
11. Lay Groundwork (Basics)
Divide Tests
Unit tests (run on each check-in)
Integration tests (run at least nightly)
Performance Tests (run at least nightly)
Install test runner
TestDriven or Resharper are good
VS2012 runner built in
Training is an ongoing effort
Brad Irby Reengineering Series
12. Lay Groundwork (Advanced)
Decide on Code Coverage
NCover, DotCover or MS Team Coverage
Stats should run nightly to develop trend
After time, decide on max Cyclomatic Complexity
Decide on Mocking Framework
Free: Moq, Rhino mocks, others
Difficult to use with Reengineering
Paid (but worth it): JustMock
Specializes in mocking legacy code
Get Team Buy-in on these Brad Irby Reengineering Series
13. Preliminary Code Cleanup
Develop Project Structure Strategy
Careful of too many partial classes (Model)
Bug in VS2008
Remove unneeded Usings and References
Clean up warnings
Set “Warnings as Errors”
Move Constants and Enums to static classes
Code Changes Good for Junior Dev
Brad Irby Reengineering Series
14. Step 1 - Add Foundation
Inversion of Control Container
Enabled loose coupling
BootStrapper
Use to setup IoC container
Service Locator
Dependency Injection too difficult for
Reengineering
Brad Irby Reengineering Series
15. Inversion of Control Container
Enables a way for code to use classes without
knowing what they are or how to create them
Centralized Service Management
Provides Loose Coupling
Allows Separation of Concerns
Improves Testability
Possibilities: Unity, Castle Windsor, StructureMap
Difficult Transition for Inexperienced Brad Irby Reengineering Series
16. BootStrapper
Provides central area for app configuration
Central Registration of classes and interfaces
Makes test setup easier and more reliable
Each test can setup IoC as appropriate
Static or Dynamic discovery of modules
Load by Hand
Scan disk looking for modules to load
All Services Need Interfaces Brad Irby Reengineering Series
17. Service Locator
Provides anonymous access to app services
Service consumer need only know about the
interface, not the service itself
Location services can be extended to objects
also (forms, regions, etc.)
Brad Irby Reengineering Series
18. How to Convert to
Inversion of Control
BootStrapper
Service Locator
Brad Irby Reengineering Series
19. Why Service Locator?
Limits refactoring to the components at hand
Dependency Injection requires update from root to
leaves
Constructor Injection
Property Injection
OnDemand Creation of Dependencies
Do not have to create classes that are never used
Advantage in tests and production code
Brad Irby Reengineering Series
20. Summary so far
Added basic components – less than 1 day
No affect on existing legacy code yet
App will build and deploy like normal
Brad Irby Reengineering Series
21. Step 2 – Entity Model and Repo
Implement Repository Pattern
Allows much more versatility in testing
Divorces app from persistence technology
Oracle, MS SQL, MySQL
Possible even without Entities
Convert to Entities (if possible)
Ensure data model is in project by itself
Allows use from old and new code
Separates data concerns from code concerns
Add Now to Reengineer Incrementally Brad Irby Reengineering Series
22. How to Convert to
Entity Model
Repository
Brad Irby Reengineering Series
23. Step 3 – Create Services
Web or Desktop
Logger
Log4Net or home-grown logger
Repository (if not already there)
Validation Manager
Validate state of domain entities
Microsoft Validation Block is good
Desktop Apps
Session State Manager
Only use this during conversion – should disappear when done
Dialog Service
Message Aggregator
MessageEvents takes planning
Basic Services Required for Decoupling
Brad Irby Reengineering Series
24. Step 4 - Migrate Services
Look for singleton patterns
Search for “.Instance”
Move to Service Locator
Look for Services with no Interfaces
ReSharper can create interface for you
Look for Static Services Classes
Difficult to Mock and Test
Cause problems testing other things
Search for “public static class”
Change to Normal class (singleton via container)
Small Changes Can Have Big Benefits Brad Irby Reengineering Series
25. Step 5 – Views & Controllers
Architect does first ones
Start with Easiest
Lots of infrastructure needed for first one
Don’t complicate with difficult workflow
Use views that don’t need data binding if possible
Next, most difficult
Then involve the rest of the team
Build Example Patterns for Others
Brad Irby Reengineering Series
26. Parting Comments
Bootstrapper
Add Extension methods to setup mocks
Mocking
Make plenty of Mocking examples for others to
learn from – steep learning curve
Insist on 75% or more coverage on new code
80% is sufficient - 100% too difficult
Common mistake – overloading TestSetup
Reengineering – 25% of the cost of Rewrite
Brad Irby Reengineering Series
27. Who Am I?
Brad Irby
http://twitter.com/bradirby
Brad@BradIrby.com
Blog: BradIrby.com
New Book: Reengineering .NET
25 Years Experience in Application Design and
Architecture
Specialist in Application Reengineering and
Architecture for .NET Applications
Brad Irby Reengineering Series
Notas del editor
In this presentation we are going to be going through a typical reengineering engagement with a fictional client. We will walk through all the steps necessary to reengineer an existing system from the start to the finish.
These are the main advantages of reengineering over rewriting.A largely ignored factor is that reengineering retains the unintended side effects of the way the current code was implemented. Customer come to depend on the small artifacts in our software, and if we rewrite it those artifacts will be lost without us knowing it. By keeping as much of the business logic as possible, these artifacts are retained, and customers are kept happy.
These are the main advantages of reengineering over rewriting.A largely ignored factor is that reengineering retains the unintended side effects of the way the current code was implemented. Customer come to depend on the small artifacts in our software, and if we rewrite it those artifacts will be lost without us knowing it. By keeping as much of the business logic as possible, these artifacts are retained, and customers are kept happy.
These are the main advantages of reengineering over rewriting.A largely ignored factor is that reengineering retains the unintended side effects of the way the current code was implemented. Customer come to depend on the small artifacts in our software, and if we rewrite it those artifacts will be lost without us knowing it. By keeping as much of the business logic as possible, these artifacts are retained, and customers are kept happy.
First, we analyze the existing code to see what we are up against. This helps us estimate how long the project will take, what infrastructure elements we will need to introduce, and which elements will need to be replaced.
Deciding on a proper unit test framework is an important first step. There are various options depending on various factors in the development environment.
Nightly builds are must. Builds on each checkin are helpful, but not required.
It is best to divide out the integration tests up front since they take so much time to run.Note that training is never done! All new additions must be accompanied by team training to make sure the team adopts the new technology. New infrastructure that nobody uses is worthless.
Code coverage is a very useful tool, helping to measure progress towards complete test coverage.Mocking frameworks can be complicated, so the team should be involved in this decision.