Clean Code
Clear Names:
- What it is: Choosing descriptive and meaningful names for variables, functions, classes, etc.
- Why it’s important: Clear names help anyone reading the code quickly understand what it does, without needing extra explanations.
- How it’s done: Avoid abbreviations and generic names. Choose names that explain exactly what the variable or function is for, such as calculateTotal instead of calc.
Baby Steps:
- What it is: Breaking down work into small, manageable chunks.
- Why it’s important: Makes the code easier to understand and maintain. If something goes wrong, it’s easier to find and fix the bug.
- How it’s done: Write and test small chunks of code frequently. Refactor (improve) those chunks as needed.
Short Functions:
- What it is: Keeping functions small and focused on a single task.
- Why it’s important: Short functions are easier to read, understand, test, and reuse.
- How to: A good rule of thumb is that a function should do only one thing, and it should do it well. If a function is getting long, break it into smaller functions.
Use Comments Only When Necessary:
- What it is: Write comments only when the code cannot be self-explanatory.
- Why it matters: Comments can become outdated or misinterpreted. Clear, well-written code is better than obscure code with too many comments.
- How to: Write code that is easy to understand on its own. Use comments to explain the “why” of certain decisions, not the “how.”
Organization Matters:
- What it is: Keep code organized and structured in a logical way.
- Why it matters: Well-organized code is easier to navigate and understand.
- How to: Group related functions, maintain a logical order in function declarations, and follow a consistent pattern throughout the code.
Avoid Repetition:
- What it is: Don’t duplicate code unnecessarily.
- Why it matters: Duplicate code increases the chance of errors and makes maintenance more difficult.
- How to do it: Use functions and classes to encapsulate reusable code. Whenever you find duplicate code, consider refactoring it to remove it.
Use Objects:
- What it is: Use object-oriented programming to organize your code.
- Why it matters: Objects help structure your code so that different parts have clear, separate responsibilities.
- How to do it: Create classes that represent entities in your problem and distribute responsibilities so that each class has a clear function.
Test Your Code:
- What it is: Write tests to ensure that your code works as expected.
- Why it matters: Tests help identify problems before code is used in production and make future changes easier.
- How to do it: Write automated tests for the most critical parts of your code and test frequently as you develop.
Clean Code Matters:
- What it is: Write code in a clear, organized manner.
- Why it matters: Clean code is easier to understand, maintain, and evolve.
- How to do it: Follow good coding practices such as consistency, clarity, and simplicity. Review and refactor your code regularly.
Learn and Improve:
- What it is: Continue learning and improving your coding skills.
- Why it’s important: Technology is always evolving, and improving your skills helps you stay current and efficient.
- How to do it: Read books, take courses, collaborate with other developers, and review your own code to identify improvements.
Keep It Simple Stupid - KISS
Clean tests follow the rules of the acronym FIRST (Fast, Indepedent, Repeatable, Self-validation, Timely).
- Speed: tests must be fast so that they can be executed several times;
- Independence: when tests are dependent, a failure can cause a domino effect, making individual analysis difficult;
- Repeatability: it must be possible to repeat the test in any environment;
- Self validation: good tests result in “true” or “false” answers. Otherwise, failure may become subjective;
- Timeliness: tests need to be written before the production code, where the tests will be applied. Otherwise, the code may become too complex to be tested or the code may not be testable at all.
Don’t Repeat Yourself - DRY
DRY is the acronym for Don’t repeat yourself. It is the concept that says that each part of the system's knowledge must have only one representation. This way, avoiding code ambiguity. In other words, there must not be two parts of the program that perform the same function, that is, the famous copy and paste in the code.
But why avoid repetition? Simple!
Anyone who has a second home on the beach, or in the countryside, knows how complicated it is to ensure the maintenance of both. Even though repetition may seem harmless in simpler programs, it can become a problem as the software grows and maintenance and development become increasingly complex.
A good way to avoid code duplication is to correctly apply the single responsibility technique. For each function or method, use only one part of the method (or function). The correct thing is to abstract just this part and create a new one!
Some condition ambiguities are not so destructive to the code, but over time they can be. Therefore, try to avoid them as much as possible.
Better safe than sorry. This famous saying applies to software development as well. Good developers think that things can go wrong, because they will eventually. This way, the code must be prepared to deal with these problems that arise.
Today most languages have resources to handle errors in code through Exceptions and try-catch blocks.
Exceptions: mechanism that signals exceptional events. For example, trying to insert the character “a” into an integer variable;
Try-catch blocks: catch the aforementioned exceptions. Therefore, they must be used globally. After all, the methods already have their functions (which is not to handle errors).
To conclude this topic, an excellent tip to avoid generating errors in your code is simply not to use “null”, either as a parameter or as a return in functions. These returns often require unnecessary checks that, if not done, can generate errors.
YAGNI - You Aren’t Gona Need It
"You aren't gonna need it" (YAGNI) is a principle of Extreme Programming (XP) that states that the programmer should not add any functionality until it is actually needed.
"Always implement features when you really need them, and never when you anticipate you will need them."
It seems obvious, doesn't it, but think about it. How many times have you implemented a feature in a project just because you thought the client would love it, or that it would give the project that edge?
This doesn't mean you should avoid writing flexible code.
It means that you should not include features in your code based on the fact that you may need them later.
There are two main reasons for practicing YAGNI:
You save time, because you avoid writing code that you won't need at the moment;
Your code gets better, because you avoid polluting the code with 'guesses' that end up, in most cases, being wrong guesses;
1- If you don't need the functionality now then don't implement it. You don't need it.
2- Do you really think you will save time overall by spending more time now than in the future?
Semantic Version 2.0.0
Given a MAJOR.MINOR.PATCH version number, increment the:
- Major version (MAJOR): when you make incompatible changes to the API,
- Minor version(MINOR): when adding features while maintaining compatibility, and
- Correction version (PATCH): when correcting errors while maintaining compatibility.
Additional labels for pre-release and metadata build are available as an extension to the MAJOR.MINOR.PATCH format.
Conventional Commits
The Conventional Commits specification is a lightweight convention on top of commit messages.
It provides an easy set of rules for creating an explicit commit history; which makes it easier to write automated tools on top of.
This convention dovetails with SemVer, by describing the features, fixes, and breaking changes made in commit messages.
Conventional Commits Format
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
Types
feat: A new feature
fix: A bug fix
docs: Documentation only changes
style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
refactor: A code change that neither fixes a bug nor adds a feature
perf: A code change that improves performance
test: Adding missing or correcting existing tests
build: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)
ci: Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs)
chore: Other changes that don't modify src or test files
revert: Reverts a previous commit
Examples
feat: add new payment method
fix: resolve issue with login timeout
docs: update API documentation with new endpoints
style: format code with prettier
refactor: reorganize code structure for user module
perf: improve database query performance
test: add unit tests for authentication service
build: update npm dependencies
ci: configure Travis CI for automated testing
chore: update README file
revert: revert "feat: add new payment method"
Scopes (Optional)
feat(auth): add JWT authentication
fix(ui): correct button alignment issue
docs(readme): update contributing guidelines
style(css): apply consistent styling to header
refactor(api): simplify request handling logic
perf(db): optimize user retrieval queries
test(router): add tests for route protection
build(deps): bump lodash from 4.17.20 to 4.17.21
ci(github-actions): add workflow for automated testing
chore(env): update environment variables
Body (Optional)
fix(login): resolve issue with login timeout
The login timeout issue was caused by incorrect session handling in the backend. This fix ensures sessions are properly managed and prevents premature timeouts.
Footer (Optional)
fix(user-profile): correct user age calculation
BREAKING CHANGE: The method `getUserAge` has been renamed to `calculateUserAge` to better reflect its purpose.
feat(payment): add support for credit card payments
ISSUES CLOSED: #123, #124
Breaking Changes
feat: change authentication mechanism
BREAKING CHANGE: The authentication mechanism now uses OAuth 2.0. All clients must update to the new authentication flow.