5 Tips for Writing Clean Python Code

แชร์
ฝัง
  • เผยแพร่เมื่อ 2 ก.ค. 2024
  • 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
    @ArjanCodes  15 วันที่ผ่านมา +1

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

  • @zion4d
    @zion4d 15 วันที่ผ่านมา +4

    Raise errors is great! But what about handling?

  • @royw2
    @royw2 18 วันที่ผ่านมา +7

    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…

  • @FernandoCordeiroDr
    @FernandoCordeiroDr 18 วันที่ผ่านมา +10

    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  17 วันที่ผ่านมา +10

      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.

  • @markoobradovic9242
    @markoobradovic9242 10 วันที่ผ่านมา +1

    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  8 วันที่ผ่านมา

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

  • @StavrosSachtouris
    @StavrosSachtouris 14 วันที่ผ่านมา +2

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

  • @marnz550
    @marnz550 18 วันที่ผ่านมา +15

    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  18 วันที่ผ่านมา +13

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

    • @fixmymechhangercouk
      @fixmymechhangercouk 18 วันที่ผ่านมา +3

      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!

  • @malteplath
    @malteplath 18 วันที่ผ่านมา +2

    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  12 วันที่ผ่านมา +1

      Glad you enjoyed it!

  • @Whatthetrash
    @Whatthetrash 15 วันที่ผ่านมา +1

    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
    @JonitoFischer 9 วันที่ผ่านมา

    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  8 วันที่ผ่านมา

      Glad to hear that Jonito!

  • @Melindrea
    @Melindrea 17 วันที่ผ่านมา +1

    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 =)

  • @marcotroster8247
    @marcotroster8247 18 วันที่ผ่านมา +1

    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
    @ZachAttack8258 17 วันที่ผ่านมา

    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  12 วันที่ผ่านมา

      Glad it was helpful!

  • @loic1665
    @loic1665 18 วันที่ผ่านมา

    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  12 วันที่ผ่านมา

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

  • @abhisheksanjaygawade1479
    @abhisheksanjaygawade1479 16 วันที่ผ่านมา

    Thanks for video

  • @ilbene7922
    @ilbene7922 16 วันที่ผ่านมา

    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

  • @metal571
    @metal571 17 วันที่ผ่านมา

    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.

  • @MoreCharactersThanNeeded
    @MoreCharactersThanNeeded 16 วันที่ผ่านมา +1

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

  • @timelschner8451
    @timelschner8451 18 วันที่ผ่านมา +3

    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 18 วันที่ผ่านมา +3

      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 18 วันที่ผ่านมา +3

      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  18 วันที่ผ่านมา +8

      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 17 วันที่ผ่านมา +1

      @@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  17 วันที่ผ่านมา +3

      @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
    @christopherpetersen342 18 วันที่ผ่านมา

    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 17 วันที่ผ่านมา

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

  • @tbpotn
    @tbpotn 18 วันที่ผ่านมา +1

    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.

  • @DerekHohls
    @DerekHohls 17 วันที่ผ่านมา

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

    • @ArjanCodes
      @ArjanCodes  17 วันที่ผ่านมา

      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 16 วันที่ผ่านมา

      @@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
    @mmilerngruppe 17 วันที่ผ่านมา

    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.

  • @danielschmider5069
    @danielschmider5069 14 วันที่ผ่านมา

    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  14 วันที่ผ่านมา

      "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.

  • @detemegandy
    @detemegandy 10 วันที่ผ่านมา

    Do you use Rye?

  • @grzegorzryznar5101
    @grzegorzryznar5101 18 วันที่ผ่านมา

    I am still waiting for game making series :)

  • @MCeplekake
    @MCeplekake 18 วันที่ผ่านมา +3

    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

  • @spaceidiot200
    @spaceidiot200 17 วันที่ผ่านมา

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

  • @Jakub1989YTb
    @Jakub1989YTb 7 วันที่ผ่านมา

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