.NET Best Practices: Architecture & Design Patterns

5 days
UARCH
5 days

Upcoming Sessions

Date:

Format:

Price:

Location:

Book now

Date:

Format:

Price:

Location:

Book now

Date:

Format:

Price:

Location:

Book now

Date:

Format:

Price:

Book now

Interested in a private company training? Request it here.

Principles to get acquainted with

S.O.L.I.D principles

The S.O.L.I.D principles were introduced by Robert C. Martin (also known as Uncle Bob) in 2000. The intention behind these principles is to make software designs more understandable, easier to maintain, and easier to extend. These principles are essential for every developer to know because they assist in writing better code and in better understanding code that was written with these principles in mind.

  • S - Single Responsibility
  • O - Open/Closed
  • L - Liskov Substitution
  • I - Interface Segregation
  • D - Dependency Inversion

Design Patterns

Introduction to Patterns

One might not believe it, but design patterns did not originate in software architecture. Instead, patterns were first described in the 1970s by a real 'bricks and mortar' architect. A pattern is defined as a reusable solution to a common problem, without dictating the exact implementation. This characteristic makes patterns an ideal learning tool and a powerful means for communicating design ideas. Of course, there are also anti-patterns—approaches that are frequently used but are better avoided.

  • What is a Pattern?
  • The Gang of Four: Erich Gamma, Ralph Johnson, Richard Helm and John Vlissides.
  • Different kinds of design patterns: creational, structural and behavioral patterns.
  • Patterns everywhere: the difference between implementation, design and architecture patterns...
  • When to apply patterns, and when not to.
  • Some anti-patterns, such as Loosy-Goosy.

Creational patterns

When developing software, you often find yourself continuously creating new objects. While the fundamental act of creating new objects is not inherently problematic, it can lead to design challenges or increased complexity. Creational patterns can assist you in managing object creation in a way that is appropriate for the situation.

  • What is a Singleton?
  • Singleton implementation choices in .NET
  • LAB: Building a Singleton in .NET
  • Factory Method - delegating/hiding the creation of objects to a factory
  • Abstract Factory - abstracting to a factory to create families of objects
  • LAB: Implementing an Abstract Factory

Behavioral patterns

Once your objects are created, they begin to interact. Without careful design, these interactions can quickly lead to tightly coupled code. Behavioral design patterns assist in identifying common communication patterns between objects and in implementing these patterns effectively. By applying these patterns correctly, you can enhance the flexibility of interactions between objects.

  • Template Method - defer exact parts of an algorithm to inheriting classes, delegates, ...
  • LAB: Building a Template Method for a board game
  • Strategy - template method without the annoying inheritance
  • LAB: Implementing a Builder as a Strategy
  • Chain of Responsibility - strategy to go through a chain of strategies
  • LAB: Using a Chain of Responsibility to implement a Builder
  • State - defer state dependending logic to state classes, state machines,
  • Using the Stateless library
  • LAB: Implementing a VCR with the State patterns using the Stateless library
  • Iterator - providing a generic way of navigating through collections, yield is your friend, asynchronously iterating a collection
  • Performance considerations on implementing IEnumerable
  • Observer - notifying whoever is interested in what you have to say, events vs. delegates
  • Mediator - providing two-way communication between objects unaware of one another, correcly implementing INotifyPropertyChanged
  • LAB: Avoiding the String-based programming anti-pattern

Structural patterns

Created objects do not tend to stand on their own. No, they start encapsulating other objects trying to create structure in, what otherwise would be a chaotic software environment. Structural patterns help at identifying and setting up relationships between objects.

  • Adapter - plugging in different objects into your code that do not fit
  • LAB: Building INotifyPropertyChanged as a generic Adapter
  • Decorator - altering the behavior of an object without the caller realising it
  • LAB: Changing IComparable<T> with a Decorator
  • Composite - tree structures are here to help you, working with Linq Expressions
  • Facade - hiding the complexity of subsystems from the caller
  • Flyweight - reduce memory consumption by preventing unnecessary creation of object
  • Proxy - proxying requests made to the subject without changing the behavior

Building your own little programming language with some patterns - Fun!

Programming languages themselves are built upon a variety of patterns in their implementation. In this chapter, you will construct your own compact programming language that, incidentally, is designed to be extensible. Throughout this process, you will uncover and apply several important patterns that are not only crucial in the realm of programming language development but are also perfectly applicable beyond this scope!

  • Interpreter: Build your own expressive language-grammar and execute it.
  • How LINQ uses Interpreter - and how you can take advantage of it yourself.
  • Builder: Hide how complex hierarchies of objects get built - and allow variations.
  • XAML as the ultimate builder.
  • Reflection: the .NET way for implementing your own builder.
  • How NOT to use reflection.
  • LAB: Building your own calculator with Interpreter and Builder
  • Visitor: When you need a lot of different operations on the same object structure.
  • Building a pretty-printer using Visitor.
  • Implementing Visitor the dynamic way.
  • LAB: Implementing a Visitor to walk over a complex hierarchy of objects

Automating your Code with Source Generators

Source Generators revolutionize the way we approach coding in C# by automating the creation of routine code directly within the C# compiler. This innovation not only circumvents the inefficiencies of reflection but also lays the groundwork for efficient Ahead-Of-Time (AOT) compilation, significantly optimizing performance.

  • What are Source Generators?
  • .NET 7 and 8 Source Generators
  • Implementing an incremental Source Generator
  • Source Generator Best Practices
  • LAB: Building your Own Source Generator

Model-View-Whatever

Most developers are not naturally skilled as graphic designers. This recognition has led to the development of design patterns that enable developers to concentrate on coding the application's behavior while allowing graphic designers to create compelling user interfaces. The cornerstone among these patterns is known as Model-View-Whatever (MVW), with Whatever being adaptable based on the specific technology in use. Grasping the MVW pattern is crucial, as it forms the foundation for developing both Windows and web applications.

  • Model-View-Controller: An ancient pattern back in fashion.
  • ASP.NET MVC - an introduction.
  • MVVM in WPF/MAUI - MVW taking advantage of powerful databinding capabilities.
  • Command: Encapsulate behavior in objects.
  • Implementing commands using closures.
  • LAB: Using MVVM in a WPF application

Reactive Programming

Have you ever encountered Reactive Programming? This significant advancement teaches you to harness Observables for programming. Through this approach, you'll learn to address common challenges that traditional Object-Oriented Programming finds difficult to solve. Additionally, we will delve into the Fluxor/Redux pattern, further expanding our toolkit for managing complex application states.

  • What are Observables?
  • Using Reactive Extensions.
  • Applying the Redux pattern to simplify complex applications.
  • LAB: Implementing a search system with Observables

Framework building

Design Patterns Applied: Developing your own reusable library.

When do you most need patterns? The answer is particularly when you're developing a framework on your own. Building a framework involves integrating new features while maintaining backward compatibility, a challenge that can be significantly simplified through the proper application of patterns. Therefore, in this final part of the training, we will construct a reusable library. During this process, we will encounter several challenges and address them by applying the appropriate patterns.

  • Adding the GoF Command pattern to MVVM.
  • Using interfaces for flexibility.
  • Building Command Objects - extending WPF's ICommand interface.
  • Adding Undo and Redo functionality to the command pattern.
  • Using a CommandManager class.
  • Challenge: retro-fitting our commands into MVVM without lots of changes.
  • Implementing Undo-Redo using the Memento pattern.
  • Choosing whether or not to add the Prototype pattern.
  • Ideas on how to proceed with the command pattern.
  • LAB: Implementing Undo/Redo logic as a reusable library

So, how can you become a better developer? One of the best ways is to learn about design patterns. Design Patterns provide reusable solutions for common software design challenges. In this training, we identify software design problems and explore how to address them using the most suitable Design Pattern. All examples and labs use the latest LTS version of .NET and Visual Studio. Labs also work with any recent .NET and VS version.

This course is intended for experienced programmers who are familiar with C# and have a working experience of .NET.

Contact Us
  • Address:
    U2U nv/sa
    Z.1. Researchpark 110
    1731 Zellik (Brussels)
    BELGIUM
  • Phone: +32 2 466 00 16
  • Email: info@u2u.be
  • Monday - Friday: 9:00 - 17:00
    Saturday - Sunday: Closed
Say Hi
© 2024 U2U All rights reserved.