
Explore the single responsibility principle, its essence, and how to apply it to achieve more maintainable code; identify srp levels and common violations, and learn adherence strategies.
Explore solid principles and design smells to craft maintainable software architecture in C#, learning dependency management and decoupling while applying srp, ocp, lsp, isp, and dip.
Explain the single responsibility principle by separating class duties to one reason for change, achieving high cohesion and low coupling across modules, classes, and functions.
Demonstrates a single responsibility principle violation in a ticketing payment model that bundles cash and card processing, highlighting the need to separate payment responsibilities and reduce coupling.
Study refactoring to a better design by abstracting the payment process with a payment model and interfaces, implementing online and cash gateways, and using composition to improve srp and modularity.
Explore SRP violations with examples like a get report method that gathers data and formats output, and a fire alarm routine that mixes policy with mechanics.
Apply the facade pattern to simplify client interaction by wrapping complex objects into a single, easy-to-use API, clarifying responsibilities and preserving SRP.
Apply the single responsibility principle by separating concerns so a class has one reason to change, and use interfaces or facades to manage evolving responsibilities without unwanted coupling.
Explore the open-closed principle, its two definitions by Martin and Meyer, and how refactoring fixes violations, while previewing template method, strategy patterns, and abstract classes versus interfaces.
The open closed principle states software should be open for extension but closed for modification. Changes come from adding code, using abstractions and interfaces to enable extension via dependency injection.
Demonstrate an OCP violation with a device finder that uses a switch to set parameters, showing why adding new devices requires modifying the method, and highlight Martin's view of OCP.
Refactor the design by abstracting the find method behind a device interface, enabling new device implementations without code changes and balancing inheritance with composition for open-for-extension design.
Explore OCP related patterns, including template method, strategy, and visitor patterns, and compare abstract classes versus interfaces for extensibility in C# design.
Identify the common smell of OCP violation—many conditional branches and switch statements—and explore delegates, the chain of responsibility pattern, template method, visitor, and strategy patterns to favor composition over inheritance.
apply the open for extension and closed for modification principle, isolate the parts that change most, and centralize object creation in a single module using abstract classes or interfaces.
Explore the Liskov Substitution Principle, contracts and variance, and preconditions and invariants, highlighting common LSP violations with a BCL example and strategies to fix them.
Clarify the Liskov substitution principle, showing subtypes must replace base types without observable client differences, and note duck typing and two common violations: contracts and covariance or contravariance.
Explore programming to contracts, distinguishing contracts from interfaces, and define preconditions, postconditions, and invariants; see how weakening contracts in inheritance breaks LSP and how code contracts verify correctness.
Explore a classic LSP violation where square inherits from rectangle, revealing why substitutability fails for area calculations and illustrating an open-closed principle violation.
We refactor to separate data and behavior by introducing a shape interface with per-shape area algorithms for rectangle and square, improving cohesion and API safety for future LSP discussion.
Explore common LSP violations with practical examples of variance, covariance, and related concepts; analyze how read-only collections and downcasting reveal subtleties in C# generics and interface design.
Identify common smells of LSP violation, such as refused bequest and downcasts, and apply tell‑don’t‑ask while fixing root causes by creating a shared base class.
enforce the LSP by treating subtypes as interchangeable with base types to ensure consistent behavior; avoid strengthening preconditions or weakening postconditions and respect covariance and contravariance in generics (in, out).
Explore the interface segregation principle (ISP) within solid principles, define ISP, identify problems caused by fat interfaces, and refactor to improve maintainability with life demo examples.
Explore how interface definitions in c# shape APIs and why the interface segregation principle favors small, cohesive interfaces. See how interface aggregation and dependency inversion solve fat classes.
Explore how a fat bank terminal interface triggers an isp violation across Zone, PDU, and Zap terminals, highlighting lsp risks and the need for refactoring.
Apply the interface segregation principle by creating small, isolated interfaces for card reader operations, implement this interface on bank terminal models, and achieve low coupling and high cohesion.
Demonstrates how a knowledge-heavy interface implementor complicates tests with a config class and xml configuration. Extract a minimal interface, inject it via the constructor, and apply the interface segregation principle.
Segregate the configuration interface so reports access only the configuration needed for generating reports, inject that interface into the report constructor, and implement a unit test to spot isp violations.
Identify common smells tied to the interface segregation principle and LSP, and apply fixes like splitting fat interfaces with the facade or adapter pattern to improve cohesion and dependency management.
Explore the interface segregation principle by ensuring clients depend only on used methods. Extract focused interfaces, apply facades or adapters, and embrace ISP to improve long-term maintainability.
Explore the dependency inversion principle, inversion of control, and dependency injection; learn refactoring techniques to fix DIP violations, examine containers, and understand architectural implications.
explore the dependency inversion principle by contrasting tight and loose coupling, define that high-level modules should depend on abstractions, and examine practical decoupling with a lamp and socket analogy.
Explore dependencies between high-level domain objects and low-level infrastructure, and show how interfaces enable indirection to reverse dependencies, achieving runtime flexibility and reduced compile-time ties.
Explore volatile versus stable dependencies, learn how indirection abstracts unstable external systems like databases and web servers, and apply test doubles to keep code unit-testable.
Explore inversion of control, dependency injection, and the dependency inversion principle, distinguishing dependencies, injection techniques, callbacks, frameworks, and the template pattern.
Demonstrate how a divergence checker is tightly coupled to counter and fiscal registration devices, revealing a DIP violation and prompting three dependency injection approaches to enable reliable unit testing.
Apply dependency injection to expose hidden dependencies and improve testability: use constructor, property, or method injection; compare encapsulation implications and enable unit tests with test doubles.
Explore dependency injection techniques in C#, including constructor, property, and method injection, and learn pitfalls when a constructor takes many dependencies, use container objects, and consider default constructors for frameworks.
Explore how to define boundaries and invert dependencies with plug-ins, privileging domain logic at the core and embracing onion, hexagonal, and ports-and-adapters architectures for flexible, testable software.
Explore pure DI vs manual dependency injection, and how IoC containers automatically resolve dependencies from the view model to the customer interface, repository, and gateway.
Implement a simple IoC container in C# by mapping types and resolving dependencies. Register dependencies, handle constructors with recursion, and validate creation of the main view model.
Explore a real-world wpa app for managing students built with an IoC container, demonstrating bootstrap, MVVM, data binding, and a Windsor-based plug-in architecture with an XML data provider.
Identify common smells of dependency inversion principle violations, such as explicit dependencies and hidden, static dependencies, and decouple with a layer of indirection, interfaces, and adapters to enable test doubles.
Explore how higher level policies avoid low level details, distinguish stable and unstable dependencies, and apply inversion of control and dependency injection to enable a ports and adapters architecture.
Learn core software design principles, including the dry and keep it simple principles, and you ain't going to need it, separation of concerns, Demeter, least knowledge, least astonishment, and encapsulation.
Apply the dry principle to eliminate duplicate logic and magic values by creating a single source of change, and use the open/closed principle to avoid switch-case duplication.
Apply the Kiss principle to keep software simple, reduce accidental complexity through decomposition and small components, and balance solid principles with composition over inheritance and avoiding pre-emptive optimisations.
Master the Yagni principle to avoid overengineering by selecting the simplest thing that could possibly work now, weighing future costs, and balancing extension points with refactoring and testing.
Learn how separation of concerns divides UI, business logic, presentation logic, and database into modular components to simplify development and maintenance, and to keep domain logic persistence agnostic.
Master the CQS principle: design methods as either commands or queries, never both, and use explicit names and signatures to improve clarity, security, and API honesty.
Explain the law of demeter as a principle of least knowledge that reduces coupling, using the paper boy scenario to show why wallets should be encapsulated and accessed via getPayment.
Explore the principle of least astonishment, showing that APIs should behave as users expect to avoid temporal coupling and surprising side effects in methods like print report.
Explore information hiding and encapsulation as foundations of robust APIs in C#. Learn how stable interfaces and private members protect invariants and simplify client use.
Define what an api is and why modular design matters. Examine good apis—simplicity, expressiveness, extensibility, and consistency—by comparing private and public APIs and applying open-closed principles.
Explore solid vs yagni to avoid needless complexity from overgeneral designs, gold plating, and coupling, and apply the single responsibility principle, reused abstraction principle, and the rule of three.
Compare the open/closed principle and yagni, examining private vs public api contexts and why future refactoring costs drive different choices about adding abstractions.
Clarify the difference between SRP and ISP by contrasting the designer's single-responsibility focus with the client's need to depend only on exposed interfaces, using a data storage example.
Clarify the difference between architecture and design, identify significant components, and learn to defer architectural decisions while exploring architecture and design patterns.
Master the dry principle by ensuring a single unambiguous representation and avoiding overengineering. Decompose to reduce essential versus accidental complexity and separate concerns into modular design.
Join the mailing list for discounts, leave a review, explore discounted courses and the blog on engineerspock.com, and support the creator on Patreon.
SOLID is an acronym which stands for SRP, OCP, LSP, ISP and DIP. These five acronyms in their turn stand for:
Single Responsibility Principle
Open/Closed Principle
Liskov Substitution Principle
Interface Segregation Principle
Dependency Inversion Principle
In this course, you’ll learn how to apply meta and SOLID principles so that your application will live a long healthy life. It means you are going to learn how to write code of the high quality: readable, understandable and reliable.
Improve your knowledge in object-oriented programming
Understand the meta principles on which all the other development principles are based
Understand the symptoms of code defects
Learn the foundations of SOLID principles
Learn how to detect the violations of SOLID principles and how to fix the problems
Learn how meta principles and SOLID principles are related to each other and how to find the balance between them
Foundations of writing object-oriented code
Despite the fact that C# is a very rich on features language, it's very common to see poorly designed and implemented applications in a real world. Language by itself does not guarantee that the architecture of an application will be great. In order to design and build maintainable software, we need to understand the principles of software development. This video course is exactly about how to achieve clean and maintainable software.
You probably have already heard the following well-known statement: most code sucks. Well, this course is all about how to produce code which doesn't suck.
Owning skills of producing a well-designed and well-implemented types is the prerequisite for the other developers to treat you as a decent professional.
Content and Overview
This course is aimed at middle and senior developers. Solid experience in C# is required.
There are plenty of code examples throughout this course so that you will learn both theoretical and practical material.
Starting with SOLID principles we will go further to the meta-principles. Going through the SOLID principles, you’ll also learn about the related patterns. Then we will get to the problem of contradictions between different principles. You’ll learn about the relationships between SOLID principles and meta principles.
In general, you’ll learn in this course:
SRP
OCP
LSP
ISP
DIP
These are the SOLID principles. You’ll learn the background problems that can be solved by particular principle, you’ll see the demonstrations in code, you’ll learn the related patterns to every principle.
Learning DIP you’ll in addition learn what is Dependency Injection, Inversion of Control, IoC-Containers and what are the architectural implications of DI.
Here are other topics you’ll learn in the course:
DRY – don’t repeat yourself
KISS – keep it simple stupid
YAGNI – You Ain’t Gonna Need It
SoC – separation of concerns
CQS – command query separation
Law of Demeter
Principle of Least Astonishment
Information Hiding and Encapsulation
API Development Principles
Contradiction between SOLID and YAGNI
Contradiction between OCP and YAGNI
What is Architecture and Design
Teaching Approach
No fluff, no ranting, no beating the air. I respect your time. The course material is succinct, yet comprehensive. All important concepts are covered. Particularly important topics are covered in-depth.
Take this course, and you will be satisfied!
------------------------------------------------------------
Keywords related to the course:
Software Architecture
SOLID Principles Tutorial C#
SOLID Tutorial C#
Software Design
SOLID Principles
SRP, OCP, LSP, ISP, DIP