Visit bit.ly/ARJAN50 to get 50% off the Pro version of Tabnine for 6 months!
@ehsisthatsweird2 жыл бұрын
python docs prefer raise NotImplementedError to ‘pass’ or ellipsis in empty abstract/protocol methods. I guess the reasoning for this is if you use super() then ‘pass’ might get you into trouble.
@mikefochtman7164 Жыл бұрын
@12:25 The little flip back and forth to confirm your customer ID was an integer, reminded me of a huge argument / debate our team had once. One side was, "It's made up of digits, so it's an 'int'." Other side was, "You do NOT perform any math or calculations with it so it is NOT an integer, it's a string of digits." (and a single individual that voted for, "It's a unique identifier, so it's its own class.") Couple of boring meetings later, the 'string of digits' camp finally wore everyone down and won the debate. lol
@XRay7772 жыл бұрын
A small side note on the annotation matter: 'from __future__ import annotations' is only available from python 3.7+. If you are on 3.6 you can just turn the annotation into a string, which will delay the evaluation until after the class is defined (see PEP 563 for details). The import actually does the same thing, but automagically.
@ChrisBNisbet2 жыл бұрын
The common prefix "customer_" is a hint to the dev/reviewer that the variables could/should be moved into some separate class/structure. I often see something similar in 'C' code where people create groups of structure fields all starting with the same prefix.
@TheTacticalDood2 жыл бұрын
Indeed that is the practice in C since it has no other way of avoiding namespace collisions.
@cheebadigga40922 жыл бұрын
@@TheTacticalDood well it has structs though.
@pedromartindelcampogonzale9613 Жыл бұрын
In the last code smell, the one about keyword args, if you are programming on a language that doesn't have this feature, you can use the builder design pattern when you have too many arguments for a constructor. If you're calling a method that is not a constructor, first, your method may be doing too much, but if you really need all the arguments, you can wrap them in a dataclass if it makes sense. Maybe you can even move the whole method and even others to this new class, if it feels better.
@Claxiux2 жыл бұрын
Code smells is an excellent name. It’s what made this series stand out and your channel with it!
@ZapOKill2 жыл бұрын
yeah, i am 100% sure he came up with the name all by himself!
@ArjanCodes2 жыл бұрын
Haha, I wish 😊. I think it was Martin Fowler who came up with the name.
@sergiovasquez72402 жыл бұрын
I am not a Python programmer, but I feel this an amazing resource to start good coding practices as soon as possible. Most of this advices translate very well to programming in general. Keep the hard work, and I hope there are more of this kind of videos coming. I bet there are very hard to make.
@ArjanCodes2 жыл бұрын
Thank you Sergio, will do!
@GulfCoastGrit2 жыл бұрын
Agree completely! I use these to improve my C# skills! 😊
@bocckoka2 жыл бұрын
to 6: in Rust, where you have move semantics, you can guarantee at compile time that you use your objects with stages properly, meaning that a state transition 'moves' the object, and you can't call methods of the previous state on it anymore, because it doesn't exist. it's called typestate pattern
@imadetheuniverse4fun2 жыл бұрын
I think you did a really good job showing code smells in code that may pass as "good" at first glance. For example the payment processor having a Protocol at first glance seemed like a good thing, but it turns out you don't need to use that and can decouple even further by simply creating the payment function with the correct parameters. Really shows that you should really think about how and where you apply these design patterns and principles.
@programming_in_ukrainian2 жыл бұрын
Hey Arjan! Nice video, thank you, but I have two things to discuss: 1. I slightly disagree with add_line_item implementation. IMHO it's better to pass native data types (name: str, quantity: int, price: int) than some custom type 'cause at least you can simplify communication with outer code (unpack dict or they would call method by passing native types) and not obligate other people to use your own object to do so. 2. Importing annotations from future is not the only way to declare your method would return value of the class itself, you can wrap its name in quotes and type hinting would still work the same way class A: def method(self) -> 'A': pass
@artemhrytsenko13532 жыл бұрын
27:05 you can put * at def some_function(*, a, b): ... and using it every single argument have to be assigned with keyword arguments (otherwise, TypeError would throw).
@ArjanCodes2 жыл бұрын
Good point, thanks!
@joem82512 жыл бұрын
You do a lot of good videos that illustrate SOLID principles. I think if you expand on those concepts with automatically-generated UML diagrams with Pylint's Pyreverse you could create some interesting content! Thank you for your videos -- you somehow always have something I need -- occasionally just when I need it!
@ArjanCodes2 жыл бұрын
Thanks Joe, will look into it!
@AlexBerkk11 ай бұрын
Tabnine ad. Pre-Copilot days were wild. I'm not crying, you're crying!
@deatho0ne587 Жыл бұрын
To your bonus tip, I agree in general. For most IDEs or Code Editors worth using, you can hover over the function/method name and get the names of every parameter/argument and their respective types. Also should give different impementations of a function if their are mutliple versions. VSC which it seems like you are using even did this around 27:59. Meaning a dev does not really have to do it if they know how to use their respective editor.
@rdwells10 ай бұрын
I would argue that there is one more minor code smell here: using an integer for a customer ID. My rule of thumb is that if you are not doing arithmetic on it, it's not a number. I learned this hard way with some manufacturing software I wrote. It had to read a list of order numbers in a text file dropped by some IT system and process those orders. They were 12-digit numbers, so I stored them as ints. (This was C++, so they were 64-bit ints.) Then IT decided to slowly replace their old mainframe database with a new Oracle system, and decided to mark orders from the new system by replacing the 12th digit with an "E". They did this without warning. I had one day to modify the program and change the type of a primary key on a bunch of database tables.
@dariuszspiewak56242 жыл бұрын
Ha! Finally found somebody who does not teach Python basics and the dry stuff of how to loop over a list (it's important as well, don't get me wrong), but actually teaches about Python software architecture and best practices :) Thank you, Arjan. That's genuinely valuable. By the way, Arjan, if you want really, really, REALLY awesome programmer keyboard and heavenly typing experience, get yourself the Kinesis Advantage keyboard. Once you do it, you'll never, ever look back on the usual QWERTY crap (even the so-called "ergonomic") which I don't touch today and don't want to even look at. I've also re-trained myself to type on a modified Dvorak layout (called Dvorak Programmer), so my hands and wrists will be healthy and thankful to me for the rest of my programming life :))) Not to mention the speed of touch-typing. Great videos. Gonna subscribe and have a look at your courses.
@an-lo97872 жыл бұрын
Hey Arjan! I appreciate you and the content you post weekly is very helpful. I have one question, do you import these codes and then determine areas you could improve, or do you write these codes and are going back over them now having a different perspective? Thank you for your feedback in advance!
@ArjanCodes2 жыл бұрын
Glad to hear it's helpful! It depends on the video type actually. For the code roast videos I work off the code of someone else, so there I mainly treat it as a code review and try to find areas of improvements. For these code smell videos, I have a list of things in my head that I've seen people make mistakes with in the past (including myself), and then I try to come up with an example that shows these things in a logical way. Overall, if I refactor code it's always an iterative process, where I try to improve something and then that triggers another possible improvement. Or what I had in mind didn't work and I have to change it back, haha :).
@andyanderson222 Жыл бұрын
Not only these tutorials are awesome, but i really like your sense of humor. These 7 x "Code smell" at the beginning was very funny) By the way, 1 question i have watching this video is why do we put default values on every Customer dataclass field? If we let user to create empty instance of customer without putting any info into constructor is it good for us? Like what will we do with this totally empty object later?
@shS836 ай бұрын
Watched your videos for the first time yesterday and became an instant fan. Subscribed. Keep up the good work!
@ArjanCodes6 ай бұрын
Welcome aboard! Happy to have you here.
@DjegGoEu2 жыл бұрын
Hey Arjan, At minute 22:56, doesn't it make more sense to use a class method to handle the creation and deployment of the object? I always have a hard time distinguishing between class method and static method usages, but that case seems to work fine with class methods. What do you think?
@ArjanCodes2 жыл бұрын
The main reason to use a class method is if you need to do something with the class. It would be a great solution in this case actually, because then you can call the initializer using cls and if you change the class name, you won't have to update this method. So yes, good point!
@frustbox2 жыл бұрын
I think in this case a classmethod would make a little more sense. It's strongly coupled to the object, in fact it's kind of a constructor. Some other examples are `datetime.now()`, `datetime.fromtimestamp()` or `datetime.strptime()` They are constructors that take some input to create a datetime object. In the code example here the `create()` method is a constructor (or initializer) that creates a PaymentProcessor object. So in this case, I would use classmethod, yes. IMHO staticmethods are more loosely coupled to the class. Kind of helper functions that are not really tied to the class or the individual object but may be used in conjunction with the class/object. And they are tacked onto the class as staticmethod solely to make imports easier. Otherwise in almost all situations I tend to avoid staticmethods and just use functions on the module/file level to not clutter the class with functions. But of course … that's all a bit convention and personal preference. There's no right or wrong here, I think.
@rdean1502 жыл бұрын
I prefer "code aroma". It really rolls off the tongue more nicely. Because, as we all know, mouthfeel is a crucial aspect of software design patterns.
@BrunoReisVideo2 жыл бұрын
These videos are great. Feels like getting a brand new bottle of nice perfume
@ArjanCodes2 жыл бұрын
Thanks so much Bruno, glad you liked it!
@slavrine2 жыл бұрын
Using wrong data structures vs backpedaling seems contradictory to each other. Should we be wrapping data in a class, and passing the instance around? This will allow us to avoid multiple lists around, but would make other code dependant on the names of methods and attributes of the data class. Thus by using a better data structure we introduce backpedaling. Thank you for great content Arjan!
@robertbrummayer49082 жыл бұрын
Another great video! The only thing I do not like and I guess also Uncle Bob would criticize are some redundant comments, e.g. the comments in the main method "create a customer", "create the order". As I have already pointed out in another comment, this is a code smell called redundant comments. Every programmer can see that you create a customer and order object there, so there is no need for these comments. There is also a doc string "Order status" that simply repeats what the name already tells. But this is just a minor point, great job!
@ArjanCodes2 жыл бұрын
Thanks Robert! You’re right. I was still on the fence here on what to do with code comments in my videos, as the default linter settings I used wanted to see comments everywhere. I’ve since turned that off and went with only adding comments if they contribute to the clarity of the code. I might do a video about comments soon to share my ideas about them.
@robertbrummayer49082 жыл бұрын
@@ArjanCodes Such a video would be great. Thanks Arjan! Best wishes from Austria :)
@Gummibandet12 жыл бұрын
Could you do a video showing what packages you use and recommend, as well as key commands you often use when coding?
@ArjanCodes2 жыл бұрын
Thanks for the suggestion!
@5ihdi2 жыл бұрын
It would be interesting to see how we can implement Factory Design Pattern to create multiple Customer, Order etc in the main() function that manages to add this multiple instances to the POSSystem. And maybe even incorporate different PaymentProcessor classes
@tehdusto Жыл бұрын
As part of my job I'm having to move from python to LabVIEW. All of these practices are still applicable in the data flow paradigm and this content is helping me improve my companies LabVIEW code base. LabVIEW is cursed though
@timjohansson43042 жыл бұрын
Hi Arjan! Great video as always, thanks for that. I would like to see a video describing your process of finding codesmells, this example is a really small code base to easily show and correct what you already found. Tips and tricks for modelling and finding these code smells would be much appreciated :)
@ArjanCodes2 жыл бұрын
Thank you Tim! I do it on some level in the code roast / refactoring videos on this channel, but great topic suggestion to dive more into how to find them, thanks!
@marcosoliveira15382 жыл бұрын
Great content. I would love to see a video about meta-programming, about your favorite decorators.
@1oglop12 жыл бұрын
I like the examples, however, I noticed that most of the videos work with data classes that are easy to change. What about refactoring an app that is using an ORM (Django or SQL Alchemy) - the pain going through the migrations (and data changes) during the refactoring is often well underestimated. I think that it would be nice if you can show the cost of changing the data model like that. Big plus point for saying `initializer` instead of constructor!
@aliemamalinezhad65232 жыл бұрын
Excellent as always
@ArjanCodes2 жыл бұрын
Thank you Ali, glad you liked the video!
@saitaro2 жыл бұрын
Thanks again, mate, your videos really make me write better code!
@xnick_uy2 жыл бұрын
Another excellent video. I think I got the majority of the main points. I'm not very experienced with async calls, and I'm also not too sure that I understand correctly the purpose of the @staticmethod qualifier. But now I have new learning goals!! :-) Please keep making these videos. Besides the content, the narrative and the edition is fantastic.
@XRay7772 жыл бұрын
staticmethod (or classmethod for that matter) allows you to call a method directly on the type as opposed to an instance. Using this to create objects is actually also a design pattern. It usually goes by the name 'factory method'.
@ArjanCodes2 жыл бұрын
Glad it was helpful! I'm going to post a video about async soon!
@funkenjoyer2 жыл бұрын
@@XRay777 Isn't usually used with @classmethod instead of @static? I guess both work just fine but I usually use the class one so that the method is decoupled from object but still tied to the class.
@XRay7772 жыл бұрын
@@funkenjoyer yes, i agree. With instances you would more often see cloning behavior like implementing __deepcopy__ or some custom clone method of you need more control
@jurgen67062 жыл бұрын
I'm not familiar with Python's Protocol classes. But since there is no dependency between the PaymentProcessor protocol and the StripePaymentProcessor is it just assumed that when you pass the StripePaymentProcessor instance that it implements the protocol? Python being Python it probably will only actually throw an error at runtime, but I'm wondering what happens at write time. Does the type checking system check this when referencing a class that does not implement the protocol and will it give a warning if in this case the StripePaymentProcessor does not implement all the methods from the PaymentProcessor?
@ArjanCodes2 жыл бұрын
That’s indeed how it works. Check out my recent protocols vs ABC classes video where I show exactly what happens and at what point you get an error. When you’re writing code and you use a type checker like Pyright, it will point out protocol implementation inconsistencies.
@MichaelFJ19692 жыл бұрын
Thanks for this video. It is really helpful. Please do consider making more such videos.
@ArjanCodes2 жыл бұрын
Will do ;)
@TomWoodland2 жыл бұрын
You create a class variable "id", isn't that overwriting a built in/protected variable? Great video. Learnt a lot.
@XRay7772 жыл бұрын
Yes, it is shadowing it, meaning that you cannot use the built-in id function in the scope of the class.
@ArjanCodes2 жыл бұрын
Indeed. I’m aware of the shadowing, but I never use that function and it’s a really useful variable name 😊. Alternatively you could name it _id, following the naming scheme used in NoSQL databases like MongoDB.
@Andrumen012 жыл бұрын
Just wanted to say that I like your channel very much. I am on a career change move and your tips have helped a lot to make the project I am currently working on be more organized. That being said, I was going to ask you about the implementation of Python events, how do you feel about code implementing events rather than direct calls to functions? Is there any "code smell" for implementing event systems? Best regards and keep up the excellent work.
@finleycooper88442 жыл бұрын
Make sure to add this to your code smell playlist so people can find it easier
@ArjanCodes2 жыл бұрын
Done - thanks for pointing that out!
@allanmuller34862 жыл бұрын
I may be getting ahead of myself, but mightn't it have been better to link the customer to the order using the id and keep the customer data in a dict keyed by id? Plusses include being able to maintain the customer id in one place, the minuses include not being able to having alternate shipping addresses for specific orders.
@XRay7772 жыл бұрын
I have to say I don't really see a benefit to that. The way he did it you can easily get all ids by doing '[c.id for c in customers]' but grouping the customer data nicely from what you are suggesting is much more involved.
@Acuzzio2 жыл бұрын
This video is just excellent. Thanks a lot for providing such a good content!!
@ArjanCodes2 жыл бұрын
You’re most welcome - I’m happy you like the content!
@zacky78622 жыл бұрын
Another great tutorial :) Thank you so much
@ArjanCodes2 жыл бұрын
Glad you liked it, @Zacky!
@user-ev2ks8fl5x2 жыл бұрын
I wonder if not is better to pass the Order dataclass to the payment method? From my point of view, probably at future, you need more information about it and you will need to add more params
@davidlakomski39192 жыл бұрын
Fortunately, my coding skills aren't advanced enough for my code to really stink xD Really love your videos and admire your teaching skills, thanks a lot !!
@ArjanCodes2 жыл бұрын
Don't worry, David, the smell develops all on its own regardless of your skill level ;).
@davidlakomski39192 жыл бұрын
Eager to discover my own putrid perfume mature then 😁
@NanaAtiekuFrans2 жыл бұрын
Your contents are always great. Thanks.
@ArjanCodes2 жыл бұрын
Glad you like it, you’re welcome!
@polyliker80652 жыл бұрын
Hey Arjan, I've recently been in an introductory course as part of a new job where we had to work with a system where stored procedures ruled the game and handled everything from data access to business logic. I asked the instructor why there was business logic in the database when we're already doing business logic in the visual basic app. He kinda got upset and said he didn't hear a good argument why it shouldn't be there, and only said that stored procedures are safer but less portable. I didn't really agree on that but kept my mouth shut since I didn't want to cause a scene. (I can think of a few reasons why stored procedures aren't considered best practices.) Do you have a view on the pro's and con's of stored procedures, in which case they are usefull and when they should be avoided?
@ArjanCodes2 жыл бұрын
I avoid using stored procedures in my projects because I like to have my business logic in a single place. Having it in multiple places leads to more work in the future: if you need to change something, you’ll probably need to change it in multiple places. Also, you now have an extra decision to make: should this new thing be a stored procedure or in the backend code? If you make the wrong choice, it costs time to fix it. Finally, having two places where business logic is stored might limit you in how you setup your software architecture, leading to a potentially less optimal solution.
@andreacazzaniga84882 жыл бұрын
You might be true, but that's not very relevant. (disclaimer: not requested advice) many business implementations are far from ideal, and this is not even a case where the implementation is necessarily bad. Wait until having a stored procedure gives a problem and be the one who knows how to solve the issue. If the stored procedure works and has never given a problem.. Keep it like this, even if it could be better. You will always want to change the cod base and stuff of projects, but.. Focus on fixing stuff that don't work or that you are asked to change. The rest.. Wait until you are more senior and your colleagues know you and trust you.
@polyliker80652 жыл бұрын
@@ArjanCodes Thanks for the reply! Those were indeed some of the reasons it seemed not to be a best practice to me. I didn't think about the limitation in terms of architecture though. Another was having two code bases to maintain and deploy potentially causing synchronisation issues which might introduce errors.
@polyliker80652 жыл бұрын
@@andreacazzaniga8488 Yeah, it was not meant as a correctional comment but more of a question on why we've gotten this as a sample app. I mean it'd be nice to be introduced to stored procedures without the sample app actually using them. So we get more of a message along the lines of 'while we'd rather put our business logic in one place, but you might encounter this. Just don't touch it unless asked'. And don't worry, the focus is always on what is asked. Don't be afraid to ask why something is done a certain way when you see possible improvement though.
@SoChot Жыл бұрын
Great video! In section 6, when you're defining the static method `create()` for the `StripePaymentProcessor` class, is there a reason you didn't use a class method since those are often used as object constructors?
@puddlejumper12 жыл бұрын
Love the code smell videos. Question: How can you reduce boiler plate code? For example you introduce 'LineItem' class but now you have to type it out 3 times in the main file (and potentially alot more if you have more items). Adding to the order.add_line_item function would reduce the code in main file. Thoughts?
@Milamber51862 жыл бұрын
In a typical pos system, all of your items would be in a database. You would not add items into the code, but instead add them to the database. In this video, it was added to the code for demonstration purposes.
@themadichib0d2 жыл бұрын
Doing so saves you some code lines in the short term for this example, but in the long term and/or real world use youd be making more work for yourself. And like the other person said, rarely are you constructing specific objects like this directly in code, and would be in taking from a source(eg database or a client) in which case youd never run into your specific concern in the first place.
@DanielWeikert2 жыл бұрын
Hi found your channel and I really appreciate your videos. So far I always used python without paying much attention to structure and best practises (so 180 degree different to your style). I like to learn how to change that but I am not sure how to start the best way. Is there any order, guide,.. which helps to learn and apply your concepts and strategies the best way? Tahnks
@dirk65313 ай бұрын
Your Order class ist decorated with @dataclass. Requestion: why contains the class functionality? Is it a good Idea to Split into Order class (only Data) and a OrderManager ( contains the business logic to handle Orders)?
@erikdeveloper Жыл бұрын
Man, you're legend!
@ArjanCodes Жыл бұрын
Thank you Erik, glad you liked the video!
@kidsforcode30522 жыл бұрын
Thanks very much. Very well explained practical advice!
@ArjanCodes2 жыл бұрын
Glad you enjoyed it!
@ZEDAWMN2 жыл бұрын
Thanks Arjan very helpful video. Can you make a video for the vscode extensions you are using for Python development ? I see you are using vscodevim and it will be interesting to see the rest. Thanks again
@ArjanCodes2 жыл бұрын
Good idea, thanks for the suggestion!
@peterkuchar2192 жыл бұрын
I'm not sure customer should go as an input to Order. Shouldnt be other way around?
@pypro2 жыл бұрын
Amazing video, great bro!! =) many thanks
@ArjanCodes2 жыл бұрын
Glad you liked it!
@felipealvarez19822 жыл бұрын
I love your smelly and stinky videos Arjan! Thank you, now I'm going to go take a shower.
@kingremonoire2392 жыл бұрын
Hi Arjan. Love your content. please keep it up :)
@ArjanCodes2 жыл бұрын
Thanks, will do!
@andymachine65452 жыл бұрын
What's the code smell related to the thumbnail? Cause thats what my code typically looks like :D
@Evkayne2 жыл бұрын
I love those 10 seconds haha!
@ArjanCodes2 жыл бұрын
Haha, good to hear :)
@alexandersnow58672 жыл бұрын
Hey Arjan, Great video. I’ve been learning a lot watching this series. I was curious about your choice to make the create method for the StripPaymentProcessor a static method and not a class method? That would resolve the annotations. I’ve found myself to be a bit unclear on the benefits of either. I would assume a classmethod might be more handy if we wanted to make additional processors that inherit from StripPayment?
@akivazonenfeld72852 жыл бұрын
You can't do it with a class method since a class method is called on an instance of the class. And since this 'create' method supposes to be used to create the instance, it doesn't make sense to make it a class method. And I'm pretty sure It won't solve the typing problem.
@alexandersnow58672 жыл бұрын
@@akivazonenfeld7285 a class method is called on the class itself and usually returns an instance of the class, which seems to be what we’re doing here. It may not resolve the typing issue if we still say that the return is the StripePaymentProcessor though
@XRay7772 жыл бұрын
I agree with you, Alexander. If you are implementeing the factory method pattern the default choice should be classmethod precisely for the reason you mentioned: it gets a reference to the type it is attached to as the first argument (usually denoted cls). If you derive from a class with a classmethod then the derived class will be passed as the cls argument if you call it on the derived class. Thid is the defining distinction between classmethod and staticmethod. A staticmethod does not get a reference to the instance / type it is attached to. It is mainly used to indicate that the method is logically connected to the class but not tightly coupled.
@DS-tj2tu2 жыл бұрын
Awesome! Thank you!
@ArjanCodes2 жыл бұрын
You’re welcome!
@Kahitar12 жыл бұрын
Why don't you ever use multiple cursors? For example you could have selected all "add_line_item"s and changed them all at once to pass LineItem. Just curious if you don't know about multiple cursors or have another reason to never use them :) Also just want to say that I love your content. I learn a lot from you in every video and it already improved my python code A TON! Thank you :) ALSO: I noticed you are using pyenv. I never used that, I always used venv or pipenv. As a suggestion for a video: I would love a pyenv Tutorial from you. Of course you don't have to do it just for me, I can just watch other tutorials. Just if you think it fits to the content of your channel ^^
@ArjanCodes2 жыл бұрын
The main reason I avoid them in my videos is that I'm concerned it would make the explanations less clear since text is changing in multiple places at the same time. I do use name refactoring a lot (F2 in VSCode). Glad to hear the videos are helpful to you. Regarding pyenv, good suggestion, thanks!
@potlurikrishnapriyatham Жыл бұрын
any tool/ide extension to detect codesmells?
@ChrisBNisbet2 жыл бұрын
Given the number of times you use the word 'interface' when describing protocol classes, I wonder if a better name for Protocol would have been Interface.
@ArjanCodes2 жыл бұрын
I would have liked a more strict interface-like programming concept in Python, like Java or Typescript has. But protocols are still quite nice and tie in well with Python’s typing system.
@alessandroferrari21662 жыл бұрын
what a gem of a video! Jam-packed with value, thank you Arjan! I was wondering: wouldn´t be better to have that staticmethod be a classmethod instead, since it returns a new instance. I'm a bit confused on the use of @classmethod in Python so my suggestion might be totally bs :D On another note, videos suggestions for the future: enterprise architecture patterns in Python, microservices in Python, DDD in Python. Again, thank you for your inspiring work!
@ArjanCodes2 жыл бұрын
Hi Alessandro, thank you, glad you liked it! Yes indeed, this would be a great use case for a class method!
@mypegionworld76122 жыл бұрын
You are the only person that makes me insecure about my code..
@ArjanCodes2 жыл бұрын
No need! We’re all here to learn (including myself).
@amir35152 жыл бұрын
Come on, it's only smellz 😉
@theguy28872 жыл бұрын
I love these videos!!!!
@ArjanCodes2 жыл бұрын
Thanks, glad you like them!
@originalvbgunz2 жыл бұрын
These videos are cool but smaller/quicker videos *focusing* on single subjects may be a better idea. Think seven videos each focused on a single subject, best practice, idea, skill Vs 1 video of seven subjects in which it is easy to get lost, confused, bored, stuck and forget altogether. Your videos are great and better than nothing (thank you for them) but focused videos might be a better idea
@ArjanCodes2 жыл бұрын
I agree to a certain point - I'm actually working on focusing my videos more at the moment. It's a balance though between focusing on a single thing but still allowing for enough depth. Sometimes, too much focus can lead to content with too little informational value. And I'd like to avoid that :).
@guilhermearantes46272 жыл бұрын
Where can I learn these topics in depth?
@ArjanCodes2 жыл бұрын
I'm going to launch an in-depth course on software design before Christmas!
@adjbutler2 жыл бұрын
thank you for this video
@ArjanCodes2 жыл бұрын
You’re welcome!
@alfonsov31902 жыл бұрын
Thanks for the video! Especially for clarifying the problem with self-reference typing. Does the __future__ import also solve problems when there is a cyclic type reference between two or more classes?
@XRay7772 жыл бұрын
Yes, it does and it also helps with cyclical imports. You can combine this with the TYPE_CHECKING flag from the typing modulec if you still want static type checking e.g. with mypy but want to avoid cyclical imports. In essence, you can then dump all the cyclical imports in a `if TYPE_CHECKING` block.
@alfonsov31902 жыл бұрын
@@XRay777 Thanks a lot!
@getpoked1012 жыл бұрын
I know you are using the vim extension but you still use your most quite a bit to navigate. Is that just for demonstration or do you have a method to the madness ?
@ArjanCodes2 жыл бұрын
That’s mostly me having to unlearn 30 years of text editing with a mouse. I’m slowly adopting more Vim-like practices though, so I’ll hopefully get better at it soon.
@getpoked1012 жыл бұрын
@@ArjanCodes I'm at about 15 years of it. It's odd I learned on emacs, then as I become a professional I used a bunch of mouse driven IDE's and now I'm in the same boat as you. I find my biggest issue with the vim extension is when it plays poorly with other extensions.
@stefanobailey7402 жыл бұрын
Can someone explain to me why you wouldn't use a Dataclass over a regular class? I understand that you can't use the dunder method new, but with slots being added to 3.10 that can't be a factor. If anyone could clear this up, I would really appreciate it
@ArjanCodes2 жыл бұрын
Sometimes your class is not at all data-oriented, and has mostly methods and not many instance variables. In that case you might als want to have more control over the initializer instead of what a dataclass provides by default. For example, a ExportFactory might not have any instance variables, but simply have as a task to create a variety of Exporters. In that case, turning it into a dataclass doesn’t add any value.
@stefanobailey7402 жыл бұрын
@@ArjanCodes thank you so much for your response. I really appreciate ypu taking the time to clear it up for me
@pacersgo2 жыл бұрын
I still don’t get at 23:03, why the “create” function is used instead of directly put the contents to __init__?
@kristik4322 жыл бұрын
It's better to keep init clean kzbin.info/www/bejne/Z4SrmmShp859f5Y
@pacersgo2 жыл бұрын
@@kristik432 it makes sense. Thank you for the link!
@aadithyavarma2 жыл бұрын
Great video! One question: class StripePaymentProcessor: def __init__(self): self.connected = False How do you change this into a dataclass? Should you use field(init=False, default=False) or use __post_init__() or both?
@ArjanCodes2 жыл бұрын
Thanks! You can change it into a dataclasses really easily: @dataclass class StripePaymentProcessor: connected: bool = False
@aadithyavarma2 жыл бұрын
@@ArjanCodes Isn't the above dataclass equivalent to the below: class StripePaymentProcessor: def __init__(self, connected=False): self.connected = connected Since we do not want to initialize the value by passing it as an argument while creating the object, it should be avoided. 1. @dataclass class StripePaymentProcessor: connected: bool = field(init=False, default=False) OR 2. @dataclass class StripePaymentProcessor: connected: bool = field(init=False) def __post_init__(self): self.connected = False Which one do you think is better 1 or 2? Or is there a better approach?
@luukvdv52382 жыл бұрын
What is your opinion about explicitly setting states from outside? I expected e.g. a pay() method that sets the state to paid instead of setting the state to paid explicitly.
@XRay7772 жыл бұрын
Seems like something you would find in Java or C++. In python you can escalate access to attributes of you need to. If you only change the value of an attribute, leave it as an attribute. If at some point you need to restrict access or do some other stuff, like verification, just turn the attribute to a property with a setter. The interface for the user remains unchanged. You cannot do this in Java or C++, which is why programmers in those languages are so pedantic about getters and setters, since it is really hard to change an existing interface without breaking stuff.
@luukvdv52382 жыл бұрын
It feels like leaking information of the implementation. From the outside you need to know the enum of those states.. also the state is already marked private using the _. So it's private and then set using a set method.
@XRay7772 жыл бұрын
@@luukvdv5238 Fair points. Regarding the first, what I usually do is put all enums that are used throughout the project / package together in a file like common.py, which makes them easily accesable from everywhere. You can also expose them in the __init__.py of your package. I would not consider enums as implementation details, rather they are discretized options that can be used with the framework. To your second point, I missed the '_', but that only marks it protected. If you want to make it private you would need two '__' and then you can still have a read-only property with just 'status'. I don't really see the benefit in having a 'pay()' method that anyone can call over a property setter that restricts the status value which you can set. The latter gives you a simpler interface for the class.
@ArjanCodes2 жыл бұрын
In general it's not a bad idea to separate implementation details like the order state from the users of the order. I can definitely imagine a pay() method as you suggest, or a set_to_paid() method. It becomes an issue though once there are many different values for the enum (cancelled, returned, refunded, payment_failed, etc.). In that case, adding a bunch of different setter methods for each of them leads to a cluttered Order class and it's better to expose the enum instead.
@Manas-co8wl Жыл бұрын
Lol people complaining about the word "code smell" as if he invented it when it was a programming jargon since the stone ages (when code really did smell btw..)
@rrwoodyt2 жыл бұрын
I still miss the whteboard!
@gustavorangel7292 жыл бұрын
On 16:00, is there a particular reason to implement a property instead of a method like get_total_price(self)?
@funkenjoyer2 жыл бұрын
it's pretty much a personal preference, they would behave pretty much the same, one thing tho that i've run into is that you can't rly create an abstract property so if you had a hierarchy of classes that all have get_total_price and you had an abstract base where it's defined as abstract method you couldn't rly swap it for property
@XRay7772 жыл бұрын
It is considered more pythonic. You can think of the total price as just a value that is automatically updated. Therefore it makes sense to access it just like any other attribute, hence the property. It allows you to skip the empty parentheses when calling it as opposed to a method.
@ArjanCodes2 жыл бұрын
Exactly what @X Ray says!
@XRay7772 жыл бұрын
@@uqams I disagree somewhat with that statement. The whole point of properties (or the whole descriptor protocol for that matter) is the flexibility to change access without changing the interface. If you would never use properties if computation is involved the whole concept would be moot. On the other hand, when the computation has side effects, as in changing something about the state of the class other than the attribute you are setting, or if the computation can be costly, then you should definitely go for a method instead.
@kuishikama3482 жыл бұрын
@@XRay777 So it works all very much the same, but you would use properties when you don't change the state of the object, basically when "not much" is happening and you basically just want to return a saved value or derive something directly from the saved values (like the totalprice = quantity * price)? You would use a method, indicated with the () if you want to describe that something is changing, like a create(), run(), start(), close() and so on? I think this is a TIL moment for me. Thanks for that. I just wonder what happens if you want to determine the totalprice, but it involves a costly function, something like accessing a web-resource, lots of calculations, things like that? Do you still use a totalprice property or do you use a method get_totalprice() to indicate to someone reading the code that this is costly? I just imagine someone extending or maintaining the code later on, not realizing the costs of these simple looking properties and then wondering why it is so slow. Profiling and debugging until realising that obj.totalprice is actually generating requests, starting a long calculation and so on. Would you use properties or methods for that?
@TomWoodland2 жыл бұрын
Code smells!!!
@ArjanCodes2 жыл бұрын
You bet! ;)
@williamwatkins66692 жыл бұрын
regarding the last code smell. I actually learnt from mcodes (kzbin.info/www/bejne/iGmQoHSneMx7l8k) that you can force the user of a library to use keywords by using the * in the arguments. Can be handy
@ChazAllenUK2 жыл бұрын
"So here's a warning..." ROFL
@abdulahhi2 жыл бұрын
goats milk?
@PeriOfTheGee2 жыл бұрын
You used named arguments for all 3 `LineItem`s, but shouldn't doing it just for 1 be enough to let the developer know which argument means what? Of course, as a devils advocate, I can say that they could all possibly be in a different order than in the ctor, but no sane person would do that while still indicating only one of them with named arguments.
@ArjanCodes2 жыл бұрын
It might be enough but it’s also hard to do this consistently because any argument following a named argument also has to be named. So you can only do this if you want to clarify it for the last few arguments, in which case you can keep the first ones unnamed. Overall, I tend to use unnamed arguments for simpler functions with one or two arguments, and named arguments for anything else, or when it’s a function with arguments of the same type.
@aclassypotato81552 жыл бұрын
hi arjan
@ArjanCodes2 жыл бұрын
Hi classy potato
@grimonce2 жыл бұрын
Great explanations and implementation, I however don't like the tabnine as a sponsor :/ I've heard some worrying things about tabnine and tried it myself, quite bloated. Tabnine is not open about its methods and there really is no reason to trust it. It is advertised however and people will start asking you to use it in your professional environment - bad influence on our community...
@ArjanCodes2 жыл бұрын
Thanks! It's been a while since I did this video and I thought Tabnine was a nice tool at the time I recorded this, but perhaps things have changed since then. I don't think Tabnine is less open about their methods than other companies though, or am I missing something?