- Use descriptive and obvious names.
- Don't use abbreviations, use full English words.
player
is better thanplr
. - Name things as directly as possible.
wasCalled
is better thanhasBeenCalled
.notify
is better thandoNotification
. - Name booleans as if they are yes or no questions.
isFirstRun
is better thanfirstRun
. - Name functions using verb forms:
increment
is better thanplusOne
.unzip
is better thanfilesFromZip
. - Name event handlers to express when they run.
onClick
is better thanclick
. - Put statements and expressions in positive form.
isFlying
instead ofisNotFlying
.late
intead ofnotOnTime
.- Lead with positive conditionals. Avoid
if not something then ... else ... end
. - If we only care about the inverse of a variable, turn it into a positive name.
missingValue
instead ofnot hasValue
.
- Don't use abbreviations, use full English words.
- Function signatures should be obvious and straightforward at the call site.
- Avoid boolean arguments that change behavior. Boolean parameters are a code smell.
- Avoid
nil
arguments in function calls. Use an optional dictionary with options as the last (or only) parameter instead.
- Write less code.
- Be concise: less code means fewer places for bugs to hide which means fewer bugs.
- Make use of well-supported open source libraries when possible. Try to only spend your time on problems that don't already have solutions.
- Omit needless variables. Don't assign names to values you only use once.
- Write good abstractions. Don't repeat yourself.
- Colocate code related by feature rather than type. Keep related code together.
- This reduces tight coupling of distinct features.
- Each feature should manage its own state, and explicitly define methods to access and change that state.
- Keep code reusable and only tackle one job per function.
- Don't make one function that both loads and calculates data; allow already loaded data to be calculated, etc.
- Prefer functions with few or no side effects. This increases testability and re-usability and deters unexpected or unplanned behavior. Side effects are inevitable, but keep them explicitly defined and obvious.
- "If a feature is sometimes dangerous, and there is a better option, then always use the better option." –Douglas Crockford
- Avoid using features and patterns that consistently lead to mistakes. Humans are fallible, and you will make mistakes.
- Prefer stateful instances (e.g. classes) rather than excessive data structuring. In other words, if something can exist more than once, then it should be a "class".
- Avoid global state
- Prefer composition over inheritance: All class hierarchies are eventually wrong for new use cases. Ask "has a", "uses a", or "can do" instead of "is a".
- Ensure that anything that is created can also be cleaned up, especially event listeners and state that is associated with objects (instances/classes) that may not exist forever. Be tidy.
- Prefer getter and setter functions when providing public read and write access to privately managed state. You can't tell the future, and someday you might need to do some processing rather than setting a simple property.
- Prefer generic solutions which can be applied to many problems rather than specific solutions that can only be applied to one.
- When a generic solution is not ideal, then write parallel code for parallel concepts. When we repeat similar patterns for similar problems, anybody familiar with the pattern can quickly understand what the code does.
- Optimize code for reading, not for writing.
- Comments should answer "why", not "what".
- Be idiomatic. Follow convention. Use a style guide. When we write code consistently, it makes it easier for others and future you to parse and understand quickly.
- Code shouldn't be surprising. Overzealous use of meta-programming can lead to future mistakes because of wrong assumptions.
- Exceptions should be exceptional.
- Don't indoctrinate exceptions or errors as standard control flow. Not only does this make your code potentially surprising, but it also introduces complexity. Our standard control flow can handle those cases too.
- Return a success value or state monad. This forces the user to consider the failure case (no accidental uncaught errors!) and makes room for soft-fail situations.
- Reserve errors for when your program reaches an unrecoverable state. (e.g., unexpected situations or improper function usage)
- Code should be boring.
- Untestable code is bad code.
Last active
December 8, 2024 17:36
-
-
Save evaera/fee751d4e228dd262fe1174ba142a719 to your computer and use it in GitHub Desktop.
Best Practices for Clean Code
Try to only spend your time on problems that don't already have solutions.
This is such a tattoo-worthy quote imo.
Good summary!
Code should be boring.
What's that supposed to mean?
Code should be boring.
What's that supposed to mean?
I assume it means don't beautify your code with comments and exciting stuff. Just make it functional.
Try to only spend your time on problems that don't already have solutions.
Problem solving on your own is still useful, that is how you learn after all
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thank you for this! I appreciate it