5 Tips for Writing Clean Python Code

In this video, I'll share 5 key things you should do to avoid writing crappy code. These tips, drawn from my own experience, will help you write clean code.
🔥 GitHub Repository: git.arjan.codes/2024/clean_code
👷 Join the FREE Code Diagnosis Workshop to help you review code more effectively using my 3-Factor Diagnosis Framework: www.arjancodes.com/diagnosis.
📨 The Friday Loop by ArjanCodes Newsletter: thefridayloop.com
💻 ArjanCodes Blog: www.arjancodes.com/blog
✍🏻 Take a quiz on this topic: www.learntail.com/quiz/ikcbog
🎓 Courses:
The Software Designer Mindset: www.arjancodes.com/courses/tsdm
The Software Architect Mindset: www.arjancodes.com/courses/tsam
Next Level Python: Become a Python Expert: www.arjancodes.com/courses/nlp
The 30-Day Design Challenge: www.arjancodes.com/courses/30ddc
👍 If you enjoyed this content, give this video a like. If you want to watch more of my upcoming videos, consider subscribing to my channel!
Social channels:
💬 Discord: discord.arjan.codes
🐦 X: x.com/arjancodes
🌍 LinkedIn: / arjancodes
🕵 Facebook: / arjancodes
📱 Instagram: / arjancodes
♪ Tiktok: / arjancodes
👀 Code reviewers:
- Yoriz
- Ryan Laursen
- Dale Hagglund
- Kit Hygh
- Alexander Milden
- Bean
🎥 Video edited by Mark Bacskai: / bacskaimark
🛒 GEAR & RECOMMENDED BOOKS: kit.co/arjancodes
🔖 Chapters:
0:00 Intro
0:30 Example
3:57 #1 Meaningful Names
6:48 #2 Comment Wisely
8:38 #3 Functions/Modules Should Be Responsible For One Thing
13:49 #4 Error Handling as Logic
15:54 BONUS: Formatting
16:29 #5 Become a domain expert without becoming a domain expert
25:02 Final thoughts
#arjancodes #softwaredesign #python
DISCLAIMER - The links in this description might be affiliate links. If you purchase a product or service through one of those links, I may receive a small commission. There is no additional charge to you. Thanks for supporting my channel so I can continue to provide you with free content each week!

Пікірлер: 47

  • @ArjanCodes
    @ArjanCodes20 күн бұрын

    Join my free Code Diagnosis workshop that teaches you a 3-factor framework using Python examples from production code ➡ arjan.codes/diagnosis

  • @FernandoCordeiroDr
    @FernandoCordeiroDr22 күн бұрын

    I get that you are trying a more functional approach, but that invoice is beeeeeeegging to become an object. When you keep passing the same arguments to a lot of functions, this is a sign there's an object structure hidden in your code. You create a factory classmethod "create_from_stripe", a "send" method, a "book" method, and badabim-badabum, you're golden. That's actually the remaining tip Uncle Bob gives about clean code: keep the number function arguments to a minimum. The strategies he suggests are to rely more on data structures and on objects, which is, in my view, pretty much the same strategy.

  • @ArjanCodes

    @ArjanCodes

    22 күн бұрын

    Well spotted! I’m currently working on an SDK for the accounting system that works exactly as you suggest, with classes for the main API objects. My idea is to use Pydantic so I can also add validation and have easy handling of JSON. When I have a first version ready, I’ll do another video about that.

  • @royw2
    @royw222 күн бұрын

    When refactoring, I like a safety net. Before refactoring, run unit tests with coverage to verify the area I’m refactoring has unit tests, adding any that are missing. Then the process is test, refactor, test. Just want to know I’m not adding any errors…

  • @StavrosSachtouris
    @StavrosSachtouris19 күн бұрын

    Here is a man who appreciated the value of functional programming through experience.

  • @zion4d
    @zion4d20 күн бұрын

    Raise errors is great! But what about handling?

  • @marnz550
    @marnz55022 күн бұрын

    Good stuff, thanks Arjan. I have a feeling you only scratched the surface on error handling. In the example you gave, the code became neater but much more vulnerable. Now if one of your functions raises an exception, the whole code breaks. Would you plz explain the full cycle of your error handling logic?

  • @ArjanCodes

    @ArjanCodes

    22 күн бұрын

    Good suggestion for a follow-up video, thank you!

  • @fixmymechhangercouk

    @fixmymechhangercouk

    22 күн бұрын

    Yes I agree! I have loads of code that handles cases where a function that returns None, but it's in a long running automation script, that needs to continue and not fail - would be really helpful to see how to handle the exceptions works as per your suggestion and how this differs to retuning None, especially when it's a few layers deep! Thank you @arjancodes!

  • @markoobradovic9242
    @markoobradovic924214 күн бұрын

    Arjan, you are soo good at what you‘re doing. Your voice is calm and relaxed. And you are able to transport your knowledge to your audience in the same manner, calm and relaxed. Learning new stuff suddenly becomes like a therapy. No more stress, no more struggle. Thank you very much. Please keep going.

  • @ArjanCodes

    @ArjanCodes

    12 күн бұрын

    That is so kind! I’m happy that you find the content helpful.

  • @malteplath
    @malteplath22 күн бұрын

    This is one of your best videos. You use your own production code, you explain your thought process clearly, and also hint at further improvements. This could be expanded into a whole course - especially the last tip.

  • @ArjanCodes

    @ArjanCodes

    17 күн бұрын

    Glad you enjoyed it!

  • @Melindrea
    @Melindrea22 күн бұрын

    You accidentally divided the application fee by 100 twice. Both in the InvoiceData (which is where it was originally) and in the get_application_fee function. I did like the changes you did in general. It makes a lot of sense =)

  • @Whatthetrash
    @Whatthetrash20 күн бұрын

    Something that's never discussed in videos like this (although this is a good video, not throwing shade at all, Arjan) is the overhead of learning all these new APIs and until you really grok what they're doing, what problems they're solving and how they work -- there really is a wall of ignorance that's hard to overcome. After all, you don't know what you dont know. All I know is , "Use this to solve your problem" but beyond that -- it really does seem like an endless (turtles all the way down) problem of "How much of this new thing do I have to learn to solve my problem?" Is this basic, fundamental knowledge thst. I should know, or concrete implementation minutia that doesnt matter beyond this API. All of that is where I find myself way more often than not knowing how to use clear variable names and short functions. >_ Edit: Hey, you just mentioned it! Becoming a domain expert without becoming a domain expert. That's the rub right there.

  • @JonitoFischer
    @JonitoFischer14 күн бұрын

    Thank you Arjan for the videos you upload, they're very helpful and have a great quality, both in teaching and technical quality, I have learned a lot from you.

  • @ArjanCodes

    @ArjanCodes

    12 күн бұрын

    Glad to hear that Jonito!

  • @marcotroster8247
    @marcotroster824722 күн бұрын

    Much better now, but it's still far from ideal. The last point about domain knowledge is crucial because otherwise you can hardly figure out the right data structures and function signatures. It's all about using expressive language and increasing information content while keeping the coupling low. I'd probably remove most of your comments and express them by function names. But that's just my personal taste. Also a huge issue with the code is what happens when a transaction completes partially. Maybe you wanna roll back the payment entirely when it's not persisted in your accounting system, etc. You should make this more explicit. But in any case, it's also important to not overengineer. When an occasional manual rollback is cheaper than programming bulletproof error handling, then keep the code as is. After all, the code is supposed to save money by automating a manual process.

  • @ZachAttack8258
    @ZachAttack825821 күн бұрын

    Been watching for a while and this is the best video yet. I’m going to link to it from our coding standards document, as it provides good examples.

  • @ArjanCodes

    @ArjanCodes

    17 күн бұрын

    Glad it was helpful!

  • @loic1665
    @loic166522 күн бұрын

    Very nice video, thanks! It reminds me of older videos like the ones about dependency I jextions or design patterns:) Also very nice to talk about domain knowledge. From my experience it is that who makes the difference at some point, even if you're technically good. It's only by knowing what you're working on and your clients' needs that you'll be able to make good decisions

  • @ArjanCodes

    @ArjanCodes

    17 күн бұрын

    I'm happy to hear you liked it! :)

  • @abhisheksanjaygawade1479
    @abhisheksanjaygawade147921 күн бұрын

    Thanks for video

  • @metal571
    @metal57121 күн бұрын

    By the way, VSCode's Python extension now allows you to "extract function" after selecting a block of code, although it doesn't seem to add type hints along with it.

  • @ilbene7922
    @ilbene792221 күн бұрын

    Very interesting, I would like to see a video about how to read code and analyze it in order to catch all these mistakes. In this video you show the problem and tthe solution but now how do you catch the problem

  • @MoreCharactersThanNeeded
    @MoreCharactersThanNeeded21 күн бұрын

    What about error handling? As in how you deal with them in after you have raised them?

  • @timelschner8451
    @timelschner845123 күн бұрын

    as always, thanks alot Arjan! I am still wondering how you would handle errors in each function. When there is a need of chaining a long list of task you have to do each method must raise some kinde of custom processing exception which should be handled in the main, or what is your approach? I´ve looked at taskflow and pypeln which should offer some kind of task processing framework. Maybe that would be nice for a next video to compare some workflow libs. What are you using?

  • @maleldil1

    @maleldil1

    23 күн бұрын

    You raise exceptions when errors happen and handle them when you can actually do something useful with them. For example, sometimes the only thing you can do is print an error message to the user asking them to try again or something, so you let the exception bubble up all the way to the UI layer and handle it there. Or maybe you want to log the exception somewhere in between so you catch it, log it, and raise it again. You don't need to create your own custom exception types for everything, but they're useful when you have to do different things depending on the error, and it's much cleaner when you can write multiple except clauses that catch different exception types.

  • @Arunnn241

    @Arunnn241

    23 күн бұрын

    The comment above is pretty accurate. I'd also add that exception handling for most things is typically neater if done as closest to top level as possible. 15:11 Here, he raises value errors in his unit function getApplicatiomFee(). You could handle this in the direct calling function constructInvoiceDataFromStripe() or that function's calling function, main(). Since main() is as top level it can get, has pretty simplified code, and is where all the main logic starts/branches out, that's where I'd put the handling.

  • @ArjanCodes

    @ArjanCodes

    23 күн бұрын

    I follow a ‘let it burn’ approach. Especially with these types of integrations, it’s often hard to predict the kinds of errors you’ll get, and on top of that you can’t do much about it at the moment you get the error. So what we do is let it crash and log the error. This integration has been running for almost 2 years now and I’ve been able to gradually increase robustness of the code to the point where it now rarely crashes.

  • @DerekHohls

    @DerekHohls

    22 күн бұрын

    @@ArjanCodes "So what we do is let it crash and log the error." I cannot understand how this can work for a production application. The worst case scenario should be to tell the user that "There was an unknown error and we cannot do what you wanted - but we will fix as soon as possible." Ensure the error trace goes to a log, that your logs are monitored and then you can dig into the underlying cause & patch as soon as possible.

  • @ArjanCodes

    @ArjanCodes

    22 күн бұрын

    @Derekhohls - there is no direct customer interaction in this automation since this purely a backend business operation to map a sale to a booking in our accounting system. Therefore, we employ the most cost-effective mechanism of handling errors, which is simply crashing and reporting the error instead of spending a lot of time writing code to prevent all possible errors. It may sound counterintuitive but handling occasional errors manually is the cheapest option for us. If we notice an error occurs more often than we like, or we think there’s a really simple fix, we’ll implement that.

  • @christopherpetersen342
    @christopherpetersen34222 күн бұрын

    speaking of reducing cognitive load, how do you feel about prefixing names like d_ for class data members (not so pretty in the presence of python dataclasses of course - more a relic of languages with explicit getters/setters ;-), g_ for the dreaded globals, l_ for local variables, p_ for passed parameters, etc.?

  • @aflous

    @aflous

    21 күн бұрын

    Please don't do this. Let your IDE help you, or your colleagues will definitely curse you

  • @tbpotn
    @tbpotn22 күн бұрын

    I feel like most of the comments are useless. Stuff like #retrieve the customer from stripe and # determine the application fee. Or # retrieve payment intents. None of these add to the code that's below it. Also, i think compute_timestamp immediately violates naming descriptively. compute_cutoff_timestamp would be better imo. Those are the two things that i noticed most.

  • @grzegorzryznar5101
    @grzegorzryznar510123 күн бұрын

    I am still waiting for game making series :)

  • @danielschmider5069
    @danielschmider506919 күн бұрын

    Why is there no try - except block to actually handle the errors? If your "error handling" just crashes the program, then it's not error handling, thats just a quit() if there's a problem...

  • @ArjanCodes

    @ArjanCodes

    19 күн бұрын

    "Do. Or do not. There is no try." 😉 There are other ways to deal with errors. I'm working a follow-up video to share what I typically do.

  • @DerekHohls
    @DerekHohls22 күн бұрын

    Is there a reason you don't have doc strings for your functions (in some cases they seem to be comments...)?

  • @ArjanCodes

    @ArjanCodes

    22 күн бұрын

    I don’t use docstrings all that much. I prefer to spend some extra time making sure function names and code structure is self-explanatory. The main way I use comments is to clarify the flow of code where that’s not immediately obvious. I also use it to formulate what I need to do while writing the code, and then often leave the comments in so it’s easier for me to understand later why I setup things in a certain way.

  • @DerekHohls

    @DerekHohls

    21 күн бұрын

    @@ArjanCodes Docstrings can be useful for the functions that are used in multiple places by your code (or if if there is code that is going to be used by external apps). That way the IDE can quickly provide info on their use and purpose. For deeply buried code; or code only cross-referenced inside a module, good inline comments are probably more useful.

  • @mmilerngruppe
    @mmilerngruppe21 күн бұрын

    15:40 but you make no exception logic, you simple ignore your new exceptions. 23:40 but your function does now not do what it names stands for.

  • @detemegandy
    @detemegandy15 күн бұрын

    Do you use Rye?

  • @spaceidiot200
    @spaceidiot20022 күн бұрын

    yeah.. I def have too many unnecessary return Nones in my code

  • @MCeplekake
    @MCeplekake22 күн бұрын

    What’s your take on uncle Bobs’s opinion that comments should be avoided at all costs? You got some more or less redundant comments there, and others that could easily be replaced for example by assigning an extra variable with a meaningful name

  • @Jakub1989YTb
    @Jakub1989YTb12 күн бұрын

    use meaningfull names... continues to use "pi" ad a name.