Write Better Code

Awesome
22 Aug 202408:01

Summary

TLDRThis video script humorously addresses the inevitable 'suckiness' of code while advocating for best practices to ease maintenance. It emphasizes the importance of clear comments, meaningful naming, and simplicity in code structure. The video draws from 'Clean Code' by Uncle Bob, offering insights on error handling, avoiding over-engineering, and the significance of testing. It suggests that by adhering to these principles, developers can maintain cleaner, more understandable codebases.

Takeaways

  • 😅 Code quality is often measured by the 'WTF per minute' ratio, humorously highlighting the inherent challenges in software development.
  • 📚 The book 'Clean Code - A Handbook of Agile Software Craftsmanship' by Uncle Bob is a popular resource for improving code quality.
  • 🤔 Comments in code can be a sign of bad code and should be used sparingly; good code should be self-explanatory with clear variable and method names.
  • 🔍 Proper naming of variables, functions, and classes is crucial for code clarity and maintainability.
  • 🚫 Avoid using misleading or unclear names in code; names should be distinct, meaningful, and easy to pronounce.
  • 🔑 Keeping functions small and focused on a single task helps to manage complexity and makes the code easier to maintain.
  • 🛠️ Continuously improving code quality by making small refinements, such as renaming variables or simplifying logic, is essential to prevent code decay.
  • 🛑 Effective error handling is vital for dealing with unexpected scenarios and should be done in a way that keeps the code clean and maintainable.
  • 💡 Simplicity is key in software development; avoid over-engineering and ensure that the functionality implemented is necessary and useful.
  • 📝 Writing tests is an essential part of the development process, ensuring that the code is clean, maintainable, and reliable.
  • 🔄 The importance of teamwork in testing, especially for considering edge cases and avoiding a narrow focus on 'happy path' scenarios.

Q & A

  • What is the 'WTF per minute' ratio mentioned in the script, and what does it imply about code quality?

    -The 'WTF per minute' ratio is a humorous way to describe the frequency of surprising or confusing elements found in code. It implies that code quality can be subjective and that even with best efforts, code may still be seen as 'terrible' by others, but following good practices can make maintenance easier.

  • Why should comments not be used to compensate for bad code according to the script?

    -Comments should not make up for bad code because they can lead to code smells, indicating poor code design. Good code should be self-explanatory with well-named variables and methods, reducing the need for excessive comments and the associated maintenance burden.

  • What is the importance of good naming conventions in programming as discussed in the script?

    -Good naming conventions are crucial as they make code more understandable and maintainable. Clear names indicate the purpose of variables, functions, and classes, reducing the need for comments and making the codebase easier to navigate and discuss.

  • How does the script suggest maintaining code quality over time?

    -The script suggests following the Boy Scouts' principle of 'Leave the campground cleaner than you found it.' This means making small improvements each time code is checked in, such as renaming variables for clarity, splitting large functions, or removing redundant code, to prevent code decay.

  • What is the significance of keeping functions small and focused in the script's discussion on code quality?

    -Keeping functions small and focused is important for reducing complexity and making code easier to understand and maintain. Small functions are easier to test and modify, which contributes to the overall quality and longevity of the codebase.

  • How does the script address the topic of error handling in clean code practices?

    -The script emphasizes using exceptions instead of return codes to separate error handling from business logic. It also suggests writing try-catch-finally statements first to consider potential problems upfront and avoiding null values to prevent errors related to null checks.

  • What does the script suggest about the relationship between simplicity and code maintainability?

    -The script suggests that simplicity is key to maintainable code. It references Elon Musk's five-step engineering process, which includes simplifying and optimizing, and removing unnecessary parts of the process or code to achieve better maintainability.

  • How does the script define 'over-engineering' and why should it be avoided in software development?

    -Over-engineering is the act of creating overly complex solutions for problems that could be solved with simpler methods. It should be avoided because it can lead to unnecessary complexity, making the code harder to understand, maintain, and modify.

  • What is the single responsibility principle mentioned in the script, and why is it important?

    -The single responsibility principle states that a class or function should have only one reason to change. It is important because it helps prevent unnecessary complexity by ensuring that components of the codebase have a single, well-defined purpose.

  • What are some best practices for writing tests as discussed in the script?

    -The script suggests writing simple, clear tests that are easy to read and understand. It also advises finding a balance for test coverage to avoid over-testing and ensuring that edge cases are thoroughly considered to prevent focusing only on the 'happy path' scenarios.

Outlines

00:00

📚 The Essence of Clean Code

This paragraph emphasizes the importance of adhering to basic guidelines in software development to ensure maintainable code, despite the inherent 'suckiness' of code. It introduces 'Clean Code - A Handbook of Agile Software Craftsmanship' by Uncle Bob as a valuable resource. The author humorously acknowledges the 'Agile' red flag but proceeds to discuss key principles such as the futility of comments in bad code, the significance of good naming conventions for variables, functions, and classes, and the necessity of keeping code simple and understandable without over-commenting. The paragraph also touches on the importance of maintaining code quality over time, referencing the Boy Scouts' principle of leaving the codebase cleaner than found.

05:02

🛠️ Best Practices in Error Handling and Simplicity

The second paragraph delves into the intricacies of error handling and the principles of simplicity in coding. It advocates for the use of exceptions over return codes to separate error handling from business logic and suggests writing try-catch-finally blocks first to preemptively address potential issues. The paragraph advises against returning or passing null values, recommending the use of special case objects or exceptions instead. It also discusses the importance of defining exceptions based on the needs of the caller and providing meaningful error messages. The 'keep it simple' mantra is further explored with Elon Musk's five-step engineering process, emphasizing the value of removing unnecessary parts of a process. The paragraph concludes with advice on avoiding over-engineering, the importance of testing, and the significance of writing clear and concise tests that cover edge cases.

Mindmap

Keywords

💡WTF per minute ratio

The 'WTF per minute ratio' is a humorous metric used to describe code quality, suggesting that all code is inherently flawed but can be improved for easier maintenance. In the video, it is mentioned as a starting point to acknowledge that while code may not be perfect, there are practices to enhance its quality and maintainability.

💡Code complexity

Code complexity refers to the level of intricacy within a piece of code, which can affect its readability and maintainability. The script emphasizes that if code requires many comments to explain, it likely has high complexity. The video encourages reducing complexity to make code self-explanatory and easier to maintain.

💡Comments

Comments are annotations in code that explain what the code does, but the video argues that they should not compensate for poor code quality. It suggests that an overabundance of comments can be a 'code smell', indicating that the code is overly complex and needs simplification rather than explanation.

💡Good naming

Good naming is a practice in programming where variables, functions, and classes are given clear and descriptive names that reveal their purpose. The video script mentions that poor naming can lead to confusion and the need for additional comments, while good naming reduces the need for explanation and improves code understandability.

💡Single responsibility principle

The single responsibility principle is a core concept in software development that states a class or function should have only one reason to change. The video uses this principle to argue for simplicity in design, ensuring that components have a single, well-defined purpose which aids in maintainability and readability.

💡Error handling

Error handling is the process of managing potential errors in software to prevent crashes and ensure stability. The video discusses best practices for error handling, such as using exceptions over return codes, and emphasizes the importance of clear, meaningful error messages to assist with debugging.

💡Null values

Null values represent the absence of a value and can lead to errors like NullPointerExceptions if not handled correctly. The script advises against returning or passing null, suggesting the use of special case objects or exceptions to avoid related errors, which aligns with the goal of writing clean and maintainable code.

💡Keep it simple

The principle of 'keep it simple' is a recurring theme in the video, advocating for straightforward solutions and avoiding unnecessary complexity. It is illustrated through practices like avoiding over-engineering, ensuring functionality is necessary, and following the single responsibility principle.

💡Testing

Testing is a critical part of software development that ensures code quality and reliability. The video mentions that tests should be simple and clear, cover necessary scenarios without over-testing, and consider edge cases to prevent issues in production.

💡Code decay

Code decay refers to the gradual decline in code quality as a project evolves. The script introduces the Boy Scout rule of leaving the code cleaner than found as a strategy to combat code decay, suggesting small, consistent improvements to maintain code quality over time.

💡Agile

Agile is a methodology for software development that emphasizes flexibility, collaboration, and customer feedback. While the video's speaker expresses initial skepticism about the term, it is mentioned in the context of 'Clean Code - A Handbook of Agile Software Craftsmanship,' indicating the book's focus on Agile principles.

Highlights

The famous comic's assertion that code quality can be measured by the 'WTF per minute' ratio humorously acknowledges the inherent flaws in software development.

Following basic guidelines can ease code maintenance, even if the code quality remains less than ideal.

The importance of good naming conventions in programming to ensure clarity and reduce the need for excessive comments.

Avoiding misleading or unclear names in code to prevent confusion and maintain distinct, meaningful identifiers.

The significance of comments in code and the potential downsides of over-commenting, including increased maintenance burden and verbosity.

The anecdote about a 'place order' method exceeding 2000 lines, illustrating the impracticality of large functions and the need for smaller, more manageable code blocks.

The principle of keeping functions small and focused to avoid complexity and facilitate easier maintenance.

The Boy Scouts' principle applied to software development, emphasizing the importance of leaving code cleaner than found to prevent decay.

The necessity of error handling in software development and strategies to manage it without cluttering the codebase.

Using exceptions over return codes to separate error handling from business logic for cleaner code.

The recommendation to write try-catch-finally statements first to consider potential problems and maintain code consistency.

Avoiding null values in functions to prevent errors and the clutter of null checks in code.

The importance of simplicity in error handling by defining exceptions based on caller needs and providing meaningful error messages.

Elon Musk's five-step engineering process as a model for simplifying and optimizing code development.

The guidance against over-engineering and the value of removing unnecessary parts of a process or code to achieve simplicity.

The single responsibility principle as a key to preventing unnecessary complexity by ensuring classes and functions have one reason to change.

The importance of writing simple, clear tests and finding a balance in test coverage to ensure code reliability.

The necessity of considering edge cases in testing to avoid focusing solely on the 'happy path' and ensure comprehensive code reliability.

Transcripts

play00:00

There is this famous comic stating  that the only valid measurement of  

play00:03

code quality is the WTF per minute ratio.

play00:07

Well… in all honesty, this is actually one  of the most accurate depictions of software  

play00:11

development. Your code will suck no matter what,  but you can at least follow some basic guidelines  

play00:16

to make maintenance easier down the road. Don’t  get me wrong… Your code will still be terrible,  

play00:20

but at least you can be proud  that you gave it your best shot.

play00:23

There are various schools of thought and  books written on the topic of good software,  

play00:27

and in this video we’ll look at 7 lessons  from one of the most popular books on the  

play00:31

subject. Clean Code - A Handbook of Agile  Software Craftsmanship by Uncle Bob.

play00:35

Let me preface this by saying that  using the word “Agile” in anything  

play00:39

software related is a big red flag for  me, but we’ll let this slide for now.

play00:43

Let’s start with something we probably agree with:  

play00:45

Comments Do Not Make up for Bad Code. We all  jumped into a codebase at some point and were  

play00:50

surprised to find some random method which  had more lines of comments than actual code.

play00:54

While the author might have had good intentions,  this is actually a terrible code smell,  

play00:59

and you should mentally prepare for a frustrating  reviewing and debugging session whenever a lot of  

play01:04

comments are present. As a rule of thumb, if you  feel the need to explain your code with comments,  

play01:09

you probably need to spend more  time reducing your code complexity. 

play01:12

Good code needs no explanation. If variables  and methods are correctly named, and the logic  

play01:17

is properly implemented, any block of  code should be pretty self explanatory.

play01:22

Keep in mind that comments have to be maintained  as well, increasing your workload in the long  

play01:26

run. And, they can even make code more verbose  when they are redundant. Java devs deserve a  

play01:31

special medal here, since they made famous the bad  habit of commenting even the getters and setters.

play01:37

I mentioned good naming of methods  and variables, which is yet another  

play01:40

important rule in programming. There are a  few key concepts you should keep in mind.

play01:44

First, variables, functions, and classes  should clearly indicate their purpose. Poor  

play01:49

names that don't reveal intent lead  to code that's hard to understand,  

play01:52

requiring unnecessary comments or extra context.  Note however, that naming conventions might be  

play01:57

different depending on your programming  language. In practice, naming a member  

play02:02

instance simply “m” might be frowned upon in  Java, but it is more than encouraged in Go.

play02:06

Second, you should avoid using  misleading or unclear names,  

play02:10

such as those that might be mistaken for  something else or are too similar to other  

play02:13

names. Names should be distinct and accurately  reflect the purpose of the item they represent.

play02:19

Names should not only be unique but  also meaningful. Avoid arbitrary  

play02:23

distinctions like misspellings or  adding noise words like “info” or  

play02:26

“data” that don't clarify the  function or object’s purpose.

play02:29

On top of that, Names should be easy to pronounce  and easy to search for within the codebase. Avoid  

play02:35

single-letter variables or cryptic abbreviations  that make the code difficult to discuss or search.

play02:40

Finally, always add meaningful context.  When names by themselves are not sufficient,  

play02:44

provide context by placing them  within well-named classes, functions,  

play02:48

or namespaces. This helps to clarify their  meaning within the broader scope of the code.

play02:53

And, as a bonus, while all  these rules are important,  

play02:56

you can actually overuse them. So  find a balance and don’t over do it.

play03:00

Another important rule which  will help you maintain your  

play03:02

code over time is to keep things small.

play03:05

To start with a small anecdote, one of the  projects I worked on in the past was an online  

play03:09

ordering solution which had a “place order”  method which exceeded 2000 lines of code. Yes,  

play03:15

this code is still in production and handles  thousands of new orders daily. However,  

play03:19

you can imagine that implementing anything new  in the “place order” function is a nightmare.

play03:24

Keeping functions small and focused on only  one thing is a no brainer, but, in practice,  

play03:29

you’ll realize that this is easier said than  done. You’ll read about arbitrary rules like the  

play03:33

fact that functions should not exceed 20 lines of  code, which can rarely be followed in real world  

play03:38

scenarios. However, the core principle of keeping  things small should dictate your implementation,  

play03:43

and is the main mechanism that will allow  you to avoid complexity in your code.

play03:48

Note that it is not enough to write good code.  You also have to maintain its quality over time.  

play03:52

Code has this bad habit of deteriorating  as projects progress. To combat this,  

play03:57

we need to actively prevent code from degrading. The Boy Scouts of America have a guiding principle  

play04:02

that applies to software development as well:  "Leave the campground cleaner than you found it."

play04:07

If every time we checked-in our code, we made it  just a bit cleaner than when we checked it out,  

play04:11

we could prevent code decay. The improvements  don't have to be major. You can rename a  

play04:16

variable to make its purpose clearer,  split a function that's getting too big,  

play04:19

remove a small piece of redundant code, or  simplify a complex conditional statement.

play04:24

As always, there is a fine line between  improving code and breaking functionality,  

play04:29

so such changes should be  backed by thorough testing.

play04:32

Ok, we spent some time looking  at the form of the code,  

play04:34

so let’s now take a step further  into some more in depth topics.

play04:38

One really important topic in software development  is error handling. Although this is necessary in  

play04:43

order to deal with unexpected scenarios  and potential failures, it often leads to  

play04:48

a cluttered codebase due to various checks and  logic that might obscure the main functionality.  

play04:53

There are numerous ways programming languages are  dealing with this in practice, from Go’s error  

play04:57

values and the somewhat verbose error handling  to Rust’s special types and pattern matching.

play05:02

While the approaches and suggested  best practices might vary depending  

play05:05

on the ecosystem you are in, there  are a handful of simple rules you  

play05:09

should follow to write clean code  that handles errors gracefully.

play05:12

First, you should use exceptions  instead of return codes. This  

play05:16

allows you to separate the concerns of  error handling and the business logic.

play05:20

Then, when possible, you should always  write try-catch-finally statements first.  

play05:24

This will force you to think about potential  problems and corner case scenarios upfront,  

play05:29

ensuring the code remains in a  consistent state regardless of errors.

play05:33

Null values are a necessary evil in software  development, but you should avoid returning  

play05:37

or passing null in your functions. Returning  or passing null leads to code that is prone to  

play05:42

NullPointerExceptions and cluttered with null  checks. Instead, use special case objects or  

play05:48

throw exceptions to avoid null-related errors. Keeping it simple is a mantra we’ll get back to  

play05:53

in a second, but this applies for errors as  well. You should define exceptions based on  

play05:57

caller needs. So always simplify error handling  by defining exceptions that align with how they  

play06:02

will be caught, reducing redundancy  and making the code more maintainable.

play06:07

And, of course, it goes without saying  that you should provide context with your  

play06:11

exceptions. In other words, exceptions  should include meaningful error messages  

play06:15

that clearly describe the failure,  helping with debugging and logging.

play06:19

Now let’s address the keep it simple principle. I recently read about Elon Musk’s five-step  

play06:23

engineering process, which  follows this principle closely. 

play06:27

In short, when building something  you should follow five clear steps:  

play06:31

Make the requirements less dumb,  Delete the part or process step,  

play06:34

Simplify or optimize, Accelerate  cycle time, and, finally Automate.

play06:38

While simplifying and optimizing is an  obvious action, I find the second step more  

play06:43

interesting. In practice, you’ll discover  that sometimes the best way to simplify  

play06:47

a process is to actually completely  remove it from the workflow. And yes,  

play06:51

this applies to coding as well, and Clean  Code offers some guidance on this topic.

play06:55

First, you should always avoid over-engineering,  

play06:57

and, believe it or not, sometimes  abstraction can be a pain in the butt. 

play07:01

Second, make sure that you are actually going  to need the functionality you are implementing. 

play07:06

Of course you should always avoid duplication  and, finally, follow the single responsibility  

play07:11

principle to make sure that your classes and  functions have only one reason to change.  

play07:16

This prevents unnecessary complexity by keeping  classes and functions focused on a single task.

play07:21

Finally, let’s address the most hated aspect  in software development - testing. As much  

play07:26

as we despise it, testing is a crucial aspect of  writing clean, maintainable, reliable code. Again,  

play07:33

there are a few best practices you should  keep in mind when forced to write tests.

play07:37

You should write simple, clear tests  that are easy to read and understand.  

play07:41

You should avoid over-testing and find a  balance for your test coverage. Finally,  

play07:45

it should be obvious that edge cases should be  thoroughly thought out. It’s easy for developers  

play07:50

to only focus on happy path testing, so it  is a good idea to team up for proper testing.

play07:55

If you feel like you learned something,  

play07:56

you should check some of my other videos as  well. Until next time, thank you for watching!

Rate This
★
★
★
★
★

5.0 / 5 (0 votes)

Related Tags
Clean CodeSoftware DevelopmentCode QualityAgile MethodError HandlingCode SimplicityBest PracticesCode MaintenanceTesting StrategiesProgramming Tips