Review: Refactoring with C# by Matt Eland
Refactoring with C# by Matt Eland is a book I would truly recommend for developers wanting to write efficient code through refactoring
Purchase on Amazon
Buy Now on Amazon.com to grab your copy of Refactoring with C# by Matt Eland.
Refactoring code is one of the fundamental skills a developer is required to have throughout their career. Along with refactoring code, identifying code smells and technical debt are considered skills as well. Of course, there are various ways to take a messy piece of code and optimize it into something elegant and efficient.
Refactoring techniques and experience make a developer rise above the rest.
Why is refactoring important? Because as a developer continues to refactor code, they know how to provide solutions based on design patterns, techniques, and refactoring. They provide solutions to problems. That is the primary reason developers write code.
There is an art and science to refactoring code where the science is proven practices to write optimized code based on experience and an art to apply creative measures to produce an elegant solution.
While some believe refactoring skills is an innate ability all developers have (either you know how to refactor or you don't), refactoring code can be learned through books and experience.
Matt Eland's Refactoring with C# fills both aspects of art and science. His ability to take decades of experience and present the concepts of refactoring code across all levels of development gives the readers a comprehensive understanding of how to refactor C# code to create better solutions.
While the book is ~400 pages and contains 4 parts, this review will break down each part and discuss the details of the chapters under each part.
PART 1 - Refactoring with C# in Visual Studio
To ease developers into the book, Matt reviews what technical debt, code smells and what refactoring code truly means. After defining the terms, he proceeds to set up the fake company called "Cloud Skies Airlines" he uses throughout the book.
In the next chapter, he takes a simple Baggage Price Calculator and proceeds to break it down into a step-by-step refactoring process. He's able to walk the reader through the refactoring process by implementing auto properties, locals, constants, and parameters into the calculator. Of course, with every refactoring, running unit tests are necessary. He also mentions the various ways to refactor code by using one of three IDEs: Visual Studio with ReSharper, Visual Studio Code with the C# Dev Kit, or JetBrains' Rider.
Once the Calculator is completely refactored, he moves on to a boarding application to demonstrate refactoring code flow. During the refactoring of the boarding application, he addresses what I call a "sawtooth" if..then group and breaks it down into easier and more maintainable segments including switch statements and ternary operators. The object initializers, loops, and refactoring LINQ statements round out the end of the third chapter. I've always been a fan of LINQ and his transformation of collection objects using the
.Select() LINQ method is how I transform them as well.
Methods in C# are extremely common and Matt introduces how to refactor code at a method level. Such techniques demonstrated include overloading methods and creating chained (or fluent) methods to give code readability. Refactoring constructors, the addition of (and ordering of) parameters, passing expression bodies (like
Action<T,T1>) as parameters, and defining static methods and extension methods provided a better understanding of how to approach refactoring methods.
Once again, we focus our attention towards an existing app called the flight search system for the next chapter. This was one of the chapters I really wanted to dig into simply because of the object-oriented aspect of it. Some of the class refactorings included moving and renaming classes and individual files, changing namespaces, and avoiding partials and regions.
The refactoring through inheritance section was very interesting to me because of the process of refactoring by creating base and abstract classes along with interfaces and using polymorphism.
I did love the one refactoring Matt mentioned with a large number of parameters being passed into methods; the "wrapping parameters into a class" refactoring. Passing numerous parameters into a method is more common in the industry than one may think. Creating a class to hold these values are definitely encouraged.
PART 2 - Refactoring Safely
At the beginning of this part, chapter 6 focuses on all of the different types of testing, the various testing libraries one can use to unit test (like xUnit and MSTest) as well as how to create a unit test. He also mentions code coverage where "if a test causes a line of code to run, it is considered covered; otherwise, it is considered not covered." I definitely agree with Matt about how a high code coverage can be deceptive.
With test-driven development as the next chapter, the process for refactoring isn't too different except for one exception: "you write your tests before you write a new feature or to implement a new fix." The process is to write a failing test, make the test pass, and then clean up and refactor the code. Rinse and repeat.
After discussing unit testing, Matt looks at the common principles developers should keep in mind when "refactoring safely." The DRY, KISS, and SOLID principles are mentioned and demonstrated through code samples. In addition to these principles, Matt also mentions how a system with high cohesion and low coupling can give the greatest flexibility throughout your development.
So surely, there would be some tools to help you with your testing? Matt has you covered as well with actual code samples. He explains each NuGet package used throughout the unit tests.
The packages he uses include Shouldly and FluentAssertions which provide human-readable assertions, Bogus which provides test data for your unit tests, Moq and NSubstitute for creating isolated mocks for testing, and Snapper and Scientist.NET for identifying issues when complex objects change.
In the following chapter, Matt adds a new API to the Cloudy Airlines system. With that new API, he discusses how to write defensive code through techniques like validating input, protecting against nulls, how immutable classes are encouraged, and using records instead of classes.
Matt also introduces one of my favorite .NET 8.0 features called primary constructors which I'm starting to use a lot as well. It puts your classes on a diet by cutting down the extra 3+ lines. Also, when using the with expression on records is an excellent way to clone objects (which I didn't know).
As Matt continues, he mentions using pattern matching and generics as a way to refactor code into smaller, more efficient pieces which is part of the evolution of C#. As the language evolves, C# implements better syntax making the language less terse.
PART 3 - Advanced Refactoring with AI and Code Analysis
Moving into Part 3, Matt brings attention to the latest craze of refactoring code through AI (artificial intelligence) using GitHub's Copilot and GitHub Copilot Chat. He examines the better ways of how to write better prompts to get the most out of GitHub Copilot and GitHub Copilot Chat in Visual Studio.
After GitHub Copilot, Matt looks at some of various tools on performing code analysis on a codebase, including Visual Studio's built-in tools like Cyclomatic Complexity, Class Coupling, and Maintainability Index. While these built-in tools give you a fundamental way of examining a codebase as a whole, he also covers how to configure code analysis rulesets.
The three tools he uses in the chapter include SonarCloud, SonarQube, and NDepend (which I absolutely recommend). Each one is a top-quality code analysis tool in their own right and definitely assist with examining any codebase thoroughly.
If you've used Visual Studio enough, you've no doubt seen the Roslyn Analyzers always analyzing your code as you type and identifying issues in your codebase.
Matt takes the reader step-by-step on how to create, test, debug, and package a Roslyn Analyzer in Visual Studio. What an awesome lift for the chapter! If your team has special requirements for a company's codebase, you can write your own analyzer to trigger a warning when compiling or writing code.
Since the reader knows how to create a Roslyn Analyzer, the next chapter moves towards how to refactor code using a Roslyn Analyzer and provide code fixes to the affected code. Again, how to create a Roslyn Analyzer is great for the chapter, but an analyzer which identifies and fixes the code is a next-level for the book. A word of warning: it's not for the faint of heart, but Matt does take you step-by-step through it explaining everything along the way (yes, definitely a teacher).
With these new changes made to the analyzer, he tests his analyzer with the RoslynTestKit, packages the extension, and publishes it to NuGet.
PART 4 - Refactoring in the Enterprise
Now that the technical stuff is out of the way, developers need to know how to refactor code on an enterprise scale.
Each chapter in Part 4 is critical to a developer's career when placed in an corporate position. Why?
- What is the company's stance on coding standards?
- How do you communicate technical debt to management?
- How do you approach brittle code when seniors say "don't touch that! It'll break the system"?
- What techniques can you incorporate into the enterprise for performing a large-scale refactoring?
In my career, I've been in enterprise discussions (oh, and arguments) about refactoring code and can identify with Matt on each chapter. So believe me when I say Part 4 contains some of the most important chapters throughout the book from an enterprise perspective.
He starts off Part 4 with how to communicate technical debt to others including management and senior developers. He continues by discussing the oh-so-common sayings used on a daily basis.
- "We have a deadline. Don't worry about refactoring!"
- "Refactoring doesn't have any value."
- "Don't worry about refactoring it. It's a prototype and won't be deployed to production." (uh-huh)
- "Don't worry about the quality of the code. We'll begin the rewrite in a month or two." (again...uh-huh)
I'm guessing every developer has heard this before. Matt breaks down each concern and tries to nullify each comment as to why it's important to refactor code.
Along with his concrete reasoning to refactor code, he also describes the best way to get organizational buy-in to refactor code on a regular basis.
Once through the communication barrier, Matt focuses on the team aspect of enterprise refactoring using code standards throughout Visual Studio and how to adjust Visual Studio to use specific formatting and cleanup functions in a team atmosphere.
Matt reviews various ways to implement refactoring into an Agile environment along with some strategies like scheduling specific sprints with strictly refactoring code and refactoring sabbaticals. The refactoring sabbaticals is a new approach I've not heard of before.
Finally, if you've been in an enterprise-level environment, his discussions about performing large-scale refactorings using the "strangler fig pattern" and deploying software using feature flags and phased rollouts using blue/green deployments are common approaches in the enterprise.
Refactoring using C# is one of those books that give developers a look into what's required to become a better developer who can refactor code efficiently whether it's their code or someone else's code. It also gives developers an insight as to how developers, in a corporate or freelance environment, refactor code on a large-scale or individually.
There hasn't been a C# refactoring book I've seen in a while which covers this much depth. This book can give developers a huge lift in their career by implementing what Matt has demonstrated in this book.
After each chapter, I like how he continually summarizes each chapter by unit testing the code. This is paramount when refactoring (as mentioned in Part 2). I like the questions at the end and further reading for the readers to continue their refactoring journey (yep, he's a teacher).
The projects in each part provides not only a "real-world" example to demonstrate the refactoring approach, but also gives code snippets because when writing code, what developer doesn't want to see code on how something works?
I cannot emphasize enough that his experience and development (and teacher) chops shines through in this book. I completely agree with everything he's addressed in the book when it comes to refactoring code.
..oh, and I would definitely recommend this book to other developers.
Refactoring with C#: Safely improve .NET applications and pay down technical debt with Visual Studio, .NET 8, and C# 12: Eland, Matt, Smith, Steve: 9781835089989: Amazon.com: Books is out and currently available on Amazon.
Purchase on Amazon
Buy Now on Amazon.com to grab your copy of Refactoring with C# by Matt Eland.
Have you purchased this book? Do you agree with everything he's mentioned in the book? Or disagree? Post your comments below and let's discuss.