
Learn the solid five object-oriented design principles—single responsibility principle, open closed principle, Liskov substitution principle, interface segregation principle, and dependency inversion principle—to improve maintainability, flexibility, and understandability of code.
Explore why this course focuses on C++, a modern, powerful general-purpose language. Learn its object-oriented, generic, and functional features, dynamic and static polymorphism, and idioms that support solid principles.
Explore the CP Solid repository on GitHub, discover presentations, standalone C++ examples, the server app project, unit and high-level tests, and continuous integration via GitHub Actions.
Examine the toy project's initial commit to understand its main.cpp structure, boost io context usage, tcp server setup, json and xml parsing, and per-connection session handling before applying SOLID principles.
Explore the latest solid refactor of a toy c++ project: a multi-library server built with cmake, featuring authentication, text service handling text reports, and xml/json parsers with unit tests.
Explains a synchronous, blocking tcp server model that creates a thread per connection, uses blocking reads, and contrasts with asynchronous designs for scalability.
Download the Windows solid c++ project from GitHub, clone the repository, open it in Visual Studio Code, install Git and dependencies, then compile the code on Windows.
Install Google test and Google Mock on Windows, clone the repository, build with CMake and g++, and copy lib and include files to enable unit tests.
Run high-level Python tests against the server application to validate text reports in JSON and XML over TCP. Build the project, start the executable, and run tests to confirm correctness.
download and clone the course repository via git on linux, install dependencies, and compile the solid principles code examples using vscode on ubuntu.
Install and configure C++ development dependencies on Linux, including gcc/g++, cmake, boost libraries, google test and google mock, with optional valgrind for testing.
Explore unified modeling language UML and its diagrams, including class diagrams, sequence diagrams, state machines, and physical diagrams, and learn how UML documents software architecture and communicates design decisions.
Class diagrams use rectangles for classes and arrows for relationships, with attributes, operations, and visibility. Cover association, inheritance, realization, dependency, and composition or aggregation, noting composition ownership and lifetime.
Build UML class diagrams with Umbrello, defining classes, attributes, and operations; model relationships like generalization, association, and dependency; specify parameters, visibility, and export diagrams.
Adopt the single responsibility principle to ensure every class, function, and module has one clear purpose, a single reason to change, and fewer dependencies for easier maintenance and testing.
Apply the single responsibility principle by keeping modules and functions simple and focused on one purpose, using divide and conquer, and refactoring to maintain cohesion and balance.
Explore applying the single responsibility principle by refactoring a database class into separate connection, cursor, and records/queries handling components.
The text editor example violates the single responsibility principle by mixing text manipulation, display, printing, and conversions in one class. Separate concerns into dedicated classes to improve cohesion.
Examine how a plant care system violates the single responsibility principle by combining sensors, actions, and state updates, and learn refactoring ideas for modular, testable, flexible design.
Refactor the initial commit toward the single responsibility principle by extracting configuration and json/xml parsing logic from main into modules, and isolate the reporting session for easier testing.
Applies single responsibility principle and refactors into modular static libraries, making main minimal and enabling unit-tested startup configuration with boost program options.
Apply the open for extension, closed for modification principle by extending behavior without modifying source code, reducing coupling, preserving tests, and speeding compilation in C++ projects.
Apply the open-closed principle judiciously; closure is impossible and premature abstraction adds complexity. Refactor when changes arise, using dynamic or static polymorphism only where domain knowledge predicts changes.
Explore the open-closed principle with a visual cartridge analogy, showing how a device is open for extension yet closed for modification through abstraction and interface.
Explore UML class diagrams and the open-closed principle by contrasting concrete button dependencies with abstract button interfaces, showing how polymorphism enables extension without modifying form window.
Learn dynamic polymorphism and inheritance to apply the open-closed principle in c++, using an abstract animal interface with a single speak method implemented by dog and cat.
Explore static polymorphism with templates as an alternative to inheritance, using a speak function that calls each type's speak at compile time for open-closed design.
Explore template specialization in c++, applying the open closed principle by extending graph algorithm behavior for directed and undirected graphs without modifying the core class.
Explore using templates and the open closed principle with c++20 concepts like flyable and swimmable, demonstrated by Bird and Fish selecting the appropriate action.
Demonstrate the dynamic decorator pattern to extend dog and cat behavior without changing their types, aligning code with the open-closed principle.
learn how the template method pattern lets subclasses implement step a and override the hook to extend base behavior while preserving the algorithm and the open-closed principle.
Explore composition versus inheritance in the open-closed principle, showing how a player composes delegate objects to vary behavior without relying on inheritance.
Explore the runtime concept idiom, enabling polymorphism via type erasure with wrapper, concept, and model. Wrap dog and cat in a vector to demonstrate open-closed extension.
Explore applying the open-closed principle by refactoring report session and text service to depend on abstractions, extract parsing logic into interfaces, and enable mocking for unit testing.
Explore how open closed principle and single responsibility principle drive refactoring of a cpp project by introducing abstract text service, a report parser interface, and a factory driven parser selection.
Explore the Liskov substitution principle, showing that subtypes must be substitutable for base types and that replacing base objects with subtype objects should preserve the program's desirable properties.
Differentiate nominal vs structural subtyping and explain the is-a relationship and behavioral subtyping within the Liskov substitution principle, emphasizing interfaces preserve expected behavior for clients.
Explore design by contract in the Liskov substitution principle, defining invariants, preconditions, and postconditions, and how subclasses preserve invariants with equal or weaker preconditions and equal or stronger postconditions.
State and verify contracts in C++ using asserts, expects, and ensures, while leveraging static_assert, type traits, and concepts to guide template selection and testing.
Use a screwdriver handle interface to illustrate the Liskov substitution principle, where tools share a common base but differ at the tip. Avoid substitutions that merely fit the interface.
Examine a classic rectangle–square example that violates Liskov substitution due to preconditions and postconditions and inherited width and height setters, then learn a cleaner separate-classes solution.
Explore Liskov substitution principle violations and how to fix them by refactoring a C++ animal example into a clean hierarchy with separate flyable and workable interfaces, avoiding diamond problems.
Demonstrates a Liskov substitution principle violation using a queryset class inspired by Django, showing how delete and update return values must align with the database interface.
the video demonstrates adding a validated report parser that extends json and xml parsers, validating year and text name while preserving the open-closed principle and liskov substitution principle.
Explore the interface segregation principle, splitting interfaces into cohesive ones so clients avoid unused methods. Understand why bloated interfaces hinder cohesion and how each client uses only the needed interface.
Explore the implications of the interface segregation principle and how cohesive, smaller interfaces reduce changes, dependencies, and test complexity, while supporting the open-closed principle.
Learn to follow the interface segregation principle by avoiding fat interfaces, applying single responsibility, and grouping methods by purpose and client into smaller interfaces, with delegation or adapters when needed.
Explore a door example showing the interface segregation principle in SOLID C++, comparing a timed door using timer client interface to a normal door without timeout, highlighting interface segregation violation.
Analyze how the plant care app violates interface segregation principle and Liskov substitution principle, using moisture and sunlight sensors, mutex, and observer patterns, and plan refactoring for cohesive interfaces.
Refactor the plant care app to follow the interface segregation principle and fix Liskov substitution principle violations by introducing water device and window device interfaces and tailoring caretakers and sensors.
Apply the dependency inversion principle by making high level client classes depend on abstractions, not concrete implementations, and have details depend on those abstractions through abstract base classes.
Explains the implications of the dependency inversion principle: high level modules depend on abstractions, not implementation details, reducing coupling and easing testing, maintenance, and reuse with mocks.
Learn how to follow dependency inversion by shaping abstractions, using interfaces and dependency injection, and selecting where to apply them for flexible, testable C++ code.
Demonstrate the observer pattern and dependency inversion by decoupling forecast and users with interfaces, enabling dynamic polymorphism and templates for reusable, testable implementations.
Demonstrating dependency inversion by moving interfaces to the sensors library, the plant care example shows caretakers depend on abstractions rather than concrete implementations.
Examine dependency inversion in a server that processes text reports using interfaces and abstractions. Move interfaces to a separate package to improve testability and compilation time with mocks.
Learning syntax of a programming language is not enough to become professional and build high quality software. One must also learn how to make good design and implement it properly so that software is robust, maintainable, flexible and testable. That’s why we need object-oriented design principles like SOLID:
Single responsibility
Open-closed
Liskov substitution
Interface segregation
Dependency inversion
This is probably the most complete SOLID principles course on Udemy. But it’s also special in that it focuses on C++ programming language, which we use for examples and assignments. And this course covers both theory and practice.
By the end of this course you should
Develop an intuitive understanding of all SOLID principles
Understand when SOLID principles are needed and when not
Learn how to follow SOLID principles in general, regardless of a programming language, using appropriate abstractions and programming patterns
Learn how to follow SOLID principles using different C++ language features and idioms
Know how to structure C++ projects, test and refactor
However, there should be no illusions about this or any other course. One cannot become a true master of object-oriented design and programming only by completing one or few courses – it takes years of practice. But this course is a good starting point and provides the needed foundations.
So what exactly is covered in the course?
Presentations (theory and concepts about the principles)
Visual analogies from real world (to better understand and remember the principles)
UML diagrams (mainly class diagrams with examples about the principles)
Plenty of stand-alone code examples (at least a few for each principle)
Almost a real-world project (server application that receives over TCP connection and processes tax reports in JSON or XML formats) with unit and high-level tests
Explanations how to install the project’s dependencies, compile it and run tests (uses C++17, CMake, Boost libraries (asio, program options, etc.), Google test)
Quizzes and final test (some have additional code examples)
Programming assignments (work on the project, etc.)
This course is for you if you
Are a beginner or intermediate C++ programmer (but not complete beginner)
Have a basic understanding of OOP (classes, polymorphism, inheritance, encapsulation, etc.)
Want to learn more and become a better software engineer
Ideally, before this course you should have already worked on a few small hobby projects or have some commercial software development experience.
You should be able to pick up the rest of the materials and technologies during the course. At the same time, some applied technologies and examples are more advanced but optional to the main subject of this course.
And even if you don’t primarily program in C++, you will still find that most of the code examples, as well as the principles, apply to many other programming languages.
What is expected from you?
Besides watching lectures and/or reading presentations, it’s expected that you
Compile, read and understand code examples and the project source code (ability to read and work with somebody else's code is very important and often underestimated)
Refactor some of the provided code examples while doing assignments
Work on the project source code in the final assignment, extend its functionality and add tests
The images in visual examples are from website pixabay and the audio in videos is from website bensound.