Product Cover Image

Reengineering .NET: Injecting Quality, Testability, and Architecture into Existing Systems

By Bradley Irby

Published by Addison-Wesley Professional

Published Date: Oct 24, 2012


Reengineer .NET Code to Improve Quality, Update Architecture, Access New Tools, and Accelerate Delivery of New Features

As software ages, it becomes brittle: difficult to understand, fix, manage, use, and improve. Developers working with  many platforms have encountered this problem; now, developers working with Microsoft’s .NET are facing it as well.  In Reengineering .NET, leading .NET architect Bradley Irby introduces proven best practices for revitalizing older .NET code and integrating new architectural and development advances into business-critical systems that can’t go offline.  Using a step-by-step approach, .NET professionals can make legacy enterprise software more reliable, maintainable,  attractive, and usable—and make it easier to upgrade for years to come.

Through real-world case studies and extensive downloadable sample code, Irby shows how to carefully plan a .NET  reengineering project, understand the true current state of your code, introduce unit testing and other agile methods, refactor to services and controllers, and leverage powerful .NET reengineering tools built into Microsoft Visual Studio 2012.

This book is an indispensable resource for all developers, architects, and project managers responsible for existing .NET code bases and for a wide audience of non-technical managers and CTOs who want to understand the unique  challenges faced by .NET teams involved in application or system reengineering projects.

Coverage includes
• Migrating legacy .NET software to more flexible, extensible, and maintainable architectures—without breaking it
• Reengineering web applications with the MVC pattern, Winforms software with MVP, and WPF/Silverlight  systems with MVVM
• Asking the right questions to predict refactoring problems before they happen
• Planning and organizing reengineering projects to apply the right expertise to each task at the right time
• Using innovative Test Doubling to make unit testing even more effective
• Applying Dependency Inversion to break tight coupling and promote easier development and testing
• Leveraging source control, defect tracking, and continuous integration
• “Cleaning up” legacy solutions to improve them before you even touch business logic
• Establishing solid development infrastructure to support your reengineering project
• Refactoring to services—including advanced techniques using Repositories, Domain Models,  and the Command Dispatcher
• Refactoring to controller/view or ViewModel/View pairs

Table of Contents

Preface     xiii
Acknowledgments     xix
About the Author     xxi
PART I Target Architecture
1  Implementing a Service-Oriented Architecture     3
An Overview of the Service-Oriented Architecture     4
Understanding Standardized Service Contracts     6
  Interfaces     6
Understanding Coupling     12
Understanding Service Abstraction     15
Designing Reusable Services     18
Understanding Service Autonomy and Service Composability     18
Understanding Service Statelessness     19
A Service Example     24
Summary     26
2  Understanding Application Architecture     27
Working with Architectural Patterns     27
An Overview of Architectural Patterns     28
Differences Among MVP, MVC, and MVVM     29
  Model Access     30
  View Models     31
Handling UI Events     38
How Do the Patterns Work?     43
Which Pattern Should You Choose?     45
Summary     45
3  Unit Testing     47
An Example of Unit Testing     48
Creating Unit Tests     49
Writing a Test     52
Detecting Exceptions     58
Understanding the Power of Assert     61
Comparing Unit Tests to Integration Tests     61
Using the InternalsVisibleTo Attribute     62
Understanding Test Driven Development     65
Learning More About Unit Testing     65
Summary     66
4  Understanding the Dependency Inversion Principle     67
Understanding Tight Coupling     67
Implementing the Abstract Factory Pattern     74
Introducing Interfaces     79
Creating Unit Tests     82
Understanding Service Location     84
  Inversion of Control Containers     84
  Service Locator     88
  A Real World Example     90
  OnDemand Service Properties     96
  Unit Testing Advantages     99
  Final Tweaks     100
Using Dependency Injection     103
Why Is Service Location Better for Reengineering?     108
Summary     113
5  Using Test Doubles with Unit Tests     115
How Do Test Doubles Work?     115
What Need Do Test Doubles Satisfy?     116
Creating a Stub     119
  Distinguishing Between Mocks and Stubs     123
Creating a Mock     124
  A Second Mocking Example     128
  A Third Mocking Example     129
Using Mocking System Services     130
Learning More About Test Doubles     133
Summary     133
PART II Reengineering
6  Initial Solution Review     137
Analyzing the Code     138
  Basic Architecture     138
  Code Structure     139
  Database Access     140
  Data Structures     140
  External Interfaces     141
  Application Controls Versus Form Controls     142
Analyzing the General Code Structure     142
Managing Language Migration     144
Removing Dead Code     145
Using Global Variables     145
Converting Code: It’s Not All or Nothing     149
Using an Automated Code Conversion Utility     150
Using Data Access Technologies     152
  Detecting the Data Model     152
  Detecting the Data Access Pattern     154
Summary     155
7  Planning the Project     157
Managing Expectations     157
Creating the Reengineering Team     158
Identifying Development Tools and the Build Process     159
  Introducing Source Control     160
  Introducing Defect Tracking     161
  Installing and Using a Continuous Integration (CI) Server     161
Cleaning Up Legacy Solutions     162
Establishing the Foundation      163
Refactoring to Use Basic Services     164
Refactoring to Use Advanced Services     166
Reporting Progress to Stakeholders     166
Managing Communication and Training     167
Summary     168
8  Identifying Development Tools and the Build Process     169
Using Source Control     169
  Types of Source Control     170
  A Process Example: Using a Distributed System     171
  A Second Process Example: Using a Distributed System     172
  A Third Process Example: Using a Centralized System     173
Understanding the Pros and Cons of Centralized Systems and Distributed Systems     173
  Consuming Shared Code from Others     173
  Sharing Code with Others and Reviewing Changes     174
  Backing up the Code     174
  Managing Check-in Frequency     175
  Managing Merge Conflicts     175
  Managing Control     176
  A Final Word About Pros and Cons     176
Evaluating a Hosting Service     176
  Using Apache Subversion (SVN)     177
  Using Microsoft Team Foundation Server (TFS)     177
  Using Git     179
Managing Features and Defects     179
  Managing Custom Workflow     180
  Managing Agile Development     180
  Managing Reporting     180
Using a Continuous Integration (CI) Build Server     181
Using Visual Studio 2010 Developer Tools     181
  Refactoring Tools in Visual Studio      182
  Third-Party Refactoring Tools     183
Summary     185
9  Cleaning Up Legacy Solutions     187
Organizing the File System     187
Structuring the Project      189
Working with Project Categories     190
Understanding Project Types     191
  Application-Agnostic Projects     192
  Generic UI Projects     192
  Model-agnostic Projects     193
  Model-specific Projects      193
Reengineering Project Recommendations     193
  Constants     194
  Data Transfer Objects (DTO) Projects      195 
  Interfaces     196
  Services     197
  Domain Model Projects     198
  Repository Projects     199
  Controllers, View Models, and Presenters     199
Refactoring to the Solution Structure     200
  Remove Unnecessary Using Clauses     200
  Separate Unit Tests and Integration Tests     201
  Move Classes to Appropriate Projects     202
  Move Shortcuts to Libraries     202
Refactorings that Affect Logic     203
  Move Initialization Logic into the Constructor     204
  Replace Nested IF Statements with Guards     205
  Removing Access to Entity Class Constructors     210
Summary     211
10  Establishing the Foundation     213
Adding New Projects     213
Using Prism, Unity, and Enterprise Library Versions     214
Adapting the Shell     216
  Creating the IBaseView     217
  Adapting the Current Shell     218
  Adding a Shell Controller     220
Creating the Service Locator     220
Setting Up the BootStrapper Class     223
  Creating the Winforms BootStrapper     223
  Updating the Winforms Program Class      226
  Creating a WPF Application and Bootstrapper     228
  Using Alternative Bootstrapper Configurations     232
Summary     236
11  Basic Refactoring to Services     237
Using DialogService     238
  Unit Testing     242
  Refactoring for DialogService     249
  Adding Unit Tests     250
Using LogWriterService     251
  Refactoring for LogWriterService     254
Tracking Session Information     257
  Refactoring for Session Information     258
Accessing Resources the SOA Way     260
  Refactoring for ResourceProvider     264
Using a Message Aggregator     265
  Refactoring for MessageAggregator     266
Converting Static Classes     271
Refactoring Static Classes     272
Summary     273
12  Advanced Refactoring to Services    275
Using a Repository Pattern     275
  Creating a Repository with a Domain Model     283
  Reengineering Methods to a Repository     288
  Converting Existing Code to Use a Domain Model     289
  Adding Data Validations to the Domain Model     291
  Reengineering Domain Models to Use Validations     296
Using a Generic Object Manager     296
Simplifying Complex Code with a Command Dispatcher Service     303
  Refactoring for CommandLineInterpreter     313
Summary     314
13 Refactoring to a Controller     315
Using the Legacy Approach to Form Creation     316
Preparing the View     319
Introducing the Controller     320
Enhancing the Controller     322
Summary     325
Appendix Reengineering .NET Projects with Visual Studio 2012     327
Examining Source Control with Visual Studio 2012     327
Managing Parallel Development     330
Making Changes in Isolation     334
Unit Testing with Visual Studio 2012     337
Writing a Unit Test Method     338
Running the Unit Test     339
Using the Edit-and-Continue Feature     341
Using Continuous Test Runner     344
Using Fakes to Write Unit Tests for “Untestable” Code     346
Looking for Hard-to-Maintain Code Using Code Metrics     348
Looking for Code Duplicates     350
Summary     353
Index     355

Purchase Info

ISBN-10: 0-13-296494-5

ISBN-13: 978-0-13-296494-4

Format: eBook (Watermarked)?

This eBook includes the following formats, accessible from your Account page after purchase:

ePubEPUBThe open industry format known for its reflowable content and usability on supported mobile devices.

MOBIMOBIThe eBook format compatible with the Amazon Kindle and Amazon Kindle applications.

Adobe ReaderPDFThe popular standard, used most often with the free Adobe® Reader® software.

This eBook requires no passwords or activation to read. We customize your eBook by discretely watermarking it with your name, making it uniquely yours.

Includes EPUB, MOBI, and PDF

$39.99 $31.99

Add to Cart