Beautiful is better than ugly. Explicit is better than implicit. Simple is better than complex. Complex is better than complicated. Flat is better than nested. Sparse is better than dense. Readability counts. Special cases aren't special enough to break the rules. Although practicality beats purity. Errors should never pass silently. Unless explicitly silenced. In the face of ambiguity, refuse the temptation to guess. There should be one-- and preferably only one --obvious way to do it. Although that way may not be obvious at first unless you're Dutch. Now is better than never. Although never is often better than *right* now. If the implementation is hard to explain, it's a bad idea. If the implementation is easy to explain, it may be a good idea. Namespaces are one honking great idea -- let's do more of those!
from python-zen
Many (open source) hackers are proud if they achieve large amounts of code, because they believe the more lines of code they've written, the more progress they have made. The more progress they have made, the more skilled they are. This is simply a delusion.
Most hackers actually don't care much about code quality. Thus, if they get something working which seems to solve a problem, they stick with it. If this kind of software development is applied to the same source code throughout its entire life-cycle, we're left with large amounts of code, a totally screwed code structure, and a flawed system design. This is because of a lack of conceptual clarity and integrity in the development process.
Code complexity is the mother of bloated, hard to use, and totally inconsistent software. With complex code, problems are solved in suboptimal ways, valuable resources are endlessly tied up, performance slows to a halt, and vulnerabilities become a commonplace. The only solution is to scrap the entire project and rewrite it from scratch.
The bad news: quality rewrites rarely happen, because hackers are proud of large amounts of code. They think they understand the complexity in the code, thus there's no need to rewrite it. They think of themselves as masterminds, understanding what others can never hope to grasp. To these types, complex software is the ideal.
Ingenious ideas are simple. Ingenious software is simple. Simplicity is the heart of the Unix philosophy. The more code lines you have removed, the more progress you have made. As the number of lines of code in your software shrinks, the more skilled you have become and the less your software sucks.
from suckless-philosophy
Finally, I prefer minimum-length but maximum-information names, and then let the context fill in the rest. Globals, for instance, typically have little context when they are used, so their names need to be relatively evocative. Thus I say
maxphysaddr
(notMaximumPhysicalAddress
) for a global variable, butnp
notNodePointer
for a pointer locally defined and used. This is largely a matter of taste, but taste is relevant to clarity.
from pike-style
- Rule 1. You can't tell where a program is going to spend its time. Bottlenecks occur in surprising places, so don't try to second guess and put in a speed hack until you've proven that's where the bottleneck is.
- Rule 2. Measure. Don't tune for speed until you've measured, and even then don't unless one part of the code overwhelms the rest.
- Rule 3. Fancy algorithms are slow when n is small, and n is usually small. Fancy algorithms have big constants. Until you know that n is frequently going to be big, don't get fancy. (Even if n does get big, use Rule 2 first.)
- Rule 4. Fancy algorithms are buggier than simple ones, and they're much harder to implement. Use simple algorithms as well as simple data structures.
- Rule 5. Data dominates. If you've chosen the right data structures and organized things well, the algorithms will almost always be self-evident. Data structures, not algorithms, are central to programming.
- Premature optimization is the root of all evil.
- When in doubt, use brute force.
- Write stupid code that uses smart objects.
from pike-rules
Don't use the nouns "Object", "Manager", "Handler", or "Data" in class names. These words say nothing about the responsibility of the class, leading maintenance programmers to lump all kinds of irrelevant crap into the class. Think instead about what the class is actually supposed to do and name it after that.
from dont-name-classes
Global Variables Should Be Avoided When Unnecessary
from global-bad
- When in doubt, parameterize
- Bundle globals into structs/records/classes.
- Favor pure functions
- Encapsulate (loosely) at the level of namespaces/packages/modules.
- Don't be afraid of long functions.
from oop-bad t=34m58s
What people tend to create when they design object oriented programs are overly architected buildings, where the walls have been prematurely erected before we have really figured out what the needs of the floor plan are. And so what happens is down the line, turns out: "Oh wait! We need to get from this room over here to that room over there, but, oh wait! We have erected barriers in between." So we end up busting a bunch of holes through all the walls, like the Kool-Aid guy, and the resulting pattern is really not organized at all, it's just swiss cheese. We thought we were being disciplined, neatly modularizing all the state, but then the requirements changed, or we just didn't anticipate certain details of the implementation and we end up with a mess.
The lesson we should take from this is to be very careful about erecting barriers, about imposing structure. It's actually better to start out with a free-form absence of structure, rather then impose a structure that will likely turn out to not really fit our problem. Bad structure that doesn't really fit our problem not only makes it harder to implement the code in the first place, it hinders change, and it confuses anyone who looks at our code because it's implying one thing, but then what's really going on is another.
In the Object-oriented world, we have to think about all these graphs. We have to think about an inheritance hierarchy, we have to think about a composition graph, we have to think about data flows between the objects and also we're thinking about a call graph.
The liberating thing about procedural code is that there's just the call graph.
We also, of course, do have to think about how our data is structured, and how our data gets transformed throughout the course of the program, but the beauty of procedural code is that we can think about them totally independent of any notion of responsibilities. When looking at my data I can think just about my data. And when looking at my functions, I'm not thinking about all these self imposed barriers.
from oop-bad t=25m40s
// Long functions are good. // Sequential code is easy to read. // Write code that does something. // Alert names: manager, controller, handler
I think that long functions are good, which is controversial. Some computer science people teach that you should never have a function with more than five lines of code.
Sequential code is really easy to read. That's how we read books: From the top to the bottom. Reading a "Choose your own adventure"-book where you have to flip to page 57 to finish a sentence is much harder.
I like writing code that does something. People tend to write a lot of functions or things that handle other code. If a lot of your code is called like
SomethingManager
orSomethingController
orSomethingHandler
, you're probably not writing code that does something, you're writing code that handles other pieces of code. That's a warning flag. It's really hard for someone from the outside to know what that "handler" actually does, whereas if it's a functions that's assigned as "this functions does this thing", then it's much clearer what's going on.
paraphrased from how-i-c
Here is a sample of code using guard clauses ...
public Foo merge (Foo a, Foo b) { if (a == null) return b; if (b == null) return a; // complicated merge code goes here. }
Some style guides would have us write this with a single return as follows ...
public Foo merge (Foo a, Foo b) { Foo result; if (a != null) { if (b != null) { // complicated merge code goes here. } else { result = a; } } else { result = b; } return result; }
from guard-clause
- Simplicity - the design must be simple, both in implementation and interface. It is more important for the implementation to be simple than the interface. Simplicity is the most important consideration in a design.
- Correctness - the design must be correct in all observable aspects. It is slightly better to be simple than correct.
- Consistency - the design must not be overly inconsistent. Consistency can be sacrificed for simplicity in some cases, but it is better to drop those parts of the design that deal with less common circumstances than to introduce either implementational complexity or inconsistency.
- Completeness - the design must cover as many important situations as is practical. All reasonably expected cases should be covered. Completeness can be sacrificed in favor of any other quality. In fact, completeness must sacrificed whenever implementation simplicity is jeopardized. Consistency can be sacrificed to achieve completeness if simplicity is retained; especially worthless is consistency of interface.
from worse-is-better
Use tabs for indentation and spaces for alignment.
from suckless-style
Tabs are 8 characters, and thus indentations are also 8 characters. There are heretic movements that try to make indentations 4 (or even 2!) characters deep, and that is akin to trying to define the value of PI to be 3.
Rationale: The whole idea behind indentation is to clearly define where a block of control starts and ends. Especially when you've been looking at your screen for 20 straight hours, you'll find it a lot easier to see how the indentation works if you have large indentations.
Now, some people will claim that having 8-character indentations makes the code move too far to the right, and makes it hard to read on a 80-character terminal screen. The answer to that is that if you need more than 3 levels of indentation, you're screwed anyway, and should fix your program.
In short, 8-char indents make things easier to read, and have the added benefit of warning you when you're nesting your functions too deep. Heed that warning.
from kernel-style
Keep lines to reasonable length (max 79 characters).
from suckless-style
- Quality matters. We all know that if you don't focus on quality it will come back to bite you.
- Making even small changes will become increasingly difficult. Eric Evans in Domain-Driven Design: "When complexity gets out of hand, developers can no longer understand the software well enough to change or extend it easily and safely." Exhibit A showed Facebook needing a huge staff to keep up their momentum maintaining a big ball of mud.
- Releases will break things, because you don't understand the relationships well enough to predict the impact of your changes. Exhibit C showed just that.
Next time management or clients try to convince you to move faster and throw quality under the bus, you can say sure, that will work, as long as you can hire 429 engineers to work on our iOS app.
from facebook-quality