Clean Code - Uncle Bob / Lesson 1
Introduction
The speaker introduces the topic of clean coding and architecture, and introduces Robert C. Martin (Uncle Bob) as the keynote speaker.
Introducing Clean Coding and Architecture
- The speaker introduces the topic of clean coding and architecture.
- Robert C. Martin (Uncle Bob) is introduced as the keynote speaker for this event.
Clean Coding and Clean Architecture
Uncle Bob discusses the importance of clean coding and architecture in software development.
Importance of Clean Coding
- Uncle Bob emphasizes the importance of clean coding in software development.
- He explains that clean code is easy to read, understand, and modify.
- He notes that writing clean code requires discipline, but it pays off in the long run.
Importance of Clean Architecture
- Uncle Bob also stresses the importance of clean architecture in software development.
- He explains that a good architecture allows for flexibility and adaptability over time.
- He notes that a good architecture should be independent of frameworks, databases, or other external factors.
Passion for Programming
Uncle Bob shares his passion for programming with the audience.
Passion for Programming
- Uncle Bob expresses his passion for programming.
- He notes that programmers share a unique ability to communicate about their work in ways others cannot.
- He emphasizes that regardless of age, gender, race or any other factor, if you are a programmer you are part of his tribe.
Aristarchus' Technique for Measuring Distance to Sun
Uncle Bob describes Aristarchus' technique for measuring distance to Sun using angles between Earth-Moon-Sun triangle.
Measuring Distance to Sun
- Uncle Bob describes Aristarchus' technique for measuring distance to Sun using angles between Earth-Moon-Sun triangle.
- He explains that if you can measure the angle between Earth-Moon line and Moon-Sun line, you can calculate the distance to Sun.
- He notes that Aristarchus' initial measurements were off by a factor of 10 due to lack of instrumentation at the time.
Measuring the Distance to the Moon and Sun
This section discusses how Aristarchus calculated the distance to the moon and sun by measuring the time it takes for the moon to pass through Earth's shadow, and how Eratosthenes calculated the size of Earth.
Calculating Distance to Moon and Sun
- Aristarchus measured that it takes about three hours for the moon to pass through Earth's shadow.
- The moon takes close to 28 days to make a complete circuit of Earth.
- The ratio between Earth's diameter and the circumference of the moon's orbit can be used to calculate the radius of that circle and get the distance to the moon in earth diameters.
- To calculate this, we need to know Earth's size. Eratosthenes calculated this about 30 years later by measuring shadows cast by sticks in Alexandria, Egypt, and Memphis at noon on summer solstice.
Importance of Human Reasoning
- Aristarchus' calculation was off by a factor of 10 but was still impressive given he had no instrumentation.
- For 2,000 years, his measurement was considered as one of best measurements we had until it was beaten in 1630.
- This shows us that human reasoning is powerful when studying situations long enough and gathering enough data.
Clean Code
This section discusses what clean code is, why it is important, and how we can make our code good enough for a code review.
Valid Measurement of Code Quality
- The only valid measurement of code quality is WTFs (What The F*** moments) per minute coming out from behind a door where a code review is taking place.
- Good code has fewer WTF moments than bad code.
Importance of Clean Code
- We have several dozen computers on our bodies and thousands in the room, so it is important to write clean code that can be easily understood by others.
- Clean code helps peers understand what our code does and prevents them from tearing their hair out trying to figure it out.
Making Our Code Good Enough for a Code Review
- The goal is to make our code good enough to survive a code review.
- Over the next several hours, we will learn how to write clean code that meets this goal.
The Importance of Software in Society
In this section, the speaker emphasizes the importance of software in modern society and how it affects our daily lives.
The Role of Software in Daily Life
- Software is an integral part of modern society and is used in almost every aspect of our daily lives.
- It is impossible to go more than 60 seconds without interacting with a software system.
- A modern car has over 100 million lines of code executing, most of which are in the entertainment and GPS systems.
- There are if statements that decide whether or not to stop the car when you push on the brake.
The Consequences of Software Failure
- Failures in software have caused dozens of people to die in automobile accidents.
- Software failures can also result in massive financial losses, such as the case with Night Capital losing $450 million due to one mistake.
- Our society runs on software, and there is nothing we can do without it. However, many people do not realize just how dependent we are on it.
The Responsibility of Programmers
- Programmers write the rules that run in machines that govern everything.
- Society does not yet fully understand just how dependent it has become on programmers and their code.
- When some poor programmer does one dumb thing and kills 10,000 people at a shop, society will wake up to this fact.
Ethics in Software Development
In this section, the speaker discusses the importance of establishing ethics in software development to avoid regulation and legislation by politicians. He emphasizes that programmers need to adopt a set of standards and moral values to uphold their profession.
Importance of Ethics in Software Development
- The lack of ethics in software development can lead to regulation and legislation by politicians.
- To avoid this, programmers need to establish a set of standards and moral values that they adhere to.
- Having a stated set of ethics will help programmers respond when questioned about unethical practices.
- If programmers do not establish their own ethical standards, politicians will create regulations for them.
Cleanliness of Code
- One important value that software developers should hold dear is the cleanliness of code.
- Good code matters because it leads to faster programming times and easier maintenance.
- Messy code can slow down programming times and make it difficult for teams to work together effectively.
The Real World for Managers
In this section, the speaker discusses what managers should do when their team cannot deliver features on time.
Adding More People Does Not Make You Go Faster
- Doubling the staff does not make you go faster.
- Adding new people to a team slows it down because they suck the life out of the old people.
- New people are trained by the old code, which makes the problem worse.
- No matter how many people you add to a team, productivity will not rise.
Why Programmers Are Slow
In this section, the speaker explains why programmers are slow and how they can improve their productivity.
Making a Mess
- Programmers are slow because they make messes.
- The desire to go fast drives programmers to make messes.
- Once code works, it needs to be cleaned up.
- Human beings do not think in nice straight lines; we cobble things together with wire and scotch tape.
Clean Code
- Nobody wants to put effort into cleaning up code because they think they're done when it works.
- You're done when it's right.
- The only way to go fast is to do a good job.
What is Clean Code?
In this section, the speaker discusses what clean code means and how it has been a concept in software development for over 40 years.
The Definition of Clean Code
- Clean code is elegant and efficient.
- A function should do one thing well.
- One thing can be measured objectively.
The Importance of Clean Code
- Adhering to objective measures transforms the structure of your code remarkably.
- Clean code reads like well-written prose.
- Clean code always looks like it was written by someone who cares.
Examples of Clean Code
- Each routine you read turns out to be pretty much what you expected.
Writing Code for Others
In this section, the speaker emphasizes that writing code that other people can maintain and use is more important than writing code that just works.
The Importance of Communication
- Your job is not just to get code to work, but also to write code that other people can maintain and use.
- It's more important to communicate with your peers using a programming language than it is to communicate with the computer because if you do that well somebody will make it work.
Ward Cunningham on Clean Code
In this section, the speaker talks about Ward Cunningham's definition of clean code.
Ward Cunningham's Definition
- You know you're working on clean code when each routine you read turns out to be pretty much what you expected.
- Clean code is no surprises, no WTF.
Introduction
The speaker introduces the code and explains what it does.
Code Overview
- The code is written in Java.
- It generates HTML for a testing tool called Fitness.
- The function name, "testableHTML," is not descriptive enough.
- The purpose of the code is to append setups and tear downs to a test page.
Understanding the Code
The speaker walks through the code and explains how it works.
Code Walkthrough
- The first line of the code creates a wiki page object.
- Every line of a function should be at the same level of abstraction, but this code oscillates between high and low levels.
- The "testableHTML" function appends setups and tear downs to a test page.
- There is a fundamental rule for functions that every line should be one level below the name. This rule is violated in this code.
Mistakes Made by the Author
The speaker discusses mistakes made by the author when writing the code.
Mistakes Made
- The author created up-and-down abstraction levels while writing the code, which makes it difficult for readers to understand.
- After getting part of the code working, the author copied and pasted it without fixing it.
Refactoring Code for Readability
In this section, the speaker discusses how he refactored a piece of code to make it more readable and easier to understand. He explains the importance of using explanatory variables and constructing well-written prose from the names of variables and functions.
Refactoring Render Page Function
- The original function was completely surrounded by an if statement that was hard to see in the original code.
- The if statement uses a variable called "is test page," which is defined right above it. This is called an explanatory variable, and its only purpose is to explain what its contents are.
- Constructing well-written prose from the names of variables and functions makes code easier to read.
- The final refactoring of this function resulted in a much smaller, more polite function that allows readers to escape early if they're not interested in reading further.
Writing Polite Code
- Writing polite code means allowing readers to exit early if they're not interested in reading further. This can be achieved by structuring code like a well-written article or paper, with a title, abstract, and increasing levels of detail as you read down.
- The final refactored version of the render page function is polite because it allows readers to exit early if they're not interested in reading further. It's also much smaller than the original version, making it easier to understand at a high level.
The First Rule of Functions
In this section, the speaker discusses the importance of making functions small and defines the first rule of functions.
The Proper Size for a Function
- A function should be small.
- The function should do one thing.
- If you cannot meaningfully extract another function from it, then that original function did more than one thing.
- All functions in the system should be exploded down into a tree of tiny little functions optimally extracted maximally extracted.
Extract Method
In this section, the speaker talks about IntelliJ's refactoring menu and how to use extract method.
Defining One Thing a Function Does
- A function does one thing if you cannot meaningfully extract another function from it.
- You must extract and extract until you cannot extract any more.
- Naming those functions will create a semantic tree of functions that you can follow by name.
Large Functions
In this section, the speaker discusses large functions and their impact on productivity.
Recognizing Large Functions
- When people get very used to a large function or module they have been working in for months, there is some part of your brain that relaxes because you see that shape.
Extract Until You Can't Anymore
In this section, the speaker talks about how to make code objective by extracting until you cannot extract anymore. He uses an example of a 3000 line function written in C and explains how to identify classes that hide inside big functions.
Extracting Variables
- The speaker talks about a 3000 line function written in C that does more than one thing.
- To make code objective, he suggests extracting variables until you cannot extract anymore.
- If there are local variables in the C function, such as int I and J, manipulate them with an indent.
- When trying to extract the indent using the IDE's extract method function, it will return an error message because it changes two variables.
Extracting Functions
- To solve the issue of changing two variables, make them global so that they can be extracted into another function.
- By continuing to extract and identify classes that hide inside big functions, you can find the true object-oriented structure of the system being designed.
The Invention of Java
In this section, the speaker talks about James Gosling's invention of Java and why he created it.
James Gosling's Invention
- James Gosling invented Java while working at Sun Microsystems in 1992 or 1993.
- He was supposed to write code for a cable television set-top box in C++, but he hated C++ and decided to create his own language called Oak (later renamed Java).
- The language was initially thrown in the garbage bin after the project was completed, but Sun Microsystems later realized that giving programmers a new language could help sell their hardware.
- Programmers are the ones who make buying decisions, so Sun Microsystems decided to give them the language of the internet.
The Origin of C-Sharp
In this section, the speaker talks about the origin of C-Sharp and how it was foisted upon the programming community as a marketing tool.
Java and Visual J++
- C-Sharp came from Java.
- Microsoft took Java and created Visual J++.
- Sun Microsystems objected to Microsoft's use of Java in Visual J++.
Extracting Code
- Indenting should be limited when extracting code.
- Functions should be small, usually 3 to 5 lines long.
- If statements can be extracted into functions with descriptive names.
Function Arguments
- Functions should have no more than three arguments.
- Passing six or more arguments into a function is not recommended.
- Boolean arguments are annoying and should not be passed into functions.
Reading Code: Double Takes and Switch Statements
In this section, the speaker talks about how reading code can be difficult when there are unexpected arguments or syntax. They introduce the concept of a "double take" and explain why it's important to avoid them in code. The speaker also discusses switch statements and why they can be problematic.
Double Takes
- When reading code, sometimes you come across a line that puzzles you.
- This is called a double take, where you have to stop your reading and go back to understand what's going on.
- Double takes are caused by rude code that forces you to stop your momentum while reading.
- To avoid double takes, use the principle of least surprise and make sure your code is not surprising.
Switch Statements
- Switch statements are problematic because they break easily when new types are added.
- Every time you do anything with a shape, you'll need a switch statement for it.
- Adding a new type of shape requires finding all switch statements in the system and modifying them accordingly.
- This process is fragile and causes difficulties when trying to add new types of shapes.
Polymorphism as Solution
- Polymorphism is the solution to avoiding switch statements in code.
- By using base classes and subclasses for different shapes, functions can be put into derivatives instead of having multiple switch statements throughout the system.
- Adding a new shape only requires adding a new file/class/subclass without changing anything else in the system. This is called the open closed principle.
Switch Statements and Dependency Management
In this section, the speaker discusses switch statements and their impact on dependency management.
Switch Statements and Dependencies
- The speaker explains that they do not like switch statements because they create a lot of dependencies.
- A switch statement with multiple cases is shown as an example of how it can lead to many source code dependencies.
- If a change is made to a switch statement, everything to the left of it must be redeployed because it all gets recompiled.
- The speaker explains that jar files are used for independently deploying chunks of a system. They allow for modules to be deployed separately from each other.
Jar Files and Dynamically Linked Libraries
In this section, the speaker discusses jar files and dynamically linked libraries.
Jar Files and DLLs
- The speaker explains that jar files are used for runtime linking loading. They allow external variables to be linked at runtime.
- The purpose of a jar file is to independently deploy chunks of a system so that changes can be made without having to redeploy everything.
- The goal is to isolate the GUI from the business rules so that changes made to one do not break the other.
- Independently deploying modules allows for changes in business requirements without affecting other parts of the system.
Why We Don't Like Switch Statements
In this section, the speaker provides more reasons why they don't like switch statements.
Reasons for Disliking Switch Statements
- Switch statements create a lot of dependencies and make it difficult to independently deploy modules.
- The speaker emphasizes the importance of being careful not to throw switch statements all over inside the system.
Managing Pairs of Functions
In this section, the speaker talks about side effect functions and how they come in pairs. He explains that managing pairs of functions is difficult and that garbage collection is a crutch for programmers. The speaker also discusses how lambdas can make things easier.
Side Effect Functions
- A side effect function changes the state of the system.
- Side effect functions come in pairs, such as open and close or new and delete.
- Garbage collection is a hack to allow programmers to forget about managing pairs of functions.
Controlling Pairs of Functions
- Pairs of functions must be called in the right order to avoid logical inconsistencies.
- Debugging systems with logical inconsistencies can take days or even longer.
- Lambdas can make it easier to manage pairs of functions by allowing for safer code.
Making Open Safe
- Using lambdas, open can be made safer by passing in a lambda called process.
Dealing with Side Effects
In this section, the speaker discusses how to deal with side effects in programming.
Using Lambdas and Command Objects
- To handle side effects, pass a lambda into your system.
- If lambdas are not available in your language, use a command object instead.
- Follow the convention of command and query separation: functions that return void should have a side-effect, while functions that return a value should not.
Prefer Exceptions Over Error Codes
- Use exceptions instead of returning error codes.
- When writing a try block, only include the try block in the function. Avoid having prefix or suffix code in the function.
- Never nest try-catch blocks.
The DRI Principle and Code Duplication
In this section, the speaker discusses code duplication and how to avoid it using the DRI principle.
The DRI Principle
- The DRI principle stands for "Don't Repeat Yourself."
- Avoid duplicated code by moving it into functions.
- If loops are duplicated throughout different parts of the system, use lambdas to eliminate duplication.
Conclusion
- Sloppy code is bad practice. Use good coding practices such as avoiding duplication and following conventions like command and query separation.
Structured Programming
This section discusses the history of structured programming and its inventor, Edsger Dijkstra.
Edsger Dijkstra: The First Programmer in the Netherlands
- Edsger Dijkstra was the first programmer in the Netherlands and one of the first programmers in the world.
- He survived Nazi occupation during World War II and went on to study software in the 1950s.
- He fell in love with computers after seeing the very first computer in the Netherlands.
The Invention of Structured Programming
- Structured programming was invented by Edsger Dijkstra.
- His goal was to turn software into mathematics by creating a set of postulates and then a set of theorems like Euclidian geometry.
- His vision was that people would write applications by adopting well-proven theorems and then writing little lemmas to adapt them.
Go-To Statements Considered Harmful
- In 1968, Dijkstra wrote a letter to editors stating that go-to statements were considered harmful.
- During those days, go-to statements were used for everything. If statements had go-tos within them, while loops didn't exist yet, so go-tos were used all over the place.
- This caused an uproar in the software community as people wrote scathing letters to editors either supporting or opposing his views.
Why Go-To Statements Were Harmful
- Dijkstra wanted to prove software correct using mathematical proofs. He discovered that certain algorithms could not be proven correct because they had unrestrained go-tos.
- These algorithms were those that had no rational way to prove them correct.
The Importance of Testing Software
In this section, the speaker discusses how software can be proven correct and the importance of testing software.
Dijkstra's Vision
- Dijkstra believed that software could be proven correct through a mathematical superstructure like Euclidian geometry.
- However, we do not have that kind of mathematical superstructure for software. Instead, we rely on science which is a set of conjectures and hypotheses that cannot be proven correct.
- Despite this, we still risk our lives every day on things that are not proven correct such as airplanes.
Treating Software Like Science
- We treat software like a science by writing tests to demonstrate that it is not incorrect.
- However, many people do not write tests for their code which raises an ethical issue.
- The speaker questions why someone would write code and then not test it.
Overall, the speaker emphasizes the importance of testing software to ensure its reliability and safety.