"Clean Code" is bad. What makes code "maintainable"? part 1 of n

Internet of Bugs
13 May 202418:15

Summary

TLDRIn this video script, the speaker critiques the conventional advice on code maintainability, arguing that much of it lacks practical principles and can even be harmful. They express a disdain for books like 'Clean Code,' which they believe promotes practices leading to team conflict and poor maintainability. The speaker emphasizes that maintainable code should be easy to understand for newcomers and stresses the importance of code isolation to prevent changes from causing unintended side effects. They also highlight the fallacy of top-down code reading and the inefficiency of hiding code logic behind abstractions, advocating for a more realistic approach to coding that acknowledges the inevitability of bugs and the need for easy debugging.

Takeaways

  • 📚 The speaker criticizes common advice on writing good code, calling it 'crap' because it lacks real-world applicability and often leads to misguided practices.
  • 📘 The speaker expresses a strong dislike for the book 'Clean Code', arguing that its advice is harmful and can lead to more problems in code maintainability.
  • 🔍 The speaker emphasizes that code maintainability is about making the code easy for others to work on, especially those who are unfamiliar with it, rather than simplifying the writing process for the original author.
  • 👀 The speaker points out that code is generally not read from top to bottom, and that the way most coding literature presents code is flawed and not reflective of real-world practices.
  • 🔍 The speaker advocates for a bottom-up approach to understanding code, starting from a bug or error message and tracing back through the codebase to find the root cause.
  • 🔗 The speaker discusses the problems with having many subclasses that are slight variants of each other, as it makes it difficult to trace through the code and understand the flow.
  • 🛠 The speaker argues that changes made in one part of the application should not affect other unrelated parts, highlighting the importance of code isolation for maintainability.
  • 🚫 The speaker criticizes the 'no global variables' and 'single responsibility principle' as being too simplistic and not necessarily preventing issues like the 'whack-a-mole' state of bugs.
  • 🔑 The speaker uses an example from 'Clean Code' to illustrate how hiding decision-making within classes can lead to a lack of transparency and difficulty in debugging.
  • 🛑 The speaker warns against the attitude of dismissing bugs that cannot be immediately reproduced, suggesting that this can lead to unresolved issues and a false sense of security.
  • 🚫 The speaker concludes by stating that the philosophy behind books like 'Clean Code' is flawed, as it assumes that code can be made perfect through simplification, which is unrealistic.

Q & A

  • What is the main topic discussed in the video script?

    -The main topic discussed in the video script is code maintainability, specifically what makes code good or bad and the critique of common advice on writing maintainable code.

  • What does the speaker claim about most of the advice on writing good code?

    -The speaker claims that most of the advice on writing good code is 'crap' because it is not based on actual principles or heuristics and often does not translate to real-world improvements.

  • What does the speaker dislike about the book 'Clean Code'?

    -The speaker dislikes 'Clean Code' because they believe the advice in it is harmful, it's specific to a particular programming language, and it promotes practices that can create contention and confusion within development teams.

  • What is the speaker's view on the importance of code readability?

    -The speaker believes that code readability is crucial, but it should be about making the code easier to work on for someone unfamiliar with it, not just about writing code that is easy for the original author to write.

  • According to the speaker, what is the primary way developers understand a new code base?

    -The speaker states that developers typically understand a new code base from the bottom up, starting with a bug or an error message, and tracing the code by following function calls and logs, rather than reading the code from top to bottom.

  • What does the speaker suggest is a common mistake made by those who follow 'Clean Code' and similar advice?

    -The speaker suggests that a common mistake is the creation of subclasses that are tiny variants of each other, which can make it difficult to trace through the code and identify the source of bugs or features.

  • What does the speaker argue is the fundamental principle of maintainable code?

    -The speaker argues that the fundamental principle of maintainable code is to make it easy to find and fix bugs when they occur, and to write tests to prevent them from recurring, rather than trying to write code that can't have bugs.

  • Why does the speaker criticize the approach of hiding information within private classes as suggested in 'Clean Code'?

    -The speaker criticizes this approach because it prevents other parts of the program from accessing potentially relevant information for finding and fixing bugs, thus breaking the principle that changes in one part of the application should not affect other parts.

  • What does the speaker mean by the term 'whack-a-mole' in the context of software development?

    -The term 'whack-a-mole' refers to a state in software development where fixing one bug causes another feature to stop working, creating a cycle of constant bug fixing with no end, often due to poor architecture or practices.

  • What is the speaker's view on the importance of code tests and the 'Open/Closed Principle' in maintaining code?

    -The speaker believes that while code tests and principles like 'Open/Closed' are important, they are not sufficient on their own. They can still result in a 'whack-a-mole' state if the architecture and practices do not ensure that changes in one part of the application do not break other parts.

  • What does the speaker suggest is the attitude of some developers who follow the advice in books like 'Clean Code'?

    -The speaker suggests that some developers who follow this advice may develop an attitude of dismissing bugs that they cannot reproduce as not real problems, which can be detrimental to the development process and lead to unresolved issues.

Outlines

00:00

🤔 The Myth of Good Code Advice

The speaker begins by challenging the conventional wisdom on what constitutes good code, criticizing much of the advice as being baseless and not grounded in practical principles. They argue that many coding principles, such as those from 'Clean Code', are often too language-specific and can lead to unnecessary debates and contention within development teams. The speaker emphasizes the importance of maintainability, stating that code should be easy for someone unfamiliar with it to work on, rather than focusing on ease of initial writing. They also highlight the common misconception that code is read linearly, which they claim is rarely the case in practice.

05:01

🔍 The Realities of Code Maintenance

In this section, the speaker discusses the typical process of engaging with a new codebase, which often involves fixing a list of existing bugs rather than having the luxury of studying the code from scratch. They describe the common practice of tracing code from the bottom up, starting with an error message or log and working backward through the code to understand the flow and identify where things go wrong. The speaker criticizes 'Clean Code' and similar principles for promoting a top-down approach that can obfuscate the code and make it difficult to trace issues, leading to a situation where developers must resort to runtime debugging to understand the code flow.

10:02

💡 The Importance of Code Isolation

The speaker emphasizes the importance of code isolation, where changes made in one part of the application should not affect other parts. They argue that principles such as 'no global variables' and 'single responsibility principle' are aimed at ensuring that changes are localized and do not have unintended consequences elsewhere in the application. The speaker also discusses the concept of 'whack-a-mole' programming, where fixing one issue inadvertently breaks another part of the application, often due to poor architecture or lack of adherence to isolation principles. They highlight the need for a coding philosophy that promotes changes to be contained within relevant parts of the application.

15:03

😤 The Pitfalls of Simplification and Concealment in Code

In the final paragraph, the speaker expresses frustration with the approach of simplifying and hiding code details, as advocated by 'Clean Code' and similar resources. They argue that this can lead to a lack of transparency and understanding, making it difficult to diagnose and fix bugs, especially when requirements change or edge cases are encountered. The speaker criticizes the assumption that code can be made 'clean' by simplification, asserting that this overlooks the reality that all code can have bugs and that the goal should be to make code maintainable and debuggable. They conclude by cautioning against the naivete of such approaches and the potential harm they can cause to real-world projects.

Mindmap

Keywords

💡Code Maintainability

Code maintainability refers to how easily code can be modified, extended, and understood by developers other than the original author. In the video, the speaker emphasizes that maintainability is about making code accessible for those unfamiliar with it, rather than simplifying it for the initial writing process. The concept is central to the video's theme, as it critiques common advice on writing 'good code' and argues for a more practical approach to maintainability.

💡Good Code vs. Bad Code

The dichotomy between good and bad code is a foundational concept in the video. Good code, as discussed, is maintainable, understandable, and not necessarily simple or concise. Bad code, on the other hand, may follow certain principles that seem logical on the surface but fail in real-world applications, leading to difficulties in maintenance and debugging. The speaker uses this distinction to critique popular coding advice, suggesting that much of it leads to bad code by focusing on the wrong aspects of coding.

💡Clean Code

Clean Code is a term and a book title that the speaker criticizes in the video. It represents a set of principles and practices aimed at making code more readable and maintainable. However, the speaker argues that the advice given in 'Clean Code' and similar resources often leads to code that is difficult to understand and maintain in practical scenarios. The critique of 'Clean Code' serves to illustrate the gap between theoretical coding principles and real-world coding needs.

💡Design Patterns

Design patterns are reusable solutions to common software design problems. In the video, the speaker mentions design patterns as being often too specific to certain languages or frameworks, which can limit their applicability and usefulness across different coding environments. The critique highlights the need for more universally applicable principles that can enhance code maintainability regardless of the specific programming language used.

💡Code Isolation

Code isolation is the concept of ensuring that changes made in one part of the codebase do not inadvertently affect other parts. The speaker argues that this is a critical aspect of maintainable code, as it allows developers to make targeted changes without causing unintended consequences elsewhere in the application. The video uses the idea of code isolation to critique practices that lead to interconnected and tightly coupled code, which can be difficult to modify and maintain.

💡Global Variables

Global variables are variables that can be accessed from any part of the program. The speaker mentions 'no global variables' as a maxim that is often associated with good coding practices. However, the critique extends to the idea that avoiding global variables is not sufficient for maintainability and that a more holistic approach is needed to ensure that changes in one part of the code do not impact others.

💡Single Responsibility Principle

The single responsibility principle is a principle from SOLID design principles that states that a class should have only one reason to change. In the video, the speaker suggests that while this principle is often touted as a key to good code, it is not always sufficient for ensuring code maintainability. The video implies that adhering to this principle does not automatically prevent the 'whack-a-mole' effect, where fixing one issue leads to another.

💡Open/Closed Principle

The open/closed principle states that software entities should be open for extension but closed for modification. The speaker uses this principle as an example of advice that, while seemingly beneficial, can lead to code that is difficult to understand and maintain. The video suggests that strict adherence to such principles can result in a codebase that is hard to debug and modify effectively.

💡Debugging

Debugging is the process of finding and resolving bugs or defects in a software program. The video emphasizes the importance of being able to debug code effectively as a key aspect of maintainability. The speaker criticizes coding practices that make it difficult to trace and fix bugs, suggesting that maintainable code should facilitate the debugging process rather than obscure it.

💡Unit Tests

Unit tests are tests that validate individual components of the software. In the video, the speaker points out that having unit tests and passing them does not guarantee that the code is bug-free or maintainable. The video uses this to argue against the reliance on testing as the sole measure of code quality, highlighting the need for a more comprehensive approach to code maintainability.

💡SOLID Principles

SOLID is an acronym for five design principles intended to make software designs more understandable, flexible, and maintainable. The speaker mentions SOLID in the context of criticizing the adherence to these principles as a sufficient condition for code maintainability. The video suggests that while SOLID principles are valuable, they must be applied with a broader understanding of the real-world implications for code maintenance.

Highlights

The speaker criticizes common advice on good code as being largely ineffective and not based on practical principles.

The speaker expresses a strong dislike for the book 'Clean Code', considering its advice harmful.

Design patterns and principles discussed are often language-specific and not universally applicable.

The speaker emphasizes the importance of code maintainability for unfamiliar developers rather than ease of initial writing.

Code is generally not read from top to bottom, contrary to what is often taught.

The speaker discusses the inefficiency of code that is optimized for printing in books rather than for real-world use.

People typically understand code from the bottom up, starting with a bug or error message.

The speaker argues against the practice of creating subclasses that are tiny variants of each other, as it complicates debugging.

The speaker criticizes the advice in 'Clean Code' that leads to obfuscation and difficulty in tracing code.

Isolating changes so they don't affect unrelated parts of the application is key to maintainable code.

The speaker discusses the 'whack-a-mole' state of projects where fixing one bug introduces new ones.

Even with principles like SOLID and unit tests, projects can still suffer from poor maintainability.

The speaker recounts a specific bug involving an expense report app to illustrate the problems with certain coding practices.

The speaker criticizes the advice in 'Clean Code' to hide decision-making processes within classes, which hinders debugging.

Maintainable code should allow for bugs to be found and fixed efficiently, not just written cleanly.

The speaker argues against the attitude of dismissing bugs that can't be immediately reproduced.

The speaker concludes by emphasizing the need for maintainable code that is practical and not just theoretically clean.

Transcripts

play00:00

So today, I'm going to start

play00:01

talking about code maintainability,

play00:04

the idea of what makes

play00:05

for good code and what makes for

play00:06

bad code.

play00:07

It's a huge topic and it's got a

play00:09

ton of corner cases, so I'm not

play00:11

going to be able to do all

play00:12

of it.

play00:12

I'm not even really going to get

play00:14

much but a good start.

play00:15

What I will say is that most of the

play00:18

advice that I've seen about what

play00:20

makes for good code

play00:21

is crap.

play00:22

And the reason that it's mostly

play00:24

crap is because it's not really

play00:26

based on any actual principles

play00:27

or heuristics, by which I don't

play00:29

mean that they don't have things

play00:31

they want to accomplish,

play00:33

but those things they want to

play00:34

accomplish don't actually map to

play00:36

making things better in the

play00:37

real world except in some

play00:39

hypothetical kind of sense.

play00:40

I have a very different take on it.

play00:42

I'm going to kind of try to walk

play00:43

you through that and hopefully by

play00:46

the time we get to the

play00:46

end, assuming you stick with me,

play00:48

you'll see why it is that I think

play00:50

that most of the advice

play00:50

is garbage, especially this thing.

play00:54

I did a video not long ago on

play00:56

programmer books and there were

play00:58

some people that said I should

play00:59

have included this.

play01:00

There were a lot of people that

play01:01

said they were happy I didn't

play01:02

include this.

play01:03

I hate this book.

play01:04

I hated this book long before it

play01:05

was trendy to hate this book.

play01:06

I took it seriously for a very

play01:07

short period of time and then it

play01:08

became obvious to me that

play01:09

the advice in here is bad.

play01:12

I mean it's just it's harmful.

play01:14

I'll get into why I'll talk about a

play01:16

couple of examples today, but just

play01:19

for the record.

play01:23

There's one for the thumbnail.

play01:34

This is the Internet of Bugs.

play01:35

My name is Carl and we're talking

play01:37

about coding advice on how to

play01:39

make maintainable and clean code.

play01:42

One thing about most of the advice,

play01:44

this goes for actually "Clean Code",

play01:47

a bunch of other

play01:48

things, a lot of design patterns.

play01:49

They're very specific to a specific

play01:51

language and a lot of the

play01:52

principles that they talk

play01:53

about that are important are things

play01:55

that are not important in other

play01:57

languages and are not

play01:59

relevant in other languages.

play02:00

I have a set of ideas that I think

play02:03

are way more applicable because I've

play02:05

worked in a

play02:05

bunch of different languages and I've

play02:07

worked in a bunch of different

play02:07

frameworks and I have

play02:09

found the same techniques to be

play02:11

useful over and over.

play02:12

Things like "Clean Code" create an

play02:15

opportunity for teams to argue with

play02:17

each other and for

play02:17

people to point to things and to

play02:19

tell each other that they're wrong

play02:20

and it just creates

play02:21

contention in a group and that's

play02:22

pointless especially when a lot of

play02:24

the advice actually

play02:25

takes you the wrong direction.

play02:27

I try really hard to make my advice

play02:30

based on my experience and based on

play02:33

what I've seen

play02:34

and what I've discovered over the

play02:37

years maps across a bunch of

play02:39

different languages and

play02:40

a bunch of different platforms.

play02:41

Hopefully as we go, you'll see that.

play02:42

To start with, the point of code

play02:46

maintainability is to make the code

play02:48

easier to work on for someone

play02:50

who's unfamiliar with it, not to

play02:51

make it easier for you to write in

play02:53

the first place.

play02:53

There's a lot of hypothetical

play02:54

garbage in the advice on how you

play02:56

write code.

play02:57

It's not about some hypothetical

play02:59

"how changes might get made in the

play03:01

future."

play03:01

It's about "how do you find the

play03:05

places that changes need to be made

play03:06

now" and "how do you

play03:08

assure that you're correct in that"

play03:11

and that those changes are isolated.

play03:13

It's not just how easy it is for

play03:15

somebody who's not you to maintain

play03:17

your project but

play03:19

you'll find, if you've been doing

play03:21

this a while, that it's very often

play03:23

the case that you're

play03:25

away from a project for a while and

play03:26

then you come back to it and you

play03:28

have to figure it

play03:28

out all over again.

play03:30

It's not at all unusual for me to

play03:31

be like, "Okay, what idiot wrote this?"

play03:33

"Oh look, I did six months ago."

play03:35

Second principle: code is generally

play03:38

not read.

play03:40

You don't start at the top of a

play03:41

file and read down and then go to

play03:42

the next file and read

play03:43

down. Not if you have a choice at least.

play03:44

If the only way that you can

play03:46

understand a code base is to read

play03:47

it like that, then the

play03:48

original author failed.

play03:49

There's one exception to this.

play03:53

There are times that I'm hired to

play03:54

audit code.

play03:55

Basically I'm brought in to

play03:57

evaluate the progress or lack

play03:59

thereof that some other developer

play04:00

has made and in that case I do

play04:03

often read code from top to bottom

play04:05

but in that case I'd

play04:06

argue I'm not really maintaining it

play04:07

and it's not about maintainability.

play04:09

I'm auditing it really so that's a

play04:11

different case than that when I'm

play04:12

talking about.

play04:12

Aside from that, I never read code

play04:14

from top to bottom if I have any

play04:16

choice at all.

play04:16

This is where most of the

play04:17

literature fails utterly.

play04:19

I know as a published technical

play04:20

author myself that it's really hard

play04:22

to write code listings

play04:24

so that they can be printed out on

play04:25

dead trees and bound into a book so

play04:27

that they can be

play04:27

understood.

play04:28

It's difficult and it's a skill to

play04:30

get it to work that way but if you

play04:32

think that it

play04:32

makes sense to optimize your code

play04:34

so that everything is two or three

play04:35

lines and something

play04:36

that should take half a page ends

play04:37

up getting spread across three

play04:39

pages so the typesetter

play04:40

hasn't eased your time of figuring

play04:41

out where to put the page breaks.

play04:43

I think you're valuing the wrong thing.

play04:44

So here's a listing from "Clean Code"

play04:46

pages 30 and 31.

play04:47

If you can't tell that the goal

play04:48

here was to have a lot of different

play04:50

places that page

play04:50

breaks could happen without the

play04:51

reader having to turn pages back

play04:52

and forth, I don't know

play04:53

what to convince you.

play04:54

All of that code could have fit

play04:56

easily in three quarters of a page

play04:58

but it's all spread

play04:58

out to make it easier to typeset.

play05:00

I thought about actually drawing

play05:02

arrows so you could actually see

play05:03

the flow of the code

play05:04

but no one's going to be convinced by that.

play05:05

Either you're going to look at it

play05:06

and you're going to realize that it's

play05:07

stupid or you're

play05:08

not and if you think that that's

play05:10

the way code ought to be written, I

play05:11

don't know what

play05:12

to tell you.

play05:12

In the real world, the way people

play05:14

figure out code is from the bottom

play05:15

up. When I'm going to fix a new code

play05:16

base, right, when I'm brought in to

play05:18

work on a code base,

play05:19

it's never the case that someone

play05:21

brings me in and says, "Okay, here's

play05:23

a new code base.

play05:25

Go take a look.

play05:27

Take a week.

play05:28

No big deal.

play05:29

Read the whole thing.

play05:30

Figure it out."

play05:30

All that kind of stuff.

play05:32

Never happens.

play05:33

What happens is I get brought in to

play05:34

work on a new codebase and there's

play05:36

already a list

play05:37

of "we need this fixed and we need

play05:38

this fixed and we need this fixed

play05:39

and we need this added."

play05:40

There's always a laundry list of

play05:42

stuff that already needs to happen.

play05:44

If there wasn't already a bunch of

play05:46

stuff that they needed to get done,

play05:47

they wouldn't be bringing somebody else in.

play05:49

So what you do, what I do, what

play05:52

most of the folks that I've talked

play05:53

to do is we start with

play05:54

a bug.

play05:55

We start with something in the bug

play05:57

that tells us what's going on.

play05:59

We look for an error message, for

play06:00

some on-screen text.

play06:02

We look for a log statement,

play06:04

something that's in the bug report

play06:05

and then we search for that

play06:06

string in the code base and we

play06:08

figure out, Okay, here's the place

play06:10

where that string

play06:11

gets printed.

play06:12

Here's the part where that string

play06:14

shows up on the screen, Okay, I

play06:15

know I'm around

play06:16

here somewhere.

play06:17

Let me read this part.

play06:18

Okay, cool.

play06:19

Now, how did I get here?

play06:21

Then you go take your editor, you

play06:22

say, "Right click, show me what

play06:23

function called this."

play06:25

And then you jump up a level and

play06:27

then you figure out, "Okay, so now

play06:28

I know what's going

play06:29

on here.

play06:30

Right click, go up a level."

play06:32

And that's how you trace code,

play06:35

right?

play06:36

And that happens not just the first

play06:38

time, but bug after bug after bug

play06:39

after bug.

play06:40

That's occasionally the case that I'll

play06:42

get a bug and I'll know right where to go,

play06:43

but generally that's because there's a

play06:45

bug around there that I've already

play06:47

had to deal with.

play06:48

And it's not at all unusual for me

play06:50

to be working on big code bases and

play06:52

work on them

play06:53

for a year and there'll be a chunk

play06:54

of that code base that I've never

play06:55

even looked at because

play06:56

I've never needed to because there

play06:57

hasn't been a bug in there that I've

play06:58

had to worry about.

play06:59

So many, many code bases just

play07:01

utterly fail to make any sense this

play07:03

way. And a lot of times it's because of

play07:06

these top down techniques that

play07:09

supposedly make code

play07:10

more clean, but it actually just

play07:12

obfuscate everything.

play07:13

One way that that happens is you

play07:14

have a whole bunch of different subclasses

play07:17

that are just

play07:18

tiny little variants of each other, right?

play07:19

So I'll say, "Hey, IDE, right click,

play07:24

show me what method calls this."

play07:25

And I'll get like a dozen answers

play07:27

because they're all of these subclasses

play07:29

that all do

play07:30

different things and I have no way

play07:31

of knowing which one it was that

play07:34

happened to be calling

play07:36

this portion of the code when the

play07:38

bug happened.

play07:40

And so now I have to give up on the

play07:42

being able to find it in the code

play07:43

base.

play07:44

I have to switch gears.

play07:46

I have to get the thing up at

play07:47

runtime.

play07:48

I have to reproduce the function.

play07:49

I have to figure out how to debug

play07:51

it or add print statements to it or

play07:53

something.

play07:53

So I can figure out which one of

play07:55

those classes was the one that was

play07:57

actually there when the

play07:58

actual bug happened and then I can

play07:59

continue working up the stack.

play08:01

And that's just a nightmare.

play08:02

It takes way more time than it

play08:03

needs to.

play08:04

So here's a listing from chapter 10

play08:05

of Clean Code.

play08:06

This is page I think 148 or 149

play08:09

something like that.

play08:09

I don't know if your addition is

play08:10

the same as mine, but when you're

play08:12

trying to go up code

play08:13

and you hit something like this

play08:14

with all of these different "this

play08:16

extends SQL" you've

play08:17

hit a dead end or really you've hit

play08:19

a maze of twisty little classes

play08:20

that are all alike.

play08:21

And there's no way of knowing which

play08:22

one's which.

play08:23

It's a productivity killer when you're

play08:25

trying to figure out what's going

play08:25

on, where this

play08:26

bug came from, or where this

play08:28

feature needs to get added. In the

play08:29

case where I do manage

play08:31

to get up to the top-ish.

play08:34

And so I have some idea of the

play08:36

slice of the app that's actually

play08:38

relevant to what I'm working

play08:40

on.

play08:40

Hopefully I didn't have to go to

play08:42

runtime to figure that out.

play08:43

But once I figure that out, the

play08:46

next idea is that everything that I

play08:49

need to do in order

play08:52

to change the bug that affects this

play08:54

thing down here should be part of

play08:56

that slice.

play08:57

I mean, not necessarily the exact

play08:59

methods all the way down in the

play09:00

stack, but this class

play09:03

and this class and this class or

play09:04

this object and this object and

play09:05

this object or this function

play09:07

and this function and this function

play09:08

or this file that calls this file

play09:10

that calls this

play09:10

file, right?

play09:12

The rest of the code, the rest of

play09:15

the application hopefully is not

play09:20

containing stuff that's causing

play09:22

this particular bug because that

play09:23

makes it really, really hard to

play09:25

chase down.

play09:25

So that's part of the whole code

play09:27

isolation thing, right?

play09:28

So the corollary to that is when I

play09:30

make a change in this stack, that

play09:33

change that happens

play09:34

in this vertical part of the

play09:36

application should not break stuff

play09:38

elsewhere in the application.

play09:40

So this is where you get these maxims

play09:43

like "no global variables," "single

play09:46

responsibility

play09:46

principle," "open closed principle,'

play09:48

all this advice that you get

play09:49

basically boiled down

play09:50

to "changes here, shouldn't break

play09:52

anything not here," saying it that

play09:54

way, saying "changes

play09:56

here shouldn't break anything not

play09:57

here" is harder for a beginner to

play10:00

understand.

play10:00

It's a lot easier for a beginner to

play10:02

understand "no global variables," right?

play10:04

But it's not at all unusual for me

play10:06

to find projects where that's

play10:08

completely violated.

play10:09

It's a state I call whack-a-mole.

play10:10

I wrote about it in my book where

play10:11

basically every time you change

play10:12

something here, every

play10:13

time you fix one bug, some feature

play10:15

that used to work stops working

play10:16

somewhere else.

play10:17

It's a nightmare and it has killed

play10:19

more projects than anything else

play10:22

that I've ever seen and

play10:23

it usually happens right at the end

play10:24

of the project when everything is

play10:26

trying to come

play10:27

together and you're doing final QA

play10:28

and then oh, there's a bug over

play10:29

here and then you fix

play10:30

that and oh, there's a bug over

play10:31

here that wasn't there yesterday

play10:32

and it's always the

play10:34

result of poor architecture, poor

play10:36

leadership, poor developers.

play10:39

Maybe the developer was incompetent,

play10:41

maybe they were over their head,

play10:43

maybe they weren't

play10:43

paying enough attention, maybe they

play10:45

just didn't care enough, it's hard

play10:46

to know.

play10:47

But by the time you get to the end

play10:48

of the project and you get in this

play10:49

whack-a-mole state, you

play10:50

generally can't fix that without

play10:52

making major structural changes

play10:55

that just cause the project

play10:57

to go way over budget and way over

play10:59

time.

play11:00

The thing is it's not at all

play11:02

unusual for me to find a project

play11:03

that is in that whack-a-mole

play11:04

state and then go through it and

play11:06

find out that it's got unit tests

play11:08

and the unit tests

play11:09

all pass and it's got open closed

play11:11

principle, it's using the solid

play11:12

principle and it doesn't

play11:13

have global variables and all that

play11:14

kind of stuff.

play11:15

Those principles just aren't

play11:16

sufficient, right?

play11:18

You can follow all those rules and

play11:20

still end up with whack-a-mole

play11:21

because they're just

play11:22

not good enough.

play11:23

It's better to have the principal

play11:24

say, look, don't do whack-a-mole,

play11:26

right? Make sure that as you're coding

play11:30

that the stuff here affects the

play11:34

stuff here and the stuff

play11:35

over there doesn't affect the stuff

play11:37

here in vice versa.

play11:38

So let's talk about a specific

play11:39

example.

play11:40

So imagine a hypothetical expense

play11:42

report app.

play11:43

So imagine you get a bug ticket

play11:44

that the user submitted receipts

play11:46

totaling $25.13 but the

play11:49

report only said $25 even.

play11:52

So where did the extra $0.13 go?

play11:53

So I've had a variant of this

play11:55

problem, it wasn't exactly this, it

play11:56

wasn't expense reports

play11:57

but it was the same kind of thing

play12:00

where the amount ended up being

play12:02

wrong because of something

play12:03

that you'll find out on in a minute.

play12:05

So for purposes of this discussion

play12:07

though, I'm going to talk about it

play12:08

as if it was expense

play12:09

reports but this is more or less an

play12:12

actual problem that I've run into

play12:13

in real life.

play12:14

So I'm looking for why it is that

play12:16

this stuff that I can see added up

play12:18

to $25.13 didn't end

play12:20

up saying $25.13 and where the hell

play12:23

the other 13 cents go? And I look for

play12:24

places that the cents

play12:25

get cut off.

play12:25

I look for places that things get

play12:27

rounded, I can't find any of that,

play12:28

I have no idea what's

play12:29

going on, takes me days off and on

play12:31

fighting with this, I still have no

play12:32

real idea.

play12:32

And then what happens is I'm

play12:34

looking at the specs and I'm

play12:36

looking at the accounting manual

play12:37

and I realize that city day in

play12:40

question, the per diem for that was

play12:42

$25.

play12:43

Turned out that the issue wasn't

play12:45

that the $25.13 was getting truncated

play12:48

$25.

play12:49

It's the $25.13 was being ignored

play12:52

completely because the system had

play12:55

decided that those

play12:56

receipts weren't relevant because

play12:57

that person was supposed to be on

play12:58

per diem that day.

play12:59

And in this particular case, the

play13:01

conditions by which the program

play13:03

decided "is this a per diem

play13:04

kind of expense report" or a "look at

play13:06

the receipts from the restaurants"

play13:07

kind of expense report

play13:08

was wrong.

play13:09

In that particular set of

play13:10

circumstances, it made the wrong

play13:11

choice because of weird accounting

play13:13

reasons.

play13:13

This is a particularly egregious

play13:15

kind of bug and it's specifically

play13:17

caused by the technique

play13:18

on page 109 and 110 of Clean Code.

play13:21

I'll put those on the screen.

play13:22

What this does is it tells you that

play13:25

you should return an amount that's

play13:27

either the per diem

play13:28

amount or it's the total of the

play13:31

receipts amount and not tell

play13:34

anywhere else in the program

play13:35

which one you picked. You're

play13:37

explicitly told by Clean Code at

play13:40

this point to hide why you

play13:43

made that decision from the rest of

play13:45

the program.

play13:46

And this is under the guise of

play13:47

error handling.

play13:49

It makes me furious.

play13:50

They're telling you that the right

play13:53

way to handle a potential error is

play13:56

take information

play13:57

that might be relevant to finding a

play13:59

bug and prevent anywhere else in

play14:02

the code from having

play14:04

access to that information because

play14:05

it's hidden inside the private part

play14:07

of this class.

play14:08

But it breaks the basic fundamental

play14:11

"stuff over here shouldn't be

play14:12

affected by stuff over

play14:13

there" thing because it draws a line

play14:15

between "over here" and "over there"

play14:17

and it hides all

play14:18

of this stuff in these private

play14:21

classes and doesn't let anybody

play14:22

else in the rest of the

play14:23

program see any of that information.

play14:26

This is an utter failure of the

play14:28

philosophy that goes into Clean

play14:29

Code and honestly most

play14:30

of the programming advice that you

play14:32

see. It assumes that you can make

play14:33

code cleaner by simplifying

play14:35

things and that's just wrong

play14:38

because that assumption is only

play14:39

valid in a world where the

play14:40

code you're simplifying is a

play14:42

hundred percent guaranteed to be a

play14:43

hundred percent correct for all time and it's not. Even if

play14:45

you have a 100% test

play14:46

coverage, and they did

play14:48

more or less in the case that I ran

play14:49

into, that doesn't mean you

play14:50

understood the requirements!

play14:52

That doesn't mean the requirements

play14:53

haven't changed!

play14:54

It just means that the code you

play14:55

wrote matches the understanding

play14:57

that you had at the time,

play14:58

and in this case as with a ton of

play15:00

cases there was a corner case-there

play15:02

was a set of circumstances

play15:03

under which the original programmers

play15:04

understanding was wrong- maybe even

play15:06

the initial specification

play15:07

was wrong.

play15:08

It took a while for that to get

play15:09

triggered and noticed but because

play15:11

of the way this thing

play15:12

got coded it was impossible to

play15:16

understand what was going on

play15:17

without digging into the

play15:18

internal private methods of this

play15:22

one class way the heck over there

play15:24

that gave no indication

play15:25

it was relevant to what was going

play15:27

on over here.

play15:28

The other thing that happens in a

play15:29

lot of times in these clean code

play15:30

systems, a report

play15:31

will come in of a bug that happens

play15:33

to a user and it will be impossible

play15:37

to figure out how

play15:39

that could have happened and it

play15:41

will be almost impossible to figure

play15:43

out how to reproduce

play15:44

that and so the developer just says

play15:47

"oh I can't reproduce that" and just

play15:48

closes it and that's

play15:50

the kind of attitude that these

play15:52

kinds of books foster and it's the

play15:53

kind of attitude that

play15:54

a lot of people that follow these

play15:55

books have, because they write code

play15:58

in such a way that

play15:58

it's really hard to find where

play16:01

things are going wrong and that way

play16:02

they can pretend

play16:03

that "oh that wasn't really a

play16:05

problem because it couldn't be

play16:05

reproduced so it doesn't really

play16:07

matter it doesn't really count

play16:09

against me it's not a real bug"

play16:12

Oh it's irritating! And

play16:13

the reason that they do this, the

play16:16

reason that the people that write

play16:20

this kind of book believe

play16:22

in this kind of code hiding and

play16:24

believe in "simplifying" code and

play16:26

"cleaning" code this way

play16:27

is because they fundamentally

play16:29

believe that their code is perfect

play16:32

and no code is perfect.

play16:33

The point of maintainable code is

play16:36

not to write code that can't have

play16:39

bugs, It is not possible

play16:41

to write code that can't have bugs.

play16:42

The value of maintainable code is

play16:45

writing code so that

play16:47

when the bugs happen, and they will

play16:49

happen, you can find them, and you

play16:52

can fix them, and

play16:53

you can write tests to make sure

play16:55

they don't pop up again. And it's a

play16:57

completely naive viewpoint

play16:58

from people writing these books and

play17:00

a lot of people have this attitude

play17:02

and usually those

play17:03

are people who are developers who

play17:05

have never actually had to support

play17:07

the code they've written

play17:08

they just write the code and they

play17:09

throw it over the wall of the Ops

play17:10

team and when something

play17:11

goes wrong "it's their problem not

play17:13

my problem it couldn't have been my

play17:14

problem because I

play17:15

had to have written the right thing

play17:16

because all of my unit tests passed

play17:18

so it's gotta

play17:18

be somebody else's problem it can't

play17:20

have been my problem." Maybe the

play17:22

author just doesn't

play17:23

know any better maybe the author is

play17:25

one of those developers that's

play17:27

never had to actually

play17:29

debug code maybe the author is

play17:30

catering to the like Prima Donna

play17:32

mindset that these books

play17:33

encourage in developers and tends

play17:35

to be present in the developers

play17:36

that follow these authors.

play17:37

Either way it's just it doesn't

play17:39

work in the real world. It's

play17:40

counterproductive. There are

play17:42

a ton of other examples from clean

play17:43

code and other books like it that I

play17:45

could go through,

play17:46

and I'm sure others will come up in

play17:47

future videos, but I can't cover all of it

play17:49

in one video, so I think I'm gonna call it

play17:50

here, before I get too more

play17:52

irritated. Okay. Deep cleansing

play17:56

breath. Remember, the Internet is

play18:03

full of bugs, and anyone that says

play18:06

different is probably

play18:07

trying to sell your their book on

play18:09

how to simplify your code. Let's be

play18:11

careful out there.

Rate This

5.0 / 5 (0 votes)

Related Tags
Code MaintainabilityClean Code CritiqueProgramming AdviceSoftware DevelopmentDebugging ProcessCode SimplicityTechnical AuthoringDeveloper MindsetBest PracticesReal-World Coding