Refactoring with C#: Safely improve .NET applications and pay down technical debt with Visual Studio, .NET 8, and C# 12 9781835089989

Key Features Apply a wide range of refactoring techniques using the latest tools and features of C# Discover ways to saf

138 119 25MB

English Pages 567 Year 2023

Report DMCA / Copyright

DOWNLOAD EPUB FILE

Table of contents :
Refactoring with C#
Foreword
Contributors
About the author
About the reviewers
Preface
Who this book is for
What this book covers
To get the most out of this book
Download the example code files
Conventions used
Get in touch
Share Your Thoughts
Download a free PDF copy of this book
Part 1: Refactoring with C# in Visual Studio
1
Technical Debt, Code Smells, and Refactoring
Understanding technical debt and legacy code
Where technical debt comes from
Identifying code smells
Introducing refactoring
Refactoring tools in Visual Studio
Case study – Cloudy Skies Airlines
Summary
Questions
Further reading
2
Introduction to Refactoring
Technical requirements
Refactoring a baggage price calculator
Converting properties to auto properties
Introducing locals
Introducing constants
Introducing parameters
Removing unreachable and unused code
Extracting methods
Refactoring manually
Testing refactored code
Refactoring in other editors
Refactoring in Visual Studio Code with the C# Dev Kit
Refactoring in JetBrains Rider
Refactoring in Visual Studio with ReSharper
Summary
Questions
Further reading
3
Refactoring Code Flow and Iteration
Technical requirements
Refactoring the boarding app
Controlling program flow
Inverting if statements
Dropping else statements after return statements
Restructuring if statements
Using ternary operators
Converting if statements into switch statements
Converting to switch expressions
Instantiating objects
Replacing var with explicit Types
Simplifying creation with target-typed new
Using object initializers
Iterating over collections
Introducing foreach
Converting to for loops
Converting to LINQ
Refactoring LINQ statements
Choosing the correct LINQ method
Combining LINQ methods
Transforming with Select
Reviewing and testing our refactored code
Summary
Questions
Further reading
4
Refactoring at the Method Level
Technical requirements
Refactoring the flight tracker
Refactoring methods
Changing method access modifiers
Renaming methods and parameters
Overloading methods
Chaining methods
Refactoring constructors
Generating constructors
Chaining constructors
Refactoring parameters
Reordering parameters
Adding parameters
Introducing optional parameters
Removing parameters
Refactoring to functions
Using expression-bodied members
Passing functions as parameters with actions
Returning data from Actions with Funcs
Introducing static methods and extension methods
Making methods static
Moving static members to another type
Creating extension methods
Reviewing and testing our refactored code
Summary
Questions
Further reading
5
Object-Oriented Refactoring
Technical requirements
Refactoring the flight search system
Organizing classes via refactoring
Moving classes to individual files
Renaming files and classes
Changing namespaces
Avoiding partial classes and regions
Refactoring and inheritance
Overriding ToString
Generating equality methods
Extracting a base class
Moving interface implementations up the inheritance tree
Controlling inheritance with abstract
Communicating intent with abstract
Introducing abstract members
Converting abstract methods to virtual methods
Refactoring for better encapsulation
Encapsulating fields
Wrapping parameters into a class
Wrapping properties into a class
Favoring composition over inheritance
Improving classes with interfaces and polymorphism
Extracting interfaces
Providing default interface implementations
Introducing polymorphism
Reviewing and testing our refactored code
Summary
Questions
Further reading
Part 2: Refactoring Safely
6
Unit Testing
Technical requirements
Understanding testing and unit tests
Types of tests and the testing pyramid
Unit tests
Testing code with xUnit
Creating an xUnit Test Project
Connecting the xUnit Test Project to your main project
Writing your first unit test
Organizing tests with Arrange/Act/Assert
Understanding tests and exceptions
Adding additional test methods
Refactoring unit tests
Parameterizing tests with Theory and InlineData
Initializing test code with constructors and fields
Sharing test code with methods
Exploring other testing frameworks
Testing with NUnit
Testing with MSTest
Adopting a testing mindset
Incorporating testing into your workflow
Isolating dependencies
Evaluating good and bad tests
Thoughts on code coverage
Summary
Questions
Further reading
7
Test-Driven Development
Technical requirements
What is Test-Driven Development?
Test-Driven Development with Visual Studio
Setting the starting balance
Adding miles and generating methods
Redeeming miles and refactoring tests
When to use Test-Driven Development
Summary
Questions
Further reading
8
Avoiding Code Anti-Patterns with SOLID
Identifying anti-patterns in C# code
Writing SOLID code
Single Responsibility Principle
Open-Closed Principle
Liskov Substitution Principle
Interface Segregation Principle
Dependency Inversion Principle
Considering other architectural principles
Learning the DRY principle
KISS principle
Understanding high cohesion and low coupling
Summary
Questions
Further reading
9
Advanced Unit Testing
Technical requirements
Creating readable tests with Shouldly
Installing the Shouldly NuGet package
Writing readable assertions with Shouldly
Writing readable assertions with FluentAssertions
Testing performance with Shouldly
Generating test data with Bogus
Mocking dependencies with Moq and NSubstitute
Understanding the need for mocking libraries
Creating mock objects with Moq
Programming Moq return values
Verifying Moq calls
Mocking with NSubstitute
Pinning tests with Snapper
Experimenting with Scientist .NET
Summary
Questions
Further reading
10
Defensive Coding Techniques
Technical requirements
Introducing the Cloudy Skies API
Validating inputs
Performing basic validation
Using the nameof keyword
Validation with guard clauses
Guard clauses with the GuardClauses library
Using CallerMemberInformation attributes
Protecting against null
Enabling nullability analysis in C#
Using nullability operators
Moving beyond classes
Preferring immutable classes
Using required and init-only properties
Primary constructors
Converting classes into record classes
Cloning objects using with expressions
Advanced type usage
Exploring pattern matching
Using generics to reduce duplication
Introducing type aliases with the using directive
Summary
Questions
Further reading
Part 3: Advanced Refactoring with AI and Code Analysis
11
AI-Assisted Refactoring with GitHub Copilot
Technical requirements
Introducing GitHub Copilot
Understanding GitHub’s predictive model
Starting the conversation with GitHub Copilot Chat
Getting started with GitHub Copilot in Visual Studio
Installing and activating GitHub Copilot
Getting access to GitHub Copilot
Generating suggestions with GitHub Copilot
Interacting with GitHub Copilot Chat
Refactoring with GitHub Copilot Chat
GitHub Copilot Chat as a code reviewer
Targeted refactoring with GitHub Copilot Chat
Drafting documentation with GitHub Copilot Chat
Generating test stubs with GitHub Copilot Chat
Understanding the limits of GitHub Copilot
Data privacy and GitHub Copilot
Concerns around GitHub Copilot and public code
Case study: Cloudy Skies Airline
Summary
Questions
Further reading
12
Code Analysis in Visual Studio
Technical requirements
Calculating code metrics in Visual Studio
Performing code analysis in Visual Studio
Analyzing your solution using the default ruleset
Configuring code analysis rulesets
Responding to code analysis rules
Treating warnings as errors
Exploring advanced code analysis tools
Tracking code metrics with SonarCloud and SonarQube
In-depth .NET analysis with NDepend
Case study – Cloudy Skies Airline
Summary
Questions
Further reading
13
Creating a Roslyn Analyzer
Technical requirements
Understanding Roslyn Analyzers
Installing the extension development workload and DGML editor
Introducing Syntax Visualizer
Creating a Roslyn Analyzer
Adding the analyzer project to our solution
Defining a code analysis rule
Analyzing symbols with our Roslyn Analyzer
Tips for writing Roslyn Analyzers
Testing Roslyn Analyzers with RoslynTestKit
Adding a Roslyn Analyzer test project
Creating AnalyzerTestFixture
Verifying that our Roslyn Analyzer doesn’t flag good code
Verifying that our Roslyn Analyzer flags bad code
Debugging Roslyn Analyzers
Sharing analyzers as Visual Studio extensions
Creating a Visual Studio extension (VSIX) for your Roslyn Analyzer
Summary
Questions
Further reading
14
Refactoring Code with Roslyn Analyzers
Technical requirements
Case study – Cloudy Skies Airlines
Building a Roslyn Analyzer code fix
Creating a CodeFixProvider
Registering a code fix
Modifying the document with a code fix
Testing Code Fixes with RoslynTestKit
Publishing Roslyn Analyzers as NuGet packages
Understanding NuGet package deployment
Building a NuGet package
Deploying the NuGet package
Referencing the NuGet package
Packaging a CodeFixProvider as an extension
Summary
Questions
Further reading
Part 4: Refactoring in the Enterprise
15
Communicating Technical Debt
Overcoming barriers to refactoring
Urgent deadlines
“Don’t touch high-risk code”
“This code is going away, don’t spend time on it”
End-of-life applications
“Just do the minimum required”
“Refactoring doesn’t provide business value”
Communicating technical debt
Technical debt as risk
Creating a risk register
Alternatives to a risk register
Prioritizing technical debt
Calculating risk priorities with a risk score
The “gut feeling” approach
Getting organizational buy-in
Setting up the conversation
Anticipating questions and objections
Different approaches for different leaders
The importance of communication
Case study – Cloudy Skies Airlines
Summary
Questions
Further reading
16
Adopting Code Standards
Technical requirements
Understanding code standards
Establishing code standards
Formatting and code cleanup in Visual Studio
Applying code standards with EditorConfig
Reviewing our starter code
Adding an EditorConfig
Customizing EditorConfigs
Summary
Questions
Further reading
17
Agile Refactoring
Refactoring in an agile environment
Key elements of agile teams
Understanding obstacles to refactoring
Succeeding with agile refactoring strategies
Dedicated work items for refactoring efforts
Refactoring code as it changes
Refactoring sprints
Refactoring sabbaticals
Accomplishing large-scale refactorings
Why large refactorings are difficult
The rewrite trap
Lessons from the ship of Theseus
Upgrading projects with.NET Upgrade Assistant
Refactoring and the strangler fig pattern
Recovering when refactoring goes wrong
The impact of failed refactorings
Establishing safety in agile environments
Deploying large-scale refactorings
Using feature flags
Phased rollouts and blue/green deployments
The value of continuous integration and continuous delivery
Case study – Cloudy Skies Airlines
Summary
Toward more sustainable software
Questions
Further reading
Index
Why subscribe?
Other Books You May Enjoy
Packt is searching for authors like you
Share Your Thoughts
Download a free PDF copy of this book

Refactoring with C#: Safely improve .NET applications and pay down technical debt with Visual Studio, .NET 8, and C# 12
 9781835089989

  • 0 0 0
  • Like this paper and download? You can publish your own PDF file online for free in a few minutes! Sign Up
Recommend Papers