Refactoring with C# Safely Improve .NET Applications and Pay down Technical Debt with Visual Studio, .NET 8, and C# 12
Software projects start as brand-new greenfield projects, but invariably become muddied in technical debt far sooner than you’d expect. In Refactoring with C#, you'll explore what technical debt is and how it arises before walking through the process of safely refactoring C# code using modern t...
Otros Autores: | , |
---|---|
Formato: | Libro electrónico |
Idioma: | Inglés |
Publicado: |
Birmingham, England :
Packt Publishing Ltd
[2023]
|
Edición: | First edition |
Materias: | |
Ver en Biblioteca Universitat Ramon Llull: | https://discovery.url.edu/permalink/34CSUC_URL/1im36ta/alma991009785406406719 |
Tabla de Contenidos:
- Cover
- Title Page
- Copyright and Credits
- Foreword
- Contributors
- Table of Contents
- Preface
- Part 1: Refactoring with C# inVisual Studio
- Chapter 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
- Chapter 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
- Chapter 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
- Chapter 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
- Chapter 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
- Chapter 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
- Chapter 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
- Chapter 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
- Chapter 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
- Chapter 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
- Chapter 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
- Chapter 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
- Chapter 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
- Chapter 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.