Gradually Improving Software Design with examples in C#
Gradually Improving Software Design is the series of lectures that are following one specific line of thought.
Through a number of real world examples, attendees will get acquainted with design and coding practices that will help them improve their code “here and now”.
Below is the complete list of lectures, divided into 4-hour blocks. The entire training takes 20 hours.
In any particular case, it is possible to join or divide lectures in a different way, or even to choose a subset and combine them into a different course.
List of lectures divided into 4-hour blocks
Principles of Object-Oriented Programming 1
This block is useful to programmers of all levels of expertise and knowledge. Through a process of refactoring, redesigning and extending a number of examples, attendees are acquainted with principles of writing clean, extendible and maintainable object-oriented code.
- Emergent Objects – Simplifying code through removal of optional arguments; letting objects emerge to substitute branching instructions, loops, etc.
- If-then-else and guard clauses – Understanding the purpose of branching and guard clauses in order to use them properly and where appropriate.
- Loops and sequences – Understanding the purpose of loops in light of theory of sequences. Special attention paid to implementations of IEnumerable interface.
- Map-reduce principle – Capitalizes on theory of sequences, leading to gross simplification of code that works with collections of data.
- Class dependencies and strategies – Introduces dependencies and their special cases; explains the effect of dependencies on polymorphic execution.
- Value objects – Distinguishes value objects from entities; explains aliasing bugs and the ways they can be avoided through use of immutable objects.
Principles of Object-Oriented Programming 2
This block explains advanced object-oriented programming and starts introducing design patterns into code.
- Removing null references – Shows practical techniques to remove almost all null references from code.
- Managing optional objects – Introduces Option functional type to replace remaining null references.
- Refactoring to patterns – Makes distinction between refactoring and redesign; demonstrates the place of design patterns in fixing design issues.
- Evolution of patterns – Demonstrates evolution of design pattern implementation from simplest to more and more complex as design goals grow larger.
Design Patterns for the Real World
This block of lectures demonstrates how design patterns can be applied in real world projects. All examples come from practice, which adds to their usefulness.
- Combining patterns – Shows cases where a single pattern doesn’t resolve design issues; then shows efficient solutions that combine two patterns.
- Meeting design goals – Explains a method based on following design goals which leads to application of a certain design pattern.
- Morphing patterns – Shows methods that allow simpler design patterns to evolve into more complex ones with similar object roles.
- Patterns in testing – Demonstrates specific application of patterns in unit and integration testing, where they help create complex mock object, perform complex assertions, produce test data, etc.
Principles of Object-oriented Design
These lectures are providing theoretical insight which is generally lacking in development teams.
- Method preconditions – Explains importance of method preconditions; introduces Code Contracts library.
- Object substitution – Explains how and why Substitution Principle works in OO languages; introduces Liskov Substitution Principle to demonstrate distinction between structural and behavioral subtyping.
- Abstract data types – Introduces abstract data types and demonstrates their importance in class design.
- Design by Contract – Introduces Design by Contract; demonstrates improvements caused by introduction of contracts in design.
- Interface Segregation Principle – Shows how to improve design through careful application of ISP; introduces fluent interface as implementation of ISP.
- Interface contracts – Applies Design by Contract to interfaces; demonstrates significant simplification of classes that are implementing interfaces with contracts.
Advanced Object-oriented Design
Covers some of the advanced techniques in class design, which can be applied to produce quite effective and powerful designs.
- Fluent interface – Considers consistency problem for objects implementing fluent interface; applies immutable objects to fluent interface design.
- Strategies – Introduces strategies as a flexible method to drive object state transformations; special attention paid to pros and cons of lambda functions.
- Composition vs. Inheritance – Explains practical aspects of class inheritance and object composition; demonstrates good aspects of object composition, but also warns of troubles that it may cause.
- Inversion of Control – Explains importance of IoC in light of object composition; introduces IoC containers.
- Module dependencies – Introduces macro-design through such concepts as abstractness and stability of modules; introduces code metrics.