Never ask permission to refactor. Never ask permission to write tests. You do these things because you KNOW they are the best way to go fast.
When you ask permission, you are asking someone else to take responsibility for your actions.
Agile is not a way to go fast. It is a way to know where you are going.
Agile is does not increase productivity. Agile increases manageability.
Agile does not guarantee you’ll get there on time. Agile destroys the hope that you might, when you won’t.
The word “refactoring” should never appear in a schedule. Refactoring is not a story or a backlog item. Refactoring is not a scheduled task. Refactoring is immediate and continuous. It’s like washing your hands in the bathroom. You always do it.
Most programmers want to write good code; but believe that their employers don’t want good code. They are wrong.
Most employers want the benefits of good code; but don’t know that good code provides those benefits.
We do. So, we should write good code.
It is more important for code to be changeable than that it work. Code that does not work, but that is easy to change, can be made to work with minimum effort. Code that works but that is hard to change will soon not work and be hard to get working again.
One of the most important qualities of a professional programmer is the courage to be brutally honest about estimates and dates; and to be unafraid to say “No” to impassioned demands that are counter to reality.
When you read code, the race, religion, politics, gender, and orientation of the author are irrelevant and invisible. The only thing you can tell about the author is their ability to write well organized code. Nothing else matters.
I have been using Test Driven Development for twenty years now. I am a faster, better, more confident programmer because of it. The code I write is very well tested. The tests give me confidence to refactor. The refactoring improves everything.
Programmers must never offer the option of bad code to managers who demand speed. Nobody goes faster when slogging through a mess. Messes slow everyone, and everything forever.
So you’re a programmer. Good. We need programmers. Have you read Knuth’s “Fundamental Algorithms”? If not, it’s the next book you should read. 40 years ago that book changed my life. Its power has not waned. Read and learn.
There is no trade-off of quality vs. speed in software. There never has been. Low quality means low speed. Always.
The only way to go fast is to go well.
Developers do not have to justify testing and refactoring to management; because those disciplines increase efficiency and productivity. Indeed, it is the lack of such disciplines that ought to require justification. I doubt any could truly be found.
Software Craftsmanship is not about glory and rockstar status. It’s not about being the overtime hero, or the last minute cowboy. Rather it is about discipline, professionalism, and the desire to constantly improve.
Agile isn’t dead, or old, or obsolete. Agile isn’t Scrum, or Less or Safe. Neither the organization, nor the team, nor the product are Agile.
Agile is not a process.
Agile is a software development discipline for small to medium sized teams.
We write tests first so that we write tests period.
We write tests first so that our code will be testable.
We write tests first so that we know what code we should write.
We write tests first because we always do the most important things first.
Unit tests are written by programmers for programmers. Acceptance tests are specified by customers for customers. Integration tests are written by architects for architects.
You cannot refactor without a comprehensive suite of tests that you trust with your life. If you have that suite, refactoring is always easy and free of risk. A moment of refactoring becomes a trivial thing rather than a huge risk.
Agile is not about going faster. Agile is about destroying hope. The data produced by a good agile team provides a cold dose of reality to the managers — in time for them to — manage.
If you like Java, program in Java. If you like C#, program in C#. If you like Ruby, Swift, Dart, Elixr, Elm, C++, Python, or even C; by all means use those languages.
But whatever you do, learn Clojure, and learn it well.
Agile is a small technique for small to medium sized software teams to build small to medium sized software projects.
Agile is not for big organizations, it is for smallish software teams.
Your boss does not need to know that you are using Agile.
Dogmatic adherence to a practice like TDD is deeply foolish.
Dogmatic avoidance of a practice like TDD is equally foolish.
Learn the practice. Learn it well. Become skilled at it. Then apply it with your best judgement.
Programmers. Read the seminal works!
Structured Programming: Dijkstra, Dahl, & Hoare.
Structured Analysis and System Specification: DeMarco.
The Structure and Interpretation of Computer Programs: Abelson and Sussman.
Design Patterns: Gamma, et. al.
The machines are already writing the code. Those machines are called compilers.
We, programmers, simply specify the solution in sufficient detail so that the machines can write the code.
Specifying the solution in sufficient detail will _always_ be a human endeavor.
“There is a new far-left fascism that demands absolute allegiance. If you do not speak its language, perform its rituals, recite its mantras, and follow its commandments, then you will be censored, banished, blacklisted, persecuted, and punished”
Despite all the excuses, complaints, and reasons. The fact remains that as professional programmers we have an absolute obligation to provide management with honest estimates, no matter how disappointing they are. This is a precondition of professionalism.
TDD:
Write no production code without a failing test.
Stop writing that test as soon as it fails, or fails to compile.
Stop writing production code as soon as the failing test passes.
Refactor both and then repeat.
Cycle time: ~10-60 seconds.
Functional programming is not esoteric, theoretical, academic, obtuse, inefficient, or inaccessible. It is simple, obvious, approachable, and elegant.
Embrace it as part of your regular programming toolkit. Combine it with OO and structure.
Language is secondary.
Never blame your employer for things that are your responsibility. If the code is a mess, it’s not the employer’s fault, it’s the programmers’ fault. Learn to negotiate features. Never negotiate workmanship. The only way to go fast is to go well.
I have long opposed the cancel culture. I find the behavior to be despicable. Debating opinions is good. Getting people fired, ostracized, disinvited, deplatformed, and banished for such debate is, frankly, evil.
Q: Does good code take longer to write than bad code?
A: No, we just think it does. So we write bad code in the mistaken belief that it helps us go faster. And so we go slow.
If we wrote good code, we’d be going faster. Probably a lot faster.
Musk cut twitter staff by 80% and everything seems to be running fine, if not better. Many other tech companies have noticed and are contemplating emulation.
Every programmer should acquire a deep understanding of functional programming.
Every programmer should acquire a deep understanding of object-oriented programming.
Every programmer should acquire a deep understanding of structured programming.
Are you afraid of LISP (clojure)? Don’t like all the parentheses? Here, I’ll teach you LISP.
A function call in Java: f(x);
A function call in LISP (f x)
Now you know LISP.
Seriously.
Advocates of a certain language or a certain paradigm sometimes claim that adherence automatically yields clean code. Sadly, this is never true. You can make a mess in any language or paradigm. Only discipline, care, and attention to detail can stave off the mess.
Software is more like science than mathematics. Mathematical expressions are provable, scientific theories are merely demonstrable. Math is deductive. Science is empirical.
Software is empirical. We demonstrate, but do not prove, correctness.
TDD does not take extra time. Writing tests _first_ is not overhead because they force you to think through the problem and partition it properly. You’d have to do that thinking anyway.
Testing after the fact IS overhead because you did all that thinking already.
50 years ago I programmed In assembler, it was great.
40 y/a I switched to C, it was great.
30 y/a I switched to C++, it was great.
20 y/a I switched to Java, it was great.
15 y/a I switched to Ruby, it was great.
10 y/a I switched to Clojure.
I doubt I’ll switch again.
Standup meetings are fine for teams who aren’t as deeply collaborative as they could be. But for teams who spend much of their days pairing, mobbing, and otherwise working closely together, standup meetings are probably redundant. YMMV.
Code that expresses its intent does not require comments.
Code is not a perfectly expressive medium, so some comments will be necessary. However minimizing comments, by working hard to make the code more expressive, is a worthy goal.
My name is Robert Martin. Folks started calling me Uncle Bob in 1989.
I wrote my first code in 1964 at the age of 12. So I’ve been a programmer for over half a century.
Programmers are my people, regardless of race, creed, or gender.
Integration tests do not test business rules. Those rules have already beeen tested, once by programmer (unit) tests, and again by customer (acceptance) tests.
Integration tests test the plumbing and choreography of the components.
One of the main complaints people seem to have about the Clean Code book is my advice to keep functions very small. In Java I prefer functions that are ~4-6 lines long. (Thats a preference, not a demand).
Why? Because this forces me to make each function about _one thing_ and…
My bookshelf of honor just above my desk. These are the books I keep at the ready. Most referenced at the bottom. Most cherished at the top.
My other six book cabinets are not shown. <grin>.
The fundamental flaw with the cancel culture is that every attempt to silence ideas you don’t like is an admission that your ideas are too weak to stand against them.
If you have never written assembler, you owe it to yourself it give it a try. Take a weekend and do a deep dive. Pick a nice 6502 or 8085 or PDP8 emulator and write a few simple routines.
When you are done — all the magic will be gone. And you will KNOW.
Some folks say that Design Patterns are dead. How foolish. The Design Patterns book is one of the most important books published in our industry. The concepts within should be common rudimentary knowledge for all professional programmers.
When we learn to code we first learn procedures. They’re cool. Then we learn objects, they are cooler. Then we learn pure functions, they are coolest. But when we learn that they all flow together indistinguishably...That’s mastery.
Business objects are not defined by the data they encapsulate. Rather they are defined by the behaviors they afford. Your business object model is a behavioral model, not a data model. The less you couple that behavior model to a particular data model, the better.
This talk is one of the best I’ve seen in a decade. Watch every second. Get a pad and take notes! There is more meat in here than in a Brazilian Barbecue.
@ICooper
My twitter experience has vastly improved recently. More people can see my tweets. My subscriber count is rapidly increasing. And there seems to be much more substance, and much less hate and canceling, in my twitter circle.
Dear political parties. Please remember, software is hard. If you need it to be right, don’t skimp. And make sure you start very early. Software can’t be rushed. Next time find a competent, disciplined, and experienced team who diligently write tests.
I gave a talk yesterday in which I mentioned TDD. Afterwards I overheard someone say: “as soon as he said TDD I left”.
I don’t have high hopes for his career.
How do you make a function do one thing, do it well, do it only? You extract from it any sub functions within it until you can’t extract any more. And then you name those extracted functions really well.
In the last three decades we have irrevocably moved software into the very foundations of our civilization.
We programmers now bear an awe inducing responsibility. Civilization is now ours to improve or destroy.
What code of ethics ought we embrace?
OO is not a mindset, nor a philosophy, nor a technique for modeling "the real world". It is nothing more, nor less, than data structures manipulated by associated functions that are called indirectly through vectors. Deal with it.
As I’ve been saying for quite some time, it is architecturally risky to depend directly on frameworks and databases without some form of isolation protecting the app.
Parler just learned that the hard way.
The word “unit” in “unit-testing” usually just means “small”. Other than that, the word has no agreed definition. Some TDDers call them micro-tests to stress the smallness. I prefer “programmer tests” because, using TDD, they are written by programmers for programmers.
Math is inclusive. We prove things right. Science is exclusive. We prove things wrong.
Software is a science, our tests only prove our programs wrong.
We trust science because our test coverage is very high.
We can’t trust software with low test coverage.
You cannot fail a sprint. Sprints cannot fail.
The purpose of a sprint is to produce management data. A sprint that delivers zero stories has produced very important and useful data for managers.
Imperative, Functional, Object-Oriented. These are not adversaries. One is not better than the other. They are not mutually exclusive. You don’t have to select just one. A well designed system is all three at the same time.
After the first hundred lines or so of code are working -- stop!
Shuffle, shuffle, shuffle.
Aggressively refactor. Get it right before you start rapidly adding thousands of lines. You'll be glad you did.
Get the seed right, then let the crystal grow.
Software is the art of organizing ideas based on how those ideas will change with time. Stable ideas are decoupled and isolated. Unstable ideas are organized to depend upon the stable ideas.
I’m a big fan of Functional Programming; I think it’s great.
I’m a big fan of Object Oriented Programming; I think it’s great.
I’m a big fan of Procedural Programming; I think it’s great.
I’m a really big fan of using all three together at the same time. I think that should
I will be giving a free on-line talk on 21 September. This will be a new talk that no one has heard before; and it will not be recorded. If you’d like to attend, keep watch here and on my website () for details. It’ll be a good one.
A wise architect understands the unpredictability of software and therefore strives to keep as many options as possible open for as long as possible. Early unnecessary decisions often become long term impediments.
The difference between monoliths and services is not architectural it is a difference in deployment strategy. The decoupling of components is independent of deployment. A monolith deployment can be just as decoupled as a [micro]service deployment.
If you value making it work over making it right then you will make it work by doing the wrong thing. As that continues, and the code degrades, it becomes harder and harder to either make it work or make it right.
Tests are partitioned by threads of behavior, not by classes. Any given test will often involve many classes within the tested behavior.
You may partition your production code with classes; but should not force your tests to adhere to that structure.
Writing computer programs is, perhaps, the most difficult and challenging task that humans have ever attempted. It is no wonder that we aren’t very good at it.
The good news is that we are learning and getting better. Progress is slow but real.
Programmers are “detail managers”. It is our job to categorize and organize _all_ the lowest level details into a consistent and comprehensible whole. This requires mastery of a discipline of intense and prolonged focus.
Most programmers would benefit from developing a disciplined mindset. There may be no better way to acquire that mindset than learning to fly an airplane. Flying is safe, but intolerant of carelessness. Just like software.
Though we may try, and try, there are times when we cannot find a way to make the code express our intent; and so we resort, in the end, to a comment.
We acknowledge that each comment we write is finally due to our failure to express ourselves in code.