For me, good design means that when I make a change, it’s as if the entire program was crafted in anticipation of it. I can solve a task with just a few choice function calls that slot in perfectly, leaving not the slightest ripple on the placid surface of the code.
That sounds pretty, but it’s not exactly actionable. “Just write your code so that changes don’t disturb its placid surface.” Right.
Let me break that down a bit. The first key piece is that architecture is about change. Someone has to be modifying the codebase. If no one is touching the code — whether because it’s perfect and complete or so wretched no one will sully their text editor with it — its design is irrelevant. The measure of a design is how easily it accommodates changes. With no changes, it’s a runner who never leaves the starting line.
I like this a lot. "Accommodation to changes" accounts for readability, organization, testing, and a lot of other things bundled in.
Coding only for the problem at hand right now: Bad.
Coding for every possible future need: Bad.
Coding to solve current problems while being accommodating towards future modifications: Good.
This. There are few things that I feel like are as satisfying as being like "Oh crap, I need to make sure it can handle ABC" or "I need to change it for this new thing" and realizing you wrote it such that sure, it does need to change somewhere, but it has that capability for change without things getting messy. The opposite of having to add more and more logic to handle cases.
Key goal of software architecture: minimize the amount of knowledge you need to have in-cranium before you can make progress.
Get problem -> Learn Code -> Code Solution -> Clean up
Change to one piece of code doesn’t necessitate a change to another. We obviously need to change something, but the less coupling we have, the less that change ripples throughout the rest of the game.
Good architecture makes a huge difference in productivity. It’s hard to overstate how profound an effect it can have.
Good architecture takes real effort and discipline. Every time you make a change or implement a feature, you have to work hard to integrate it gracefully into the rest of the program. You have to take great care to both organize the code well and keep it organized throughout the thousands of little changes that make up a development cycle.
You have to think about which parts of the program should be decoupled and introduce abstractions at those points.
Writing well-architected code takes careful thought, and that translates to time. Maintaining a good architecture over the life of a project takes a lot of effort. You have to treat your codebase like a good camper does their campsite: always try to leave it a little better than you found it.
Design requires a lot of experimentation and exploration. Especially early on, it’s common to write code that you know you’ll throw away.
If there is any method that eases these constraints, it’s simplicity. In my code today, I try very hard to write the cleanest, most direct solution to the problem. The kind of code where after you read it, you understand exactly what it does and can’t imagine any other possible solution.
The most effective and certain method, however, is the code review. However, it is also very time consuming. It requires that one or more developers restrain from being (in the eyes of the customer) productive and give their attention to someone else’s code. Provided that the developer has a high standard of quality, it will definitely improve total quality of the code. Of course, there is the concept of pair programming, which could be seen as a form of continuous code reviewing. Highly effective, and can improve the skills of both developers.
These tools and processes can be very useful, but their overall efficiency depends on one thing: quality awareness within your development team. I’ll explain what I mean with “quality awareness”. It is the ability of developers to recognize code smells or failure to use design patterns at locations where they would typically be applied. This awareness it typically raises as developers gain more experience, but we’d typically like to help fate a little hand.
It's subjective and variable depending on the circumstances:
Skill and experience of the author (I tend to gloss over PRs by people that do consistently good work)
Difficulty/importance of changes
ROI for additional time spent
etc.
There's an implicit assumption that you can't spend "forever" on a piece of code; at some point it's got to be "good enough" so you can move on. It's also subject to diminishing returns.
To me, high quality code means less lines of code, but has more power. That power might be a useful abstraction, or it's just a useful algorithm to solve repeatable problems.
And if you want more quality of your code, make it easy to test, the easier to test a code block, the more quality that code block has.
And if you want even more quality of your code, make it fast. If your language couldn't make it fast enough, change the language.
"Make it fast" means you should use better algorithms or data structures to solve the problem. Because as you know, to solve one problem, there're many ways to do it. So it's also called optimization of the code to use better libraries, for example.
Personally, the more that code reads like prose, the higher quality it is. High quality code tells you the story about the business solution that it is implementing.
My favorite code is that which reveals to me something about the business that I did not previously know. Plus, like businesses, it’s written in a way to accommodate the future only when the future arrives.
Maintainable means it is easy to understand, sensibly organized, it is painless to make modifications that should be expected (client wants to add another type of report), and as easy as possible to make changes that aren't (client wants a totally new feature)
Efficient means the code uses as few resources as possible to accomplish its job, so that it is as fast and scalable as possible.
If code is like cake, then good code is like cake that you can enjoy eating and that will not leave you with stomach aches later on.
Note that 'doing what it is supposed to' is not an attribute of good code any more than 'being edible' is an attribute of good cake. That's just a fundamental real-world requirement for when someone asks you to write code / bake a cake. It doesn't have anything to do with either of those being good.
In the case of cake, yes. How that translates to code is that code is also experienced as being good by how you interact with it later, i.e. modifying it in any way (rather than just looking at it).
There are two parts to learning craftsmanship: knowledge and work. You must gain the knowledge of principles, patterns, practices and heuristics that a craftsman knows, and you must also grind that knowledge into your eyes and gut by working hard and practicing.
Learning to write clean code is hard work. It requires more than just the knowledge of principles and patterns. You must sweat over it. You must practice it yourself, and watch yourself fail. You must watch others practice it and fail, You must see them stumble and retrace their steps.
In my opinion "good" code is the one that is disposable. Is a codebase where you can identify with confidence the parts that need to be changed or removed in order to make a new feature or meet a new requirement.
You won't necessarily recognize it when you see it or when you write it for the first time, but you'll know when the times comes and you have to mantain it.
Top comments (58)
There's a really great chapter about this in "Game Programming Patterns" by Robert Nystrom:
Be sure to read the whole thing!
I like this a lot. "Accommodation to changes" accounts for readability, organization, testing, and a lot of other things bundled in.
Coding only for the problem at hand right now: Bad.
Coding for every possible future need: Bad.
Coding to solve current problems while being accommodating towards future modifications: Good.
I have seen this scenario a few times and it obviously delays the whole project because requirements keep changing and so does the code.
This. There are few things that I feel like are as satisfying as being like "Oh crap, I need to make sure it can handle ABC" or "I need to change it for this new thing" and realizing you wrote it such that sure, it does need to change somewhere, but it has that capability for change without things getting messy. The opposite of having to add more and more logic to handle cases.
A few points taken from Robert Nystrom are:
High quality code is the one that has a low wtf/hour ratio
😅
Exactly so, although I think that per minute would be a really big number hahaha.
This is the one and only true metric for good code quality. It never fails.
An interesting point from Gridshore on this:
Definition:
Attributes:
It's like art vs obscenity; I know it when I see it.
So, what would be the optimal time? Or is it somehow subjective depending on the circumstances?
It's subjective and variable depending on the circumstances:
There's an implicit assumption that you can't spend "forever" on a piece of code; at some point it's got to be "good enough" so you can move on. It's also subject to diminishing returns.
To me, high quality code means less lines of code, but has more power. That power might be a useful abstraction, or it's just a useful algorithm to solve repeatable problems.
And if you want more quality of your code, make it easy to test, the easier to test a code block, the more quality that code block has.
And if you want even more quality of your code, make it fast. If your language couldn't make it fast enough, change the language.
How can you make your code faster?
"Make it fast" means you should use better algorithms or data structures to solve the problem. Because as you know, to solve one problem, there're many ways to do it. So it's also called optimization of the code to use better libraries, for example.
Personally, the more that code reads like prose, the higher quality it is. High quality code tells you the story about the business solution that it is implementing.
My favorite code is that which reveals to me something about the business that I did not previously know. Plus, like businesses, it’s written in a way to accommodate the future only when the future arrives.
Maintainable and efficient.
Maintainable means it is easy to understand, sensibly organized, it is painless to make modifications that should be expected (client wants to add another type of report), and as easy as possible to make changes that aren't (client wants a totally new feature)
Efficient means the code uses as few resources as possible to accomplish its job, so that it is as fast and scalable as possible.
I'm going to use the #likeimfive approach here.
If code is like cake, then good code is like cake that you can enjoy eating and that will not leave you with stomach aches later on.
Note that 'doing what it is supposed to' is not an attribute of good code any more than 'being edible' is an attribute of good cake. That's just a fundamental real-world requirement for when someone asks you to write code / bake a cake. It doesn't have anything to do with either of those being good.
Just to highlight.. so you mean cake is considered good based on the experience of eating it.
In the case of cake, yes. How that translates to code is that code is also experienced as being good by how you interact with it later, i.e. modifying it in any way (rather than just looking at it).
Uncle Bob says:
That is good advice for a beginner!
In my opinion "good" code is the one that is disposable. Is a codebase where you can identify with confidence the parts that need to be changed or removed in order to make a new feature or meet a new requirement.
You won't necessarily recognize it when you see it or when you write it for the first time, but you'll know when the times comes and you have to mantain it.
My personal definition is very subjective: A code is of high quality if
Some comments may only be visible to logged-in visitors. Sign in to view all comments.