Uncle Bobโ€™s SOLID Principles Made Easy ๐Ÿ€ - In Python!

ArjanCodes ยท Beginner ยท๐Ÿ–Œ๏ธ UI/UX Design ยท5y ago

Key Takeaways

The video discusses Uncle Bob's SOLID design principles using practical examples in Python, covering Single Responsibility Principle, Open-Closed principle, Liskov Substitution Principle, Interface Segregation Principle, and Dependency Inversion Principle.

Full Transcript

the solid design principles help you write great code that's easy to reuse and extend and that's going to save you a lot of time today i'm going to show you exactly how they work using practical examples in python let's dive right into it if you're new here you want to become a better software developer and gain a deeper understanding of programming in general start now by subscribing and hitting the bell so you don't miss anything the solid design principles were first mentioned in a paper written in 2000 by the software engineer robert martin also called uncle bob what's going on with all these weird naming schemes in computer science gang of four uncle bob what what kind of vibe are we going for i'm uncle arjun and have i got something solid for you [Music] solid stands for five principles single responsibility open closed list of substitution interface segregation and dependency inversion i've talked about some of these principles before but in today's video i'm going to take you through a code example of a sales system with order and payment handling in python to illustrate each of these five principles in a practical setting the example i'm going to talk about today is a sales system there's a class order that has items quantities and prices and the payment status and there are functions for adding items computing the total price and paying the order in this example i create an order i add a couple of items then i print the total price and finally i pay the order and this what happens when i run the program so very straightforward we create an order of 210 dollars we're processing a debit payment type and we're verifying that with the security code and the pay method that you see here is basically responsible for dealing with the payments the first of the five principles installed i'm going to talk about is single responsibility we want classes and methods to have a single responsibility another way to say it is that we want classes and methods to have high cohesion be responsible for only a single thing and that ensures that you can reuse them much easier later on in this case the order class does way too many things i mean adding items you can understand it's part of an order because you want to be able to add items to an order computing the total price could also still be part of the order but handling the payment definitely shouldn't be part of the order so the order class has way too many responsibilities and we need to fix that now the way we can do it is for example by extracting this pay method and putting it into a separate class that has another advantage because if later we want to add other payment types like bitcoin or apple pay or whatever we don't have to change the order class anymore we can do it in the payment processing side of things so let's do that so i'm going to create a class here called payment processor and inside that class we want to have the different payment methods now at the moment the pay method is not ideal because there's like an if else statement in here that checks for the various different payment types and i think we want to do something different so let's redesign this method and split it into two methods pay debit and pay credit so i'm going to copy over all this code and then i'm going to refactor it so that it fits with our new design so instead of a pay method we now have a pay credit method and a debit method i'm just copying over everything and then remove what i don't need anymore we no longer need to know the payment type because that's encoded in the method name so i'm removing that here and then i'm going to remove these if statements because we don't need that either so now we have to pay debit and pay credit methods inside a payment processor class the only issue is that we want to set the order status to paid so this means that the payment processor actually needs the order in order to process the payment so we're going to pass that as a parameter now we need to do is not call order.pay anymore but create a payment processor and then use that so now we have a separate pavement processor and we can remove this bay method from the order class so much shorter classes we've made sure that order and both payment processor have their own single responsibility which is handling adding stuff to the order and processing the payment and when we run this code we are going to get exactly the same result as before except that of course i need to add the order object to the payment processor there you go that's the single responsibility principle if you look at what we did we increased the cohesion order has one responsibility payment processor has one responsibility but we also introduced some coupling we'll deal with that later on the second principle the o in solid stands for open closed and that means we want to write code that's open for extension so we should be able to extend the existing code with new functionality but closed for modification we shouldn't need to modify the original code in order to do that let's take a look at what this means in the order example so we have our order we have our payment processor and we have creating the order and processing the payment here in the example now the issue is if we want to add an extra payment method like bitcoin or apple pay or paypal or whatever we have to modify the payment processor class so that violates the open closed principle optimally what we'd like to do is create a structure of classes and subclasses so that we can just define a new subclass for each new payment type in order to do that we need to refactor this payment processor class so let's turn it into an abstract class and create sub-classes for each of the different payment types so i'm going to import the abc module here and let's create an abstract payment processor class that code we're going to need later and we're going to add a single method abstract method that's called pay so now what we can do is for each payment type create a subclass for example let's create a debit payment processor and that's a subclass of payment processor and similarly let's create a credit payment processor we don't need this code anymore and now what we do here is create one of these instances of the subclass and then simply call the pay method there we go let's run this yeah still works fortunately but now we do not violate this open close principle anymore because if we want to add another payment type like paypal for example we don't have to change the payment processor or the order anymore let's try and do that so now i've created a new paypal payment processor and we can use it here without having to change anything about the order class or anything related to that the third principle is lisk of substitution and that means that if you have objects in a program you should be able to replace those objects with instances of their subtypes or subclasses without altering the correctness of the program let's take a look again at this paypal payment processor now the thing is that paypal payments don't work with security code but with email addresses so if i wanted to fix that without changing anything in the code what i probably should do is make sure that this is actually an email address and not a security code so i'd do it like this but then here i would provide some kind of email address the issue is that this is not supposed to be security code but an email address so we're kind of abusing this type to do something different than we're supposed to and that means we're violating the liskov substitution principle one way to solve this is by removing this dependency from the pay method and actually setting it in the initializer so that we can do different things in initializer depending on the type of class we create so let's remove security code here and that means we also have to remove it here here and here and then let's add an initializer and we can add the same initializer to the credit payment processor and the paypal payment processor then gets an email address and we should add self because now it's an attribute of the class instead of a method parameter so there we go now if we create the paypal payment process so we don't pass the email address here anymore but as a parameter to the initializer and now let's run the code again and we get again the same result but now we're properly using the pay method instead of changing what parameters mean in order to fit our specific use case by the way if you're enjoying this content so far give this video a like the fourth principle in solid is interface segregation interface segregation means that overall it's better if you have several specific interfaces as opposed to one general purpose interface i've extended this example to now include a two-factor authentication inside the payment processor class so there's an off sms that gets a code and that authorizes the payment in the debit payment processor i've implemented this in a very simple way just putting a verified variable to true whenever we retrieve an sms code normally you would do all kinds of checks here i'm not implementing that for the sake of simplicity the issue is that a credit payment processor doesn't have two-factor authentication so what we do here is i raise an exception that credit card payments don't support this and paypal payment processor does support it so i have a similar kind of implementation here and the only thing i added to the pay method is checking that the payment has been verified and i'm only doing that in the debit and in the paypal payment process because for credit payments it's not allowed here you see an issue with defining a generic interface like the payment processor to do multiple things that are not always applicable to subclasses in this case not all subclasses support two-factor authentication so it's better to create separate interfaces for this and what you could do for example is add a second subclass of payment processor that adds sms two-factor authentication capabilities so let's add that class here and this is a subclass of payment processor payment processor no longer contains this sms authentication method but we put it in the payment processor sms class and this one is no longer needed because it's already in the superclass and now we can use this class and only inherit from that class if we support sms authentication so that's the debit payment processor and that's the paypal payment processor and then the credit payment processor we don't need to put in this weird sms authentication method that always raises an exception so that's much cleaner this way so that's interface segregation so instead of one general purpose interface we split it so that subclasses can have more meaningful behavior instead of doing this with classes and subclasses you can also use composition which arguably makes more sense in this example what do i mean by that so we have the authentication method here but what we could also do is create a separate class called sms authorizer that handles the authentication let's add that class and that class has two methods one for verifying an authorization code and second for checking that it's authorized for now let's assume that all codes are always valid obviously normally you would add checks here to verify that the code is actually found then we have an is authorized method that returns a bool you could directly access the property but this is a bit cleaner a payment processor still only has a pay method but we don't have this class anymore but now our specific subclasses receive an sms authorizer if they are using that functionality so the debit payment processor doesn't only get a security code it also gets an authorizer and i'm adding a type in here to just make sure that we know what type of object we're getting also now we don't store the verified status anymore inside the payment processor because our authorizer is responsible for that the offs mess function is no longer there and inside the payment method we call the is authorized method from our authorizer and let's do something similar for the paypal payment processor there you go now we need to change the code here to create this authorizer for us and instead of calling off sms on the processor we're calling it on the authorizer and now we should get a similar result as before oh i think i forgot to change this class here let's try that again yes there we go so now what happened is that we used composition instead of more subclasses to create a similar effect myself i tend to use composition more than inheritance because most cases i noticed i don't really need a big inheritance tree i just need to separate the different kinds of behavior in my application and composition works very well for that the final principle in solid is dependency inversion i talked about that one before in another video if you want to check that out click here or here somewhere dependency inversion means i want our classes to depend on abstractions and not on concrete subclasses and in this code this is currently an issue because the payment processes are depending on specific authorizers in this case an sms authorizer so to solve that is create another abstract authorizer class that you pass to the payment processors let's create that class the authorizer class only contains an is authorized method and sms authorizer is now a subclass of that class there we go instead of passing an object of this type to a payment processor we're going to pass an object of this type so let's change that here in the code let's run that now nothing really changed in terms of behavior by doing this but now we can add other things that make this easier to use for example let's say i want to create another authorization method like checking that you're not a robot so let's add another class to deal with that just gonna copy over part of this code but not a robot doesn't have a verify code method it has a not a robot method and now we can do is create another authorizer here and call the not a robot method instead so that's dependency inversion and that works because we made sure that the authorizer is of type authorizer and not of type as a mess off i hope these examples clarify what the solid design principles mean and how they translate to practical applications if you've been using these principles already in your code let me know in the comments below though it is important to know about these principles as a software developer i do notice that as you get more comfortable in applying these they kind of get ingrained into the way you work in my case for example i don't think about these specific principles anymore when i write code i just automatically gravitate towards solutions that incorporate them i have a lot more python videos in the pipeline so make sure to subscribe and come on over to discord to hang out and talk about software design thanks for watching take care and stay tuned for another video of uncle arjun posse of one son why don't you come on over and sit on uncle arjun's lap i love talking in third person [Music] we don't want classes to have low cohesion and be responsible for too many different things first we're going to explain the code example darn and there are a few functions that help me create different orders i hope these examples clarify these these i hope these examples clarify what the solid design principles mean and better better i just automatically go

Original Description

๐Ÿ’ก Learn how to design great software in 7 steps: https://arjan.codes/designguide. In this video, I discuss the SOLID design principles by Robert Martin (Uncle Bob) using practical examples in Python. Though the SOLID principles are one of several sets of software design philosophies, and arguably quite specific for Object-Oriented programming, they are the most well-known and easy to apply to your own code. You can find the code I worked on in this episode in my GitHub repository: https://github.com/arjancodes/betterpython ๐ŸŽ“ ArjanCodes Courses: https://www.arjancodes.com/courses. ๐Ÿ’ฌ Join my Discord server: https://discord.arjan.codes. โŒจ๏ธ Keyboard Iโ€™m using: https://amzn.to/49YM97v. ๐Ÿ”– Chapters: 0:00 Intro 1:08 Example explanation 1:45 Single responsibility principle 5:01 Open/closed principle 7:36 Liskov substitution principle 9:48 Interface segregation principle 12:12 Interface segregation variety using composition 15:25 Dependency inversion 17:29 Final thoughts 18:15 Gag reel #arjancodes #softwaredesign #solidprinciples
Watch on YouTube โ†— (saves to browser)
Sign in to unlock AI tutor explanation ยท โšก30

Playlist

Uploads from ArjanCodes ยท ArjanCodes ยท 14 of 60

1 Full stack WEB DEVELOPMENT in 2021 - the ULTIMATE tech stack for FAST web app development
Full stack WEB DEVELOPMENT in 2021 - the ULTIMATE tech stack for FAST web app development
ArjanCodes
2 FROM PRODUCT IDEA TO SOFTWARE - turn your idea into reality in a few steps
FROM PRODUCT IDEA TO SOFTWARE - turn your idea into reality in a few steps
ArjanCodes
3 Cohesion and Coupling: Write BETTER PYTHON CODE Part 1
Cohesion and Coupling: Write BETTER PYTHON CODE Part 1
ArjanCodes
4 Build a GLASSMORPHISM React Component - Typescript & Material-UI
Build a GLASSMORPHISM React Component - Typescript & Material-UI
ArjanCodes
5 Observer Pattern Tutorial: I NEVER Knew Events Were THIS Powerful ๐Ÿš€
Observer Pattern Tutorial: I NEVER Knew Events Were THIS Powerful ๐Ÿš€
ArjanCodes
6 100% CODE COVERAGE - Think You're Done? Think AGAIN.โ˜
100% CODE COVERAGE - Think You're Done? Think AGAIN.โ˜
ArjanCodes
7 Two UNDERRATED Design Patterns ๐Ÿ’ก Write BETTER PYTHON CODE Part 6
Two UNDERRATED Design Patterns ๐Ÿ’ก Write BETTER PYTHON CODE Part 6
ArjanCodes
8 1000 Subscribers! ๐Ÿš€ WHY I Started this Channel and WHAT'S NEXT
1000 Subscribers! ๐Ÿš€ WHY I Started this Channel and WHAT'S NEXT
ArjanCodes
9 Channel Trailer ArjanCodes - March 2021
Channel Trailer ArjanCodes - March 2021
ArjanCodes
10 Exception Handling Tips in Python โš  Write Better Python Code Part 7
Exception Handling Tips in Python โš  Write Better Python Code Part 7
ArjanCodes
11 Monadic Error Handling in Python โš  Write Better Python Code Part 7B
Monadic Error Handling in Python โš  Write Better Python Code Part 7B
ArjanCodes
12 GW BASIC Games I Wrote When I Was a Kid ๐ŸŽฎ Running 30 Year Old Code
GW BASIC Games I Wrote When I Was a Kid ๐ŸŽฎ Running 30 Year Old Code
ArjanCodes
13 Why You Should Think About SOFTWARE ARCHITECTURE in Python ๐Ÿ’ก
Why You Should Think About SOFTWARE ARCHITECTURE in Python ๐Ÿ’ก
ArjanCodes
โ–ถ Uncle Bobโ€™s SOLID Principles Made Easy ๐Ÿ€ - In Python!
Uncle Bobโ€™s SOLID Principles Made Easy ๐Ÿ€ - In Python!
ArjanCodes
15 QUESTIONABLE Object Creation Patterns in Python ๐Ÿค”
QUESTIONABLE Object Creation Patterns in Python ๐Ÿค”
ArjanCodes
16 If Youโ€™re Not Using Python DATA CLASSES Yet, You Should ๐Ÿš€
If Youโ€™re Not Using Python DATA CLASSES Yet, You Should ๐Ÿš€
ArjanCodes
17 CODE ROAST: Yahtzee - New Python Code Refactoring Series!
CODE ROAST: Yahtzee - New Python Code Refactoring Series!
ArjanCodes
18 7 UX Design Tips for Developers
7 UX Design Tips for Developers
ArjanCodes
19 Going All-in on Software Design in Python + an ANNOUNCEMENT ๐ŸŽ™
Going All-in on Software Design in Python + an ANNOUNCEMENT ๐ŸŽ™
ArjanCodes
20 ๐ŸŽ™ Interview with Sybren Stรผvel, Developer @ Blender 3D
๐ŸŽ™ Interview with Sybren Stรผvel, Developer @ Blender 3D
ArjanCodes
21 Do We Still Need Dataclasses? // PYDANTIC Tutorial
Do We Still Need Dataclasses? // PYDANTIC Tutorial
ArjanCodes
22 7 Python Mistakes That Instantly Expose Junior Developers
7 Python Mistakes That Instantly Expose Junior Developers
ArjanCodes
23 Answering Your Most Frequently Asked Python Questions // Q&A 07-2021
Answering Your Most Frequently Asked Python Questions // Q&A 07-2021
ArjanCodes
24 GitHub Copilot ๐Ÿค– The Future of Software Development?
GitHub Copilot ๐Ÿค– The Future of Software Development?
ArjanCodes
25 More Python Code Smells: Avoid These 7 Smelly Snags
More Python Code Smells: Avoid These 7 Smelly Snags
ArjanCodes
26 Test-Driven Development In Python // The Power of Red-Green-Refactor
Test-Driven Development In Python // The Power of Red-Green-Refactor
ArjanCodes
27 5 Tips To Keep Technical Debt Under Control
5 Tips To Keep Technical Debt Under Control
ArjanCodes
28 Refactoring A Tower Defense Game In Python // CODE ROAST
Refactoring A Tower Defense Game In Python // CODE ROAST
ArjanCodes
29 The Factory Design Pattern is Obsolete in Python
The Factory Design Pattern is Obsolete in Python
ArjanCodes
30 Why the Plugin Architecture Gives You CRAZY Flexibility
Why the Plugin Architecture Gives You CRAZY Flexibility
ArjanCodes
31 Refactoring A Data Science Project Part 1 - Abstraction and Composition
Refactoring A Data Science Project Part 1 - Abstraction and Composition
ArjanCodes
32 Refactoring A Data Science Project Part 2 - The Information Expert
Refactoring A Data Science Project Part 2 - The Information Expert
ArjanCodes
33 Refactoring A Data Science Project Part 3 - Configuration Cleanup
Refactoring A Data Science Project Part 3 - Configuration Cleanup
ArjanCodes
34 Purge These 7 Code Smells From Your Python Code
Purge These 7 Code Smells From Your Python Code
ArjanCodes
35 Running A Software Development YouTube Channel
Running A Software Development YouTube Channel
ArjanCodes
36 Refactoring A PDF And Web Scraper Part 1 // CODE ROAST
Refactoring A PDF And Web Scraper Part 1 // CODE ROAST
ArjanCodes
37 Refactoring A PDF And Web Scraper Part 2 // CODE ROAST
Refactoring A PDF And Web Scraper Part 2 // CODE ROAST
ArjanCodes
38 How To Easily Do Asynchronous Programming With Asyncio In Python
How To Easily Do Asynchronous Programming With Asyncio In Python
ArjanCodes
39 The Software Designer Mindset
The Software Designer Mindset
ArjanCodes
40 NEVER Worry About Data Science Projects Configs Again
NEVER Worry About Data Science Projects Configs Again
ArjanCodes
41 Powerful VSCode Tips And Tricks For Python Development And Design
Powerful VSCode Tips And Tricks For Python Development And Design
ArjanCodes
42 8 Python Coding Tips - From The Google Python Style Guide
8 Python Coding Tips - From The Google Python Style Guide
ArjanCodes
43 What Is Encapsulation And Information Hiding?
What Is Encapsulation And Information Hiding?
ArjanCodes
44 8 Tips For Becoming A Senior Developer
8 Tips For Becoming A Senior Developer
ArjanCodes
45 Building A Custom Context Manager In Python: A Closer Look
Building A Custom Context Manager In Python: A Closer Look
ArjanCodes
46 GraphQL vs REST: What's The Difference And When To Use Which?
GraphQL vs REST: What's The Difference And When To Use Which?
ArjanCodes
47 You Can Do Really Cool Things With Functions In Python
You Can Do Really Cool Things With Functions In Python
ArjanCodes
48 Announcing The Black VS Code Theme (Launching April 1st)
Announcing The Black VS Code Theme (Launching April 1st)
ArjanCodes
49 7 DevOps Best Practices For Launching A SaaS Platform
7 DevOps Best Practices For Launching A SaaS Platform
ArjanCodes
50 Refactoring a Rock Paper Scissors Lizard Spock Game // Code Roast Part 1
Refactoring a Rock Paper Scissors Lizard Spock Game // Code Roast Part 1
ArjanCodes
51 Refactoring a Rock Paper Scissors Lizard Spock Game // Part 2
Refactoring a Rock Paper Scissors Lizard Spock Game // Part 2
ArjanCodes
52 Things Are Going To Change Around Here
Things Are Going To Change Around Here
ArjanCodes
53 Dependency Injection Explained In One Minute // Python Tips
Dependency Injection Explained In One Minute // Python Tips
ArjanCodes
54 How To Setup A MacBook Pro M1 For Software Development
How To Setup A MacBook Pro M1 For Software Development
ArjanCodes
55 A Simple & Effective Way To Improve Python Class Performance
A Simple & Effective Way To Improve Python Class Performance
ArjanCodes
56 How To Write Unit Tests For Existing Python Code // Part 1 of 2
How To Write Unit Tests For Existing Python Code // Part 1 of 2
ArjanCodes
57 How To Write Unit Tests For Existing Python Code // Part 2 of 2
How To Write Unit Tests For Existing Python Code // Part 2 of 2
ArjanCodes
58 Make Sure You Choose The Right Data Structure // Python Tips
Make Sure You Choose The Right Data Structure // Python Tips
ArjanCodes
59 5 Tips For Object-Oriented Programming Done Well - In Python
5 Tips For Object-Oriented Programming Done Well - In Python
ArjanCodes
60 Next-Level Concurrent Programming In Python With Asyncio
Next-Level Concurrent Programming In Python With Asyncio
ArjanCodes

This video teaches how to apply Uncle Bob's SOLID design principles to software design using Python, covering key principles such as Single Responsibility Principle, Open-Closed principle, and Liskov Substitution Principle. By following these principles, developers can create more maintainable, flexible, and scalable software systems.

Key Takeaways
  1. Extract the pay method from the Order class and put it into a separate class called PaymentProcessor
  2. Create a PaymentProcessor class with different payment methods
  3. Refactor the pay method to split it into two methods, pay debit and pay credit
  4. Remove the if-else statement that checks for the various payment types
  5. Pass the Order as a parameter to the PaymentProcessor class to process the payment and update the order status to 'paid'
  6. Create an abstract class and subclasses for different payment types
  7. Implement the Open-Closed principle
  8. Fix the Liskov Substitution Principle violation
๐Ÿ’ก The SOLID principles are essential for software developers to create maintainable, flexible, and scalable software systems, and can be applied to various programming languages, including Python.
๐Ÿ”’ Pro feature: Ask AI to explain this lesson โ†’

Related AI Lessons

โšก
A Young Designerโ€™s Question: What Are Companies Actually Hiring For?
Learn what companies are actually hiring for in UX design and how to position yourself for success
Medium ยท UX Design
โšก
Why Clear Calls-to-Action Are Essential for Business Websites
Learn why clear calls-to-action are crucial for business websites to convert visitors into customers
Medium ยท UX Design
โšก
AI in Design: The Skill That Gets Scarce When Making Gets Cheap.
Learn how AI is changing the design industry by making creation cheaper and more abundant, shifting the designer's role to curator and decision-maker
Medium ยท AI
โšก
Sheba Manager Mobile Apps: Retail OS in the Palm of a Merchantโ€™s Hand
Learn how a Sr. Product Designer revamped the Sheba Manager Mobile app to create a retail OS for merchants
Medium ยท UX Design

Chapters (10)

Intro
1:08 Example explanation
1:45 Single responsibility principle
5:01 Open/closed principle
7:36 Liskov substitution principle
9:48 Interface segregation principle
12:12 Interface segregation variety using composition
15:25 Dependency inversion
17:29 Final thoughts
18:15 Gag reel
Up next
Answering Revit Questions for Reddit
Balkan Architect
Watch โ†’