Believe me. There are no videos on youtube other than you to my knowledge that explain the design pattern before and after effect with real practice examples . Thank you so much !
True! I have only seen very abstract examples that almost completely overlap with the pattern description. Not bad, but real world examples are much more insightful once you get the general idea.
have you found any more? This is also exactly what I was looking for. I am concerned his newer stuff is a bit more faster-paced, but still good. I know we can slow the videos down, but this isn't about teaching us 'what to do', this level is all about 'how to think' is this video is a really really great example of this. Looking for more samples around the web if you found them
aws re:invent has some really good videos on software development, way beyond this. However, arjan’s video is great if you’re still at the level where you need practical examples.
Honestly, this is some of, if not the best, intermediate/advanced level content out there! Too many people focussing on the pure basics, but you presented this in such an easy to understand way! Forget binging Netflix, time to binge Arjan 😂 Thanks a lot ❤️
This is exactly the sort of level of information I need at my stage of learning to code. thank you so much really appreciate the thought you've put into this!
Highly Underrated Video, should have more than a million views. There are very important concepts which programmers don't even know. Thanks for the High Quality Content !!
It is not even possible to get this kind information from paid sources, but you are great person that making these kind of valuable lessons available on youtube. Thank you very much for all the effort, Respect.
I absolutely love this channel. I have always really struggled with the idea of trying to identify what "intermediate" level coding is, and I would say this channel really fills that gap in the existing TH-cam literature for python coding. I think this channel is going to really level up my skills, can't wait to see more!
Absolutely outstanding video Arjan! I've been coding Python for ~5 years and always saw these techniques in play but never really knew where they were coming from. Looking forward to the rest of the series.
Great video. I'm a data scientist but moving more and more to software development. I'm still having a hard time writing good code, but I'm starting to be able to recognize it when I see it. Videos like this are super helpful with that.
Fully agree. Basic concepts like this are highly undervalued by many devs since they struggle to grasp the rather abstract benefits. Unfortunatly todays high demand on devs also has lead to many people working in this field now who better should not be writing code for a living.
You create the Best videos on refactoring, design patterns, OOP, thank you a lot!! Most of the videos on youtube are very basic, with ridiculous, generic "foo", "add_numbers" etc. examples, but you show real, practical examples, and superb refactoring, just as if we asked a senior mentor to review our junior codes and recommend improvements. You are creating fantastic videos, thanks a lot!!
This is a such a great series! I've been looking for intermediate level design content for years. You've nailed the delivery and content. Looking forward to seeing more videos.
I was so frustrated of going through tonnes of leetcode interview exercises/tutorials and was looking for a more philosophical understanding of how to design python codes. Then I found your channel, I am now more confident after going through some if not all of your videos. Keep it up! The coding challenge is soon, will update if your content helped me land the job.
I noticed cohesion and coupling are pretty similar to the concept of between and within dispersion in cluster analysis. Kinda cluster should be maximized by between-cluster distance and minimize by within distance of elements inside. Why I noticed this only after your video? Your explanations are really genious.
I hate python but I watched the video anyways because nowadays almost nobody talks about cohesion and coupling. As you stated, the concepts shown apply to any language since they are abstract, language independent ones. Grats!
Your videos have changed the way I code. This is my second time going through this playlist. Since watching your videos I have been writing better code. Trying to do better every time. I have even done better at interviews. Thank you so much for great content. Merry Christmas and Happy New Year!
Sir, you are really amazing teacher. Your teaching style is very explicit and clear. But there are several other parts of the programming world I would like to learn from you, and these are (mentioned based on my interests) 1) Data Structure and Algorithms 2) Programming along with any GUI Library (I prefer tkinter) 3) Also teach us about Databases (SQL , NoSql (mongoDb etc)) Thank you Sir, I hope, We'll be blessed with these videos in future.
Exactly the kind of content that so many are actually looking for!!! If we have developer jobs without great code-review and training practices, we are stuck trying to figure out how to improve our code quality by ourselves. This is appreciated 1000x. Something I'd please ask going forward, and the reason I am responding in THIS video instead of your others - please don't go TOO FAST in your videos. This video was a great speed and I am concerned that in some of the vids you have made since that you are moving too fast. Please remember that this isn't about 'how to do' something, it is about 'how to (structure your) thinking'. This takes time to settle into the brain and the programmers watching are constantly trying analyze the 'why' of what you are doing and fit it back into their own models. Please use this type of video pacing as an example in your newer videos. Also, please always debug on screen, we've all been there and it is really great to watch what you do too.
I just discovered your channel, I always found Design Patterns boring, but I watched almost all your videos about it. Thank you, you make it very playful and concrete and the rhythm is also perfect !
One interesting concept to add to this: We could define the string we print as the return value of the __str__ method of the class instead. Then in print method of the class put print(self). That way we can both print the str with a call to print or get the str as an output to write somewhere else with str(instance)
Usually the way would be to overwrite both, the __str__ and __repr__ (the latter should contain a representation similar how we would reconstruct the object in python). __str__ overwriting should be done carefully and usually keep it as simple as possible. Most often, we would not want to have a formatted string containing arguable design decisions. Especially, having newlines in __str__ should always taken with some careness. If these objects are included in other objects, you'll start having problems visualizing them without getting corrupt visualizations. Just think about printing out a little table as one example. There are useful exceptions, e.g. pandas dataframes, so they work very well with interactive environments. Here I'd argue that __str__ should just contain the information a bit more minimal in a one liner. Nowadays in recent python, we'd usually just define the data classes as dataclasses and then we'll automatical get a useful __str__ and __repr__ and __init, what reduces the need to even think and debate it. The usual way to deal with a pretty printing or a formatted output is to add a formatted_str or similar called function. One reason is also, that you want to influence the formatting with options (and you can't really do that in __str__). E.g. whether you want a colon there, or maybe you want output it as a csv (so you can pipe into a database). Indeed, very often, you could even think about delegating it to a specialized library like python-tabular or similar. Anyway, the only thing I really disliked in this video is to call the method "print". I would always suggest, especially to learners, not to use any keywords or global function names as function names. Even if it fits the purpose of the method very well, the chance for both confusion and hard to debug errors is significant. You can even see it in this video. There are three prints in three consecutive lines: the first is in a method name declaration, the 2nd one calls the global standard python print and the 3rd one calls the print method of another object. It's even worse that the three methods will do something similar. It's only a question of time till the wrong print is used, not caught immediately and the ending up in a subtle and close to impossible findable bug. I mean, you still can call print(vehicle) or vehicle.print() that both will do something similar, but different. Anyway, this video is outstanding good!
You are a god for uploading this series. Starting out as a python developer, I found myself coming across difficult issues when returning to old code I've written where better understanding of design patterns could've helped. The very few tutorials covering this stuff are either long form lectures, and the best books on software design use Java as a reference. This is such a great niche that you're tackling and I hope your account accrues more subscribers and viewers. Thank you!
As a senior dev in my team your sample code for bad example gave me a slight headache. But your explanation to all the changes made me way too happy. Thanks for the great content 👍. After completely watching the video this reminded me why people say good code doesn't need any mandane comments.
8:00 this is excellent advice, just what I needed tbh. think about the data first before doing any coding, let the data and their relationships guide the program structure!
Great stuff, thank you!! I really appreciate this kind of intermediate+ material. There is very little available. Looking forward to the rest of the series.
You could use dataclasses to save a lot of boilerplate. And I like to implement __str__ methods to print objects. But I guess you left that out to make it not too complicated. Anyway nice videos. Good to watch.
Thank you! Yes - dataclasses are really helpful, as are the __str__ methods for printing. It's always a challenge to make sure the examples used to explain a concept do not introduce too many other 'new' things at the same time. I do think a video about these 'helper' libraries would be useful, as they really save you a lot of time.
Yeah, that's an important point. But you are doing great at finding the right mix which is shown by your amazing growth over the last month. Will definitly follow your upcoming videos - keep going!
Hallo Arjan. Dank voor je uitstekende uitleg zeer leerzaam ik ga de rest van de video's bekijken educatie moet vrij en toegankelijk zijn voor iedereen een kopje koffie komt zeker. Dank Khaled
Thanks for this info series. It is nice to know the CS terms for some of the things I have learned from practical experience. In particular, a favourite of mine is to store the info and related methods in an Enum. In this case I would have defined `class Vehicle Registry(VehicleInfo, Enum)` and define the different type of vehicles as Enum members.
Great video! If we want to go further, we can create abstract class and give an object VehicleRegistry to the application and thus increase the decoupling We can also create another class to compute financial stuff like prices, taxes and even reduction and thus increase coupling.
Your videos are absolutely amazing! I can only imagine how much work and hours you have put into this. Thank you for sharing your knowledge to all of us learning Python!
Regarding naming convention and it's connection to your "Functions vs Classes" video... Functions = action_focused, Classes = StateFocused... I don't know, is it unwritten rule or just coincidence, but in your code: Classes are named like NounSomething (like VehicleRegistry, Noun = State) Functions are named like verb_something (like register_vehicle, verb = action) Nice! :)
Thank you for the great video about cohesion and coupling, I can learn a lot from these videos about code structure design. One question about the types you added at minute 10:00 to the classes. When to use it that way compared to when using it directly in constructor e.g.: __init__(self, x: str)?
Love it. It would be extremely more helpful to also explain the details of how Expert is used to produce these Lowly Coupled and Strongly Cohesive design. For example you mention that register_vehicle having to know about implementation details of another class is a "bad thing" and it would be better to add it to Vehicle_Registry.... and you explained why doing this would help clearly. But Larman also suggests that abstracting these patterns as much as possible is good, and so perhaps go into how you are assigning responsibility to the class that has the information to fulfill the responsibility. This is the solution Expert provides, as noted by Larman, and continuously using these terms to explain what you're doing is helpful.... Otherwise you'd have to look up the book and the read the chapter on GRASP to understand more deeply and not everyone is inclined to do so!
Hi Dasiq, thanks for the feedback! That's an excellent suggestion - in this example, I wanted to focus on the cohesion and coupling concepts, but the other aspects of GRASP such as Information Expert are definitely useful to talk about as well. I might do another video in the future, where I talk specifically about this.
Dear Arjan, thank you for sharing such a detailed and thoughtful video. I loved how you explain the though process of improvement. It's hard to find such content out there. Please keep going. I look forward to studying all of your catalogue (see what I did there!) ;)
Great video! just a minor vocabulary pointer (business people have committed far worse sins): if you can't actually measure it, it's not a metric by definition. Cohesion and Coupling are heuristics. It's an esoteric word I'm trying to bring back!
Wow , this is something different , there are tons tutorials but you are good ! keep doing . Looking for descriptors and design patterns lecutres, any idea ?
There are a few design things I feel like I'd change: 1. As others have mentioned, Vehicle and VehicleInfo would be good as dataclasses. 2. Using enums instead of a boolean "electric" flag. This would allow for adding more vehicle types in the future, such as "hybrid" or "diesel," if one needs to differentiate the two. 3. __str__() is much cleaner when printing stuff, rather than using a unique print() method. This is obviously a boon if, as you said, one wants to develop a GUI.
Great series with many valuable insights!! Could you elaborate the different types of couplings and cohesions happening in the code? But nonetheless the video was fantastic.
Hi Arjan, This video is immensely helpful, and I look forward to seeing the rest of the playlist! However, I am commenting because a coding practice you demonstrate is confusing to me. As I do not use Python day to day and don't come across the latest coding practices, I am trying to seek some clarity from you and other folks who are more proficient! In the Vehicle and VehicleInfo classes, you are defining variables that are class members, and later using them as object members (referencing via self). This is allowed in Python, but the issue is that self(dot)id = id statement for example would create an object member of the same name on the spot. This will shadow the class member id defined earlier whenever self(dot)id is accessed. As per my understanding, defining the variables in a C++ like style at the top has distinctly different semantics in Python than defining them in __init__ (class member vs. object member). From what I could make of it, the only defined class member at the top of the class that gets used is VehicleRegistry.vehicle_info dictionary, the rest are object members created in __init__ that shadowed the original class member definitions.
Arjan, one small request : Can you make a video on how to structure a python project, or package? Regarding your question, one badly designed library is the collections package in python.
Great stuff! I like to think of a class as a bunch of cohesive tiny functions (either return one thing or has one side effect, rarely having both) that work on shared data or attributes. If the tiny functions have no shared data between them, write them in just normal functions. All the data/attributes should be defined in __init__ method or as class variables if they affect the class a whole rather than an instance (class variables are at the same indentation level as class methods). I refuse to add new attributes in any other method besides __init__. If I had to create a new attribute in a method so I can use it in another method, I could add that attribute in the __init__ method and default it to a reasonable value (None, 0, [], {}, "", etc.) so anyone reading my code can understand this class has these attributes/data and if they have default values, I know those attributes could be changed later if a method has been invoked.
Thank you! Separating declaration of data from usage of data wherever you can is an excellent best practice. It’s a pity Python doesn’t enforce this like most other object-oriented languages. As a developer, you need to be able to easily understand what the structure is of the data in a class, otherwise, what is the benefit of using a class in the first place?
@@ArjanCodes yeah that’s true. There is a way around it by inherently from typing.NamedTuple or using the __slot__ class variable. But that is extra work. Adding attributes dynamically could have its merits in GUI classes like PyQt5 but it confuses me when reading someone’s else code. Even when i do GUI classes and the attributes have not been created yet until a signal is emitted, I still define them in the __init__ method and default it to None. I know the code will be verbose but the intention of what I am doing is clear to my future me and future reviewers I hope. Speaking of GUI, i dislike putting my widget data/attributes in a method called setupIU and calling that method within the __init__ method. I could put all the UI data and other data in the init method and separate them by empty lines or comments.
Hi Arjan, thank you for your great video series. I have some comments: 1) You talk about low cohesion of a single function, however cohesion is usually a concept defined on the module/class level: en.wikipedia.org/wiki/Cohesion_%28computer_science%29. High cohesion means the methods and data of a class work well together to fulfill the (hopefullfy single) responsibility of the class. The problem of your function is rather that it does too many things and has too many responsibilites, however the problem is not low cohesion since this is a concept on the module/class level. 2) Enums instead of string constants such as "BMW 5" would greatly improve the example. 3) Enabling pylint in VS code would help you to find typos much earlier. 4) I recommend to use "is_electric" instead of "electric" as a name to improve readability. The name "is_electric" clearly tells the reader that this is a boolean while "electric" is vague in comparison and does not sound boolean.
Hi Robert, thanks for your suggestions! About cohesion: I don't think this is as black-and-white as you state it. "module" can mean different things in different programming languages. On top of that, the distinction between a function and a class is not always that clear. For example, in Python you can define functions within a function. Shouldn't we be able to talk about cohesion of the outer function? If you use React for web development, you have functional components, which are functions with state. These functional components can get quite big and behave like classes, and we should be able to look at cohesion of a functional component even if it's not a class. So how I see cohesion is that a piece of code should have one main responsibility. The scope of that responsibility changes depending on the level at which you're operating (library, namespace, class, function/method).
Hmm, watched the video, couldn't do it myself, so I watched again and did coding side by side and I did it. However I can't imagine I would be able to do it alone. Anyway I surely learned at least something. Thanks.
I like the gist of the concepts of cohesion and coupling, however they're not really 'metrics' until you find a way of (at least operationally) measuring them. How would you quantify these notions?
Great video Arjan. One question: 1. def create_vehicle(): return Vehicle(id, license_plate, self.vehicle_info[brand]) 2. def add_vehicle_info(self, brand, electric, catalogue_price): self.vehicle_info[brand] = VehicleInfo(brand, electric, catalogue_price) Aren't this classes/methods too coupled with Vehicle and VehicleInfo? Thanks 😜😜
I really enjoyed this video to the point I had to go back and try to refactor some of my project. The issue I'm having is trying to refactor my database models. Could you make a video refactoring code for a database related project?
When you do this, please go as slow and 'simple' as we did in this type of example. This video is perfect in many ways. It is a bit slower, more of 'figuring it out as we go' type of feel then the newer material. If the material goes too quick or is too refined, it won't help the intermediate level programmer as much since we are all here trying to learn how to think, not how to do. Thank you for making these videos!!
At 24:24, the application class should have a init method that makes VehicleRegistry(). I think the VehicleRegistry() must not depends on register_vehicle method. If you register new vehicle, VehicleRegistry() method will also be run. So it is wrong, I think. Thanks for your good video.
add_vehicle_info arguments should definitely be in VehicleInfo class as attributes instead of defined in the VehicleRegistry class. Then when you instantiate your vehicle and pass the brand, it automatically assigns those attributes.
@@ArjanCodes I just figured out the main point: you can solve elegantly circular imports by making use of abstract classes and using these for the dep. injection when defining classes that need to know about each other beforehand. The sloppy solution is to delay the import of, say instance B, in the method of instance A that actually use instance B. works the same way, probably the most common solution but it leaves a lot more to the coder to debug and all the rest. If you want a descritpion of the program, just ask me. btw tried to use discord but says I am not allowed to post messages int chats. thanks for reading, cheers!
@@andreacazzaniga8488 Yes, the concept of Dependency Inversion is one of the biggest design/architecture patterns that 'blew my mind' 🤯 when I first learned about it and finally understood it. When I put it into practice on my project at the time, it really improved the overall structure, and when done consistently it pretty much eliminates the problem of circular imports. BTW: Just to be clear, Dependency Inversion is different (more abstract) than Dependency Injection. You can do Dependency Inversion without necessarily doing Dependency Injection. I understand Dependency Injection is also very powerful, but in my case it would have been much more complicated than just reorganizing some classes, introducing a few interfaces/abstract-classes, and modifying the 'direction' of which 'modules' import from other 'modules'.
If I'm understanding this correctly, cohesion and decoupling can be closely achieved in general by convenient grouping of information, such that methods that operate on that information can be colocated in the same class? I have many questions, but I'm in luck, as this is only the first video in this wonderful series. Keep it up!
Learn more about how to launch a software product faster here: th-cam.com/video/MU20ah5s9ww/w-d-xo.html
Remind Me! 1 week
@@AlexB-op7kb how goes it?
@@javierfry97 haha remind me 1 year. I forgot to follow up
Believe me. There are no videos on youtube other than you to my knowledge that explain the design pattern before and after effect with real practice examples . Thank you so much !
You're welcome Kannan, happy that you're enjoying the videos!
I third this
True! I have only seen very abstract examples that almost completely overlap with the pattern description. Not bad, but real world examples are much more insightful once you get the general idea.
have you found any more? This is also exactly what I was looking for.
I am concerned his newer stuff is a bit more faster-paced, but still good. I know we can slow the videos down, but this isn't about teaching us 'what to do', this level is all about 'how to think' is this video is a really really great example of this. Looking for more samples around the web if you found them
aws re:invent has some really good videos on software development, way beyond this. However, arjan’s video is great if you’re still at the level where you need practical examples.
Thank you for not making 'hello world' tutorials!!!!!!! Keep going! :)
Thank you! Will do :)
Agreed! Thank you Arjan, this is super helpful stuff!!
Honestly, this is some of, if not the best, intermediate/advanced level content out there! Too many people focussing on the pure basics, but you presented this in such an easy to understand way!
Forget binging Netflix, time to binge Arjan 😂
Thanks a lot ❤️
This is exactly the sort of level of information I need at my stage of learning to code. thank you so much really appreciate the thought you've put into this!
Thank you! Happy that you enjoy the videos.
I'm glad you got something out of this , but read my post.
@@larrytroxler7017 Can't see your latest comments, so I can't unfortunately. Why don't you make your own video?
were you able to find any other examples of this level of code teaching? This is where I landed too.
Highly Underrated Video, should have more than a million views. There are very important concepts which programmers don't even know.
Thanks for the High Quality Content !!
Thank you Talha, I’m happy you’re enjoying the videos!
True, but as a explained in my initial reply, there are some problems with this guy's post.
It is not even possible to get this kind information from paid sources, but you are great person that making these kind of valuable lessons available on youtube. Thank you very much for all the effort, Respect.
Thank you, Space Walker - glad you like the content!
I absolutely love this channel. I have always really struggled with the idea of trying to identify what "intermediate" level coding is, and I would say this channel really fills that gap in the existing TH-cam literature for python coding. I think this channel is going to really level up my skills, can't wait to see more!
Thanks Dennis, I’m glad you’re enjoying the videos and that they’re helpful to you.
@@ArjanCodes Certainly very helpful! Do you have any other ideas in the pipeline for content that we can look forward to?
Absolutely :).
did you find any other channels that are similar? I did not but I am also looking to do much better here as well at this level.
Absolutely outstanding video Arjan! I've been coding Python for ~5 years and always saw these techniques in play but never really knew where they were coming from. Looking forward to the rest of the series.
Thank you so much, Daniel, glad you enjoyed it!
Great video. I'm a data scientist but moving more and more to software development. I'm still having a hard time writing good code, but I'm starting to be able to recognize it when I see it. Videos like this are super helpful with that.
Fully agree. Basic concepts like this are highly undervalued by many devs since they struggle to grasp the rather abstract benefits. Unfortunatly todays high demand on devs also has lead to many people working in this field now who better should not be writing code for a living.
You create the Best videos on refactoring, design patterns, OOP, thank you a lot!!
Most of the videos on youtube are very basic,
with ridiculous, generic "foo", "add_numbers" etc. examples,
but you show real, practical examples,
and superb refactoring,
just as if we asked a senior mentor to review our junior codes and recommend improvements.
You are creating fantastic videos, thanks a lot!!
This is a such a great series! I've been looking for intermediate level design content for years. You've nailed the delivery and content. Looking forward to seeing more videos.
Thank you Cristian, happy you are enjoying the series!
Completely agree! Loving this series! Looking forward to more videos! Great job!!!
I was so frustrated of going through tonnes of leetcode interview exercises/tutorials and was looking for a more philosophical understanding of how to design python codes. Then I found your channel, I am now more confident after going through some if not all of your videos. Keep it up! The coding challenge is soon, will update if your content helped me land the job.
Did you land the Job yet ?
@@marookegberosamuel I did! but unfortunately (or fortunately) it's not just python - so a lot of learning curves!
I noticed cohesion and coupling are pretty similar to the concept of between and within dispersion in cluster analysis. Kinda cluster should be maximized by between-cluster distance and minimize by within distance of elements inside. Why I noticed this only after your video? Your explanations are really genious.
Nice observation! It makes sense to me.
I can even tell how much I love your content sir, thank you for creating these videos all for free, you are a hero.
Thank you for the kind words, Mikaeil! I'm glad you like the videos :)
I hate python but I watched the video anyways because nowadays almost nobody talks about cohesion and coupling. As you stated, the concepts shown apply to any language since they are abstract, language independent ones. Grats!
Your videos have changed the way I code. This is my second time going through this playlist.
Since watching your videos I have been writing better code. Trying to do better every time. I have even done better at interviews.
Thank you so much for great content.
Merry Christmas and Happy New Year!
Sir, you are really amazing teacher. Your teaching style is very explicit and clear. But there are several other parts of the programming world I would like to learn from you, and these are (mentioned based on my interests)
1) Data Structure and Algorithms
2) Programming along with any GUI Library (I prefer tkinter)
3) Also teach us about Databases (SQL , NoSql (mongoDb etc))
Thank you Sir, I hope, We'll be blessed with these videos in future.
Words can't describe how awesome your job is. Watching your videos makes me want to refactor all my shitty code
your work stands out in flood of basics tutorials with silly examples, thank you Arjan!
Exactly the kind of content that so many are actually looking for!!! If we have developer jobs without great code-review and training practices, we are stuck trying to figure out how to improve our code quality by ourselves. This is appreciated 1000x.
Something I'd please ask going forward, and the reason I am responding in THIS video instead of your others - please don't go TOO FAST in your videos. This video was a great speed and I am concerned that in some of the vids you have made since that you are moving too fast. Please remember that this isn't about 'how to do' something, it is about 'how to (structure your) thinking'. This takes time to settle into the brain and the programmers watching are constantly trying analyze the 'why' of what you are doing and fit it back into their own models.
Please use this type of video pacing as an example in your newer videos.
Also, please always debug on screen, we've all been there and it is really great to watch what you do too.
20:26 Truer words have never been spoken 🙏🙏
Fantastic series! I think all of the concepts you're discussing are vastly under-appreciated
I just discovered your channel, I always found Design Patterns boring, but I watched almost all your videos about it. Thank you, you make it very playful and concrete and the rhythm is also perfect !
Thank you so much! I’m happy that you’re enjoying the videos.
This is what I was looking for almost a year. Thanks, Arjian.
Your jumper should read "Never stop explaining". Excellent contyent, thank you so much
I’ll keep it mind when I do shopping again, haha.
One interesting concept to add to this:
We could define the string we print as the return value of the __str__ method of the class instead.
Then in print method of the class put print(self).
That way we can both print the str with a call to print or get the str as an output to write somewhere else with str(instance)
Usually the way would be to overwrite both, the __str__ and __repr__ (the latter should contain a representation similar how we would reconstruct the object in python). __str__ overwriting should be done carefully and usually keep it as simple as possible. Most often, we would not want to have a formatted string containing arguable design decisions. Especially, having newlines in __str__ should always taken with some careness. If these objects are included in other objects, you'll start having problems visualizing them without getting corrupt visualizations. Just think about printing out a little table as one example. There are useful exceptions, e.g. pandas dataframes, so they work very well with interactive environments.
Here I'd argue that __str__ should just contain the information a bit more minimal in a one liner.
Nowadays in recent python, we'd usually just define the data classes as dataclasses and then we'll automatical get a useful __str__ and __repr__ and __init, what reduces the need to even think and debate it.
The usual way to deal with a pretty printing or a formatted output is to add a formatted_str or similar called function. One reason is also, that you want to influence the formatting with options (and you can't really do that in __str__). E.g. whether you want a colon there, or maybe you want output it as a csv (so you can pipe into a database). Indeed, very often, you could even think about delegating it to a specialized library like python-tabular or similar.
Anyway, the only thing I really disliked in this video is to call the method "print". I would always suggest, especially to learners, not to use any keywords or global function names as function names. Even if it fits the purpose of the method very well, the chance for both confusion and hard to debug errors is significant. You can even see it in this video. There are three prints in three consecutive lines: the first is in a method name declaration, the 2nd one calls the global standard python print and the 3rd one calls the print method of another object. It's even worse that the three methods will do something similar. It's only a question of time till the wrong print is used, not caught immediately and the ending up in a subtle and close to impossible findable bug. I mean, you still can call print(vehicle) or vehicle.print() that both will do something similar, but different.
Anyway, this video is outstanding good!
You are a god for uploading this series. Starting out as a python developer, I found myself coming across difficult issues when returning to old code I've written where better understanding of design patterns could've helped. The very few tutorials covering this stuff are either long form lectures, and the best books on software design use Java as a reference. This is such a great niche that you're tackling and I hope your account accrues more subscribers and viewers. Thank you!
Thank you so much - glad you like the content!
Yes please. Can't even believe you made a reference to bridger and template pattern. Fantastic.
Thank you!
This series is great, both the topics and your way of explaining stuff. Thanks for taking the time to make these!
Thanks Pim, glad you like it!
As a senior dev in my team your sample code for bad example gave me a slight headache.
But your explanation to all the changes made me way too happy.
Thanks for the great content 👍.
After completely watching the video this reminded me why people say good code doesn't need any mandane comments.
Thank you, glad you liked the example (at least the after part ;) ).
great walkthrough. the example code really demonstrates the concepts
This really pulled the concepts together for me.
Glad to hear it was helpful!
8:00 this is excellent advice, just what I needed tbh. think about the data first before doing any coding, let the data and their relationships guide the program structure!
Great stuff, thank you!! I really appreciate this kind of intermediate+ material. There is very little available. Looking forward to the rest of the series.
Thanks! Happy you liked it!
You could use dataclasses to save a lot of boilerplate. And I like to implement __str__ methods to print objects. But I guess you left that out to make it not too complicated. Anyway nice videos. Good to watch.
Thank you! Yes - dataclasses are really helpful, as are the __str__ methods for printing. It's always a challenge to make sure the examples used to explain a concept do not introduce too many other 'new' things at the same time. I do think a video about these 'helper' libraries would be useful, as they really save you a lot of time.
Yeah, that's an important point. But you are doing great at finding the right mix which is shown by your amazing growth over the last month. Will definitly follow your upcoming videos - keep going!
Hallo Arjan. Dank voor je uitstekende uitleg zeer leerzaam ik ga de rest van de video's bekijken educatie moet vrij en toegankelijk zijn voor iedereen een kopje koffie komt zeker. Dank Khaled
Graag gedaan, Khaled!
Thanks for this info series. It is nice to know the CS terms for some of the things I have learned from practical experience.
In particular, a favourite of mine is to store the info and related methods in an Enum.
In this case I would have defined `class Vehicle Registry(VehicleInfo, Enum)` and define the different type of vehicles as Enum members.
Exactly. You should never store classifications like these as bools. His final code would never pass a software review.
It's really cool that you used composition and not inheritance!
Thanks! Yes, I'm a big fan of composition over inheritance (you may have noticed that in some of my other videos 😉).
Im really happy to have found this channel, I'm really enjoying this Better Python Code playlist!, thank you!
Great video!
If we want to go further, we can create abstract class and give an object VehicleRegistry to the application and thus increase the decoupling
We can also create another class to compute financial stuff like prices, taxes and even reduction and thus increase coupling.
these videos are gold, everybody just tells tutorial kid examples , here are the real men examples
Glad you like them! And even better, they're for men and women ;).
Your videos are absolutely amazing! I can only imagine how much work and hours you have put into this. Thank you for sharing your knowledge to all of us learning Python!
Holy cow, this is first video that I am subscribing, liking and sharing right away. This is a gem. Thank you very much Arjan.
Thank you very much! I’m happy you liked the video.
This is outstanding content, creatively and articulately presented. Bravo.
I'm glad you enjoyed the video!
Love your work man. Your calm and clear delivery is a breath of fresh air. Keep it up.
I'm so grateful to have found your channel. Very great content. Thank you very much! Cheers from Brazil!
Hi Goulartto, I'm happy to hear you like the content - cheers!
This series is gold
This video is underrated. Well done!
Thanks Benjamin, glad you liked it!
Great video. I wish I knew about your channel long before now. Thanks a million!
Found it, watch it, love it. You're awesome!
Thank you, glad to hear you liked the video!
Good channel with very very good content!! Keep sharing your knowledge like this Arjan!!! Thanks so much!!!
Thank you Leonardo, glad you like the content!
Thank you Arjan for sharing your knowledge in such easy and clear way, appreciate
Thanks so much Jakub, glad the content is helpful!
Regarding naming convention and it's connection to your "Functions vs Classes" video...
Functions = action_focused, Classes = StateFocused...
I don't know, is it unwritten rule or just coincidence, but in your code:
Classes are named like NounSomething (like VehicleRegistry, Noun = State)
Functions are named like verb_something (like register_vehicle, verb = action)
Nice! :)
this is very perfect constringe of python code that I never have it's so amazing, it has more knowledgeable pattern design
Glad it was helpful!
Thank you for the great video about cohesion and coupling, I can learn a lot from these videos about code structure design.
One question about the types you added at minute 10:00 to the classes. When to use it that way compared to when using it directly in constructor e.g.: __init__(self, x: str)?
First person I've subscribed to in over a year. Great videos sir :D
Welcome aboard!
One of the best content. Thank you so much for sharing your knowledge. I am going to watch all of your other vedios. Please keep on the great work.
At 16:10 I'm screaming internally but Arjun, you've shown us how to use dataclasses!
Love it. It would be extremely more helpful to also explain the details of how Expert is used to produce these Lowly Coupled and Strongly Cohesive design.
For example you mention that register_vehicle having to know about implementation details of another class is a "bad thing" and it would be better to add it to Vehicle_Registry....
and you explained why doing this would help clearly. But Larman also suggests that abstracting these patterns as much as possible is good, and so perhaps go into how you are assigning responsibility to the class that has the information to fulfill the responsibility. This is the solution Expert provides, as noted by Larman, and continuously using these terms to explain what you're doing is helpful.... Otherwise you'd have to look up the book and the read the chapter on GRASP to understand more deeply and not everyone is inclined to do so!
Hi Dasiq, thanks for the feedback! That's an excellent suggestion - in this example, I wanted to focus on the cohesion and coupling concepts, but the other aspects of GRASP such as Information Expert are definitely useful to talk about as well. I might do another video in the future, where I talk specifically about this.
Dear Arjan, thank you for sharing such a detailed and thoughtful video. I loved how you explain the though process of improvement. It's hard to find such content out there. Please keep going. I look forward to studying all of your catalogue (see what I did there!) ;)
Great video! just a minor vocabulary pointer (business people have committed far worse sins): if you can't actually measure it, it's not a metric by definition. Cohesion and Coupling are heuristics. It's an esoteric word I'm trying to bring back!
Great stuff Arjan! You got a new subscriber! Groetjes uit Den Haag!
This is such a great series. Thanks so much!
Thank you Erik, happy you are enjoying it.
Wow , this is something different , there are tons tutorials but you are good ! keep doing . Looking for descriptors and design patterns lecutres, any idea ?
Well well done! You've got another fan here. I'm digging your videos.
Thank you @cocoonk1d! I’m glad you like the videos!
Easiest sub of my life.
Thank you! And welcome onboard ;).
There are a few design things I feel like I'd change:
1. As others have mentioned, Vehicle and VehicleInfo would be good as dataclasses.
2. Using enums instead of a boolean "electric" flag. This would allow for adding more vehicle types in the future, such as "hybrid" or "diesel," if one needs to differentiate the two.
3. __str__() is much cleaner when printing stuff, rather than using a unique print() method. This is obviously a boon if, as you said, one wants to develop a GUI.
This is some really good quality video. You covered so many concepts , thanks
"gaaaamd neeek" which means really good in my language, keep up the good work!!!!!!
Thank you! Will do! (what language is this by the way?)
What a really great topic that no one ever seems to discuss. And very well presented. New subscriber.
Thank you Chuck, happy you like it.
I'm learning a lot from your videos - thanks.
Glad to hear the videos are helpful!
Very challenging, yet very interesting, and great to learn and understand. Thanks
Glad you enjoyed it!
Great series with many valuable insights!!
Could you elaborate the different types of couplings and cohesions happening in the code?
But nonetheless the video was fantastic.
Glad you liked it, James. I’ll definitely revisit cohesion and coupling again soon, and then I’ll also talk about the different types.
Thanks man really wished I'd learned this sooner
Immensely helpful and well explained! Thank you so much...looking forward for more 😃
Thanks so much Connor, glad the content is helpful!
I think you should start looking more into shortcuts :D Like copy line to bottom and multi-line caret
Hi Arjan,
This video is immensely helpful, and I look forward to seeing the rest of the playlist! However, I am commenting because a coding practice you demonstrate is confusing to me. As I do not use Python day to day and don't come across the latest coding practices, I am trying to seek some clarity from you and other folks who are more proficient!
In the Vehicle and VehicleInfo classes, you are defining variables that are class members, and later using them as object members (referencing via self). This is allowed in Python, but the issue is that self(dot)id = id statement for example would create an object member of the same name on the spot. This will shadow the class member id defined earlier whenever self(dot)id is accessed. As per my understanding, defining the variables in a C++ like style at the top has distinctly different semantics in Python than defining them in __init__ (class member vs. object member).
From what I could make of it, the only defined class member at the top of the class that gets used is VehicleRegistry.vehicle_info dictionary, the rest are object members created in __init__ that shadowed the original class member definitions.
Arjan, one small request : Can you make a video on how to structure a python project, or package?
Regarding your question, one badly designed library is the collections package in python.
Great stuff! I like to think of a class as a bunch of cohesive tiny functions (either return one thing or has one side effect, rarely having both) that work on shared data or attributes. If the tiny functions have no shared data between them, write them in just normal functions. All the data/attributes should be defined in __init__ method or as class variables if they affect the class a whole rather than an instance (class variables are at the same indentation level as class methods). I refuse to add new attributes in any other method besides __init__. If I had to create a new attribute in a method so I can use it in another method, I could add that attribute in the __init__ method and default it to a reasonable value (None, 0, [], {}, "", etc.) so anyone reading my code can understand this class has these attributes/data and if they have default values, I know those attributes could be changed later if a method has been invoked.
Thank you! Separating declaration of data from usage of data wherever you can is an excellent best practice. It’s a pity Python doesn’t enforce this like most other object-oriented languages. As a developer, you need to be able to easily understand what the structure is of the data in a class, otherwise, what is the benefit of using a class in the first place?
@@ArjanCodes yeah that’s true. There is a way around it by inherently from typing.NamedTuple or using the __slot__ class variable. But that is extra work. Adding attributes dynamically could have its merits in GUI classes like PyQt5 but it confuses me when reading someone’s else code. Even when i do GUI classes and the attributes have not been created yet until a signal is emitted, I still define them in the __init__ method and default it to None. I know the code will be verbose but the intention of what I am doing is clear to my future me and future reviewers I hope. Speaking of GUI, i dislike putting my widget data/attributes in a method called setupIU and calling that method within the __init__ method. I could put all the UI data and other data in the init method and separate them by empty lines or comments.
Thanks for a tutorial. It's really very useful and unique.
Hi Arjan, thank you for your great video series. I have some comments: 1) You talk about low cohesion of a single function, however cohesion is usually a concept defined on the module/class level: en.wikipedia.org/wiki/Cohesion_%28computer_science%29. High cohesion means the methods and data of a class work well together to fulfill the (hopefullfy single) responsibility of the class. The problem of your function is rather that it does too many things and has too many responsibilites, however the problem is not low cohesion since this is a concept on the module/class level. 2) Enums instead of string constants such as "BMW 5" would greatly improve the example. 3) Enabling pylint in VS code would help you to find typos much earlier. 4) I recommend to use "is_electric" instead of "electric" as a name to improve readability. The name "is_electric" clearly tells the reader that this is a boolean while "electric" is vague in comparison and does not sound boolean.
Hi Robert, thanks for your suggestions! About cohesion: I don't think this is as black-and-white as you state it. "module" can mean different things in different programming languages. On top of that, the distinction between a function and a class is not always that clear. For example, in Python you can define functions within a function. Shouldn't we be able to talk about cohesion of the outer function? If you use React for web development, you have functional components, which are functions with state. These functional components can get quite big and behave like classes, and we should be able to look at cohesion of a functional component even if it's not a class. So how I see cohesion is that a piece of code should have one main responsibility. The scope of that responsibility changes depending on the level at which you're operating (library, namespace, class, function/method).
@@ArjanCodes Hi Arjan, thank you for your response. I see, you mean cohesion in a broader sense here. I am not a dogmatic person anyway :)
It is a kind of ASMR video with high technical knowledge.
Hmm, watched the video, couldn't do it myself, so I watched again and did coding side by side and I did it. However I can't imagine I would be able to do it alone. Anyway I surely learned at least something. Thanks.
You’re welcome. Happy that you enjoyed the video!
Great video, but @18:40, wouldn't it be better to write a __str__ method rather than creating our own print method?
Probably that’s a better option indeed!
Great series! Thanks so much. Could you also touch the topic about Python and DI container?
Thank you Jan, I’m happy you’re enjoying the series. Thank you for the suggestion, I’ll keep it in mind for one of my next videos!
I love seeing beautiful code. Thank you for this!
Thanks Mark, glad you liked it!
It is not beautiful code, unfortunately. See me latest comment.
I like the gist of the concepts of cohesion and coupling, however they're not really 'metrics' until you find a way of (at least operationally) measuring them. How would you quantify these notions?
Great video Arjan.
One question:
1. def create_vehicle():
return Vehicle(id, license_plate, self.vehicle_info[brand])
2. def add_vehicle_info(self, brand, electric, catalogue_price):
self.vehicle_info[brand] = VehicleInfo(brand, electric, catalogue_price)
Aren't this classes/methods too coupled with Vehicle and VehicleInfo?
Thanks 😜😜
I really enjoyed this video to the point I had to go back and try to refactor some of my project. The issue I'm having is trying to refactor my database models. Could you make a video refactoring code for a database related project?
Thanks, great suggestion!
@@ArjanCodes thank you for your awesome videos, I look forward to learning more with you
When you do this, please go as slow and 'simple' as we did in this type of example. This video is perfect in many ways. It is a bit slower, more of 'figuring it out as we go' type of feel then the newer material. If the material goes too quick or is too refined, it won't help the intermediate level programmer as much since we are all here trying to learn how to think, not how to do. Thank you for making these videos!!
Excellent video. Thank you very much for this serie.
Thanks so much Das.
Thank you, Arjan. Superb content.
Thanks so much Ian, glad the content is helpful!
At 24:24, the application class should have a init method that makes VehicleRegistry(). I think the VehicleRegistry() must not depends on register_vehicle method. If you register new vehicle, VehicleRegistry() method will also be run. So it is wrong, I think.
Thanks for your good video.
Nice video Arjan!
add_vehicle_info arguments should definitely be in VehicleInfo class as attributes instead of defined in the VehicleRegistry class. Then when you instantiate your vehicle and pass the brand, it automatically assigns those attributes.
Also a video on how to avoid circular imports. Am i doing smtg wrong when it happens?
Thank you for the suggestion!
@@ArjanCodes I just figured out the main point: you can solve elegantly circular imports by making use of abstract classes and using these for the dep. injection when defining classes that need to know about each other beforehand. The sloppy solution is to delay the import of, say instance B, in the method of instance A that actually use instance B. works the same way, probably the most common solution but it leaves a lot more to the coder to debug and all the rest. If you want a descritpion of the program, just ask me. btw tried to use discord but says I am not allowed to post messages int chats. thanks for reading, cheers!
@@andreacazzaniga8488 Yes, the concept of Dependency Inversion is one of the biggest design/architecture patterns that 'blew my mind' 🤯 when I first learned about it and finally understood it. When I put it into practice on my project at the time, it really improved the overall structure, and when done consistently it pretty much eliminates the problem of circular imports.
BTW: Just to be clear, Dependency Inversion is different (more abstract) than Dependency Injection. You can do Dependency Inversion without necessarily doing Dependency Injection. I understand Dependency Injection is also very powerful, but in my case it would have been much more complicated than just reorganizing some classes, introducing a few interfaces/abstract-classes, and modifying the 'direction' of which 'modules' import from other 'modules'.
@@robharwood3538 yes maybe I meant dependency inversion I am still not clear with which one one is which, but yes, you got the point!
best best explanation ever
If I'm understanding this correctly, cohesion and decoupling can be closely achieved in general by convenient grouping of information, such that methods that operate on that information can be colocated in the same class?
I have many questions, but I'm in luck, as this is only the first video in this wonderful series. Keep it up!
Super thankful of this content!