0%

Code Like a Pro in C# teaches you to how write clean C# code that’s suitable for enterprise applications. In this book, you’ll refactor a legacy codebase by applying modern C# techniques. You’ll explore tools like Entity Framework Core, design techniques like dependency injection, and key practices like testing and clean coding. It’s a perfect path to upgrade your existing C# skills or shift from another OO language into C# and the .NET ecosystem.

Table of Contents

  1. inside front cover
    1. Clean Code Checklist
  2. Code like a Pro in C#
  3. Copyright
  4. contents
  5. front matter
    1. preface
    2. acknowledgments
    3. about this book
    4. Who should read this book
    5. How this book is organized: A roadmap
    6. About the code
    7. liveBook discussion forum
    8. about the author
    9. about the cover illustration
  6. Part 1 Using C# and .NET
  7. 1 Introducing C# and .NET
    1. 1.1 Why work in C#?
    2. 1.1.1 Reason 1: C# is economical
    3. 1.1.2 Reason 2: C# is maintainable
    4. 1.1.3 Reason 3: C# is developer friendly and easy to use
    5. 1.2 Why not work in C#?
    6. 1.2.1 Operating system development
    7. 1.2.2 Real-time operating system embedded development in C#
    8. 1.2.3 Numerical computing and C#
    9. 1.3 Switching to C#
    10. 1.4 What you will learn in this book
    11. 1.5 What you will not learn in this book
    12. Summary
  8. 2 .NET and how it compiles
    1. 2.1 What is the .NET Framework?
    2. 2.2 What is .NET 5?
    3. Exercises
    4. 2.3 How CLI-compliant languages are compiled
    5. 2.3.1 Step 1: C# code (high-level)
    6. 2.3.2 Step 2: Common Intermediate Language (assembly level)
    7. 2.3.3 Step 3: Native code (processor level)
    8. Exercises
    9. Summary
  9. Part 2 The existing codebase
  10. 3 How bad is this code?
    1. 3.1 Introducing Flying Dutchman Airlines
    2. 3.2 Pieces of the puzzle: Taking a look at our requirements
    3. 3.2.1 Object-relational mapping
    4. 3.2.2 The GET /flight endpoint: Retrieving information on all flights
    5. 3.2.3 The GET /flight/{flightNumber} endpoint: Getting specific flight information
    6. 3.2.4 The POST /booking/{flightNumber} endpoint: Booking a flight
    7. 3.3 Coming to terms with the existing codebase
    8. 3.3.1 Assessing the existing database schema and its tables
    9. 3.3.2 The existing codebase: Web service configuration files
    10. 3.3.3 Considering models and views in the existing codebase
    11. Summary
  11. 4 Manage your unmanaged resources!
    1. 4.1 The FlightController: Assessing the GET /flight endpoint
    2. 4.1.1 The GET /flight endpoint and what it does
    3. 4.1.2 Method signature: The meaning of ResponseType and typeof
    4. 4.1.3 Collecting flight information with collections
    5. 4.1.4 Connection strings, or how to give a security engineer a heart attack
    6. 4.1.5 Using IDisposable to release unmanaged resources
    7. 4.1.6 Querying a database with SqlCommand
    8. 4.2 The FlightController: Assessing GET /flight/{flightNumber}
    9. 4.3 The FlightController: POST /flight
    10. 4.4 The FlightController: DELETE /flight/{flightNumber}
    11. Exercises
    12. Summary
  12. Part 3 The database access layer
  13. 5 Setting up a project and database with Entity Framework Core
    1. 5.1 Creating a .NET 5 solution and project
    2. 5.2 Setting up and configuring a web service
    3. 5.2.1 Configuring a .NET 5 web service
    4. 5.2.2 Creating and using HostBuilder
    5. 5.2.3 Implementing the Startup class
    6. 5.2.4 Using the repository/service pattern for our web service architecture
    7. 5.3 Implementing the database access layer
    8. 5.3.1 Entity Framework Core and reverse-engineering
    9. 5.3.2 DbSet and the Entity Framework Core workflow
    10. 5.3.3 Configuration methods and environment variables
    11. 5.3.4 Setting an environment variable on Windows
    12. 5.3.5 Setting an environment variable on macOS
    13. 5.3.6 Retrieving environment variables at run time in your code
    14. Exercises
    15. Summary
  14. Part 4 The repository layer
  15. 6 Test-driven development and dependency injection
    1. 6.1 Test-driven development
    2. Exercises
    3. 6.2 The CreateCustomer method
    4. 6.2.1 Why you should always validate input arguments
    5. 6.2.2 Using “arrange, act, assert” to write unit tests
    6. 6.2.3 Validating against invalid characters
    7. 6.2.4 In-lining test data with the [DataRow] attribute
    8. 6.2.5 Object initializers and autogenerated code
    9. 6.2.6 Constructors, reflection, and asynchronous programming
    10. 6.2.7 Locks, mutexes, and semaphores
    11. 6.2.8 Synchronous to asynchronous execution . . . continued
    12. 6.2.9 Testing Entity Framework Core
    13. 6.2.10 Controlling dependencies with dependency injection
    14. Exercises
    15. Summary
  16. 7 Comparing objects
    1. 7.1 The GetCustomerByName method
    2. 7.1.1 Question marks: Nullable types and their applications
    3. 7.1.2 Custom exceptions, LINQ, and extension methods
    4. 7.2 Congruence: From the Middle Ages to C#
    5. 7.2.1 Creating a “comparer” class using EqualityComparer<T>
    6. 7.2.2 Testing equality by overriding the Equals method
    7. 7.2.3 Overloading the equality operator
    8. Exercises
    9. Summary
  17. 8 Stubbing, generics, and coupling
    1. 8.1 Implementing the Booking repository
    2. 8.2 Input validation, separation of concerns, and coupling
    3. Exercises
    4. 8.3 Using object initializers
    5. 8.4 Unit testing with stubs
    6. 8.5 Programming with generics
    7. 8.6 Providing default arguments by using optional parameters
    8. 8.7 Conditionals, Func, switches, and switch expressions
    9. 8.7.1 The ternary conditional operator
    10. 8.7.2 Branching using an array of functions
    11. 8.7.3 Switch statements and expressions
    12. 8.7.4 Querying for pending changes in Entity Framework Core
    13. Exercises
    14. Summary
  18. 9 Extension methods, streams, and abstract classes
    1. 9.1 Implementing the Airport repository
    2. 9.2 Getting an Airport out of the database by its ID
    3. 9.3 Validating the AirportID input parameter
    4. 9.4 Output streams and being specifically abstract
    5. 9.5 Querying the database for an Airport object
    6. 9.6 Implementing the Flight repository
    7. 9.6.1 The IsPositive extension method and “magic numbers”
    8. 9.6.2 Getting a flight out of the database
    9. Exercises
    10. Summary
  19. Part 5 The service layer
  20. 10 Reflection and mocks
    1. 10.1 The repository/service pattern revisited
    2. 10.1.1 What is the use of a service class?
    3. Exercises
    4. 10.2 Implementing the CustomerService
    5. 10.2.1 Setting up for success: Creating skeleton classes
    6. 10.2.2 How to delete your own code
    7. Exercises
    8. 10.3 Implementing the BookingService
    9. 10.3.1 Unit testing across architectural layers
    10. 10.3.2 The difference between a stub and a mock
    11. 10.3.3 Mocking a class with the Moq library
    12. 10.3.4 Calling a repository from a service
    13. Exercises
    14. Summary
  21. 11 Runtime type checking revisited and error handling
    1. 11.1 Validating input parameters of a service layer method
    2. 11.1.1 Runtime type checks with the is and as operators
    3. 11.1.2 Type checking with the is operator
    4. 11.1.3 Type checking with the as operator
    5. 11.1.4 What did we do in section 11.1?
    6. 11.2 Cleaning up the BookingServiceTests class
    7. 11.3 Foreign key constraints in service classes
    8. 11.3.1 Calling the Flight repository from a service class
    9. Exercises
    10. Summary
  22. 12 Using IAsyncEnumerable<T> and yield return
    1. 12.1 Do we need an AirportService class?
    2. 12.2 Implementing the FlightService class
    3. 12.2.1 Getting information on a specific flight from the FlightRepository
    4. 12.2.2 Combining two data streams into a view
    5. 12.2.3 Using the yield return keywords with try-catch code blocks
    6. 12.2.4 Implementing GetFlightByFlightNumber
    7. Exercises
    8. Summary
  23. Part 6 The controller layer
  24. 13 Middleware, HTTP routing, and HTTP responses
    1. 13.1 The controller class within the repository/service pattern
    2. 13.2 Determining what controllers to implement
    3. 13.3 Implementing the FlightController
    4. 13.3.1 Returning HTTP responses with the IActionResult interface (GetFlights)
    5. 13.3.2 Injecting dependencies into a controller using middleware
    6. 13.3.3 Implementing the GET /Flight/{FlightNumber} endpoint
    7. 13.4 Routing HTTP requests to controllers and methods
    8. Exercises
    9. Summary
  25. 14 JSON serialization/ deserialization and custom model binding
    1. 14.1 Implementing the BookingController class
    2. 14.1.1 Introduction to data deserialization
    3. 14.1.2 Using the [FromBody] attribute to deserialize incoming HTTP data
    4. 14.1.3 Using a custom model binder and method attribute for model binding
    5. 14.1.4 Implementing the CreateBooking endpoint method logic
    6. 14.2 Acceptance testing and Swagger middleware
    7. 14.2.1 Manual acceptance testing with an OpenAPI specification
    8. 14.2.2 Generating an OpenAPI specification at runtime
    9. 14.3 The end of the road
    10. Summary
  26. appendix A Exercise answers
    1. Chapter 2: .NET and how it compiles
    2. Chapter 4: Manage your unmanaged resources!
    3. Chapter 5: Setting up a project and database with Entity Framework Core
    4. Chapter 6: Test-driven development and dependency injection
    5. Chapter 7: Comparing objects
    6. Chapter 8: Stubbing, generics, and coupling
    7. Chapter 9: Extension methods, streams, and abstract classes
    8. Chapter 10: Reflection and mocks
    9. Chapter 11: Runtime type checking revisited and error handling
    10. Chapter 12: Using IAsyncEnumerable<T> and yield return
    11. Chapter 13: Middleware, HTTP routing, and HTTP responses
  27. appendix B Clean code checklist
  28. appendix C Installation guides
  29. appendix D OpenAPI FlyTomorrow
  30. appendix E Reading list
  31. index
  32. inside back cover
    1. Clean Code Checklist
3.137.185.180