Rails Development: Coding Conventions & Best Practices.
What’s in a name
A good name answers important questions. What does it contain? What does it mean? How would I use it?
What role does it play?
Always name your methods based on their behavior, not implementation.
Consider,
By looking at the method name above, we can predict it’s going to perform 2–3 database operations, but
when I’m working on the Business model, why would it concern me?
Going by, the naming method based on their business role, the method can be renamed as,
Structural Naming
Another common strategy is to name things for their role in the program. It’s the input or the output. It’s the recurring phrase or the middle sentence. Consider the code for counting differences between two points;
Here the arguments first and second are pretty vague, considering the fact that we’re not even sure if the order matters. In this context, it doesn’t.
I can then restructure my code as;
What we can conclude from this is, the first step was to describe the problem in English. Distance calculation between two strands is about the count of the mutations encountered between the two strands.
Refactoring
Rearranging code is generally pretty trivial. The tricky part is knowing where to begin, and recognizing that you can do it. Part of getting over that barrier is simply doing it a few times. Find a conditional, and for each of its blocks, create an object whose sole responsibility is to do that thing.
Refactoring is about recognizing a snippet of code as exhibiting characteristics that are known to be problematic. Applying a change that is known to fix this category of problem.
This problematic pattern is called Code Smell, “code smell is a surface indication that usually corresponds to a deeper problem in the system.” — Martin Fowler
Starting small is never a bad idea, if you can refactor code at the micro level, then when it all comes together, it will become a refactored code.
Consider two code snippets for example,
What is the similarity in the code pieces above? Both have each loop, and if we try finding their code smells,
- A loop with a temporary variable.
- A loop with a nested conditional.
Let’s try refactoring them
The first loop only has a temporary variable, which can be fixed using ‘inject’
This one has two temporary variables, and a nested loop, since we’re trying to rank them, sort_by should work!. The code can be refactored even more, since we’re trying to find the max value, we can directly use the max_by function here,
General Practices
- What if we devise a set of rules to follow while coding, that later on reduces our efforts in refactoring.
The most basic and important point is FORMATTING. It sounds like the most obvious and easy thing to do but it’s very important to format your code correctly. In terms of code readability, understanding for future references, and also while resolving conflicts that occur while merging two different branches. - When writing an if condition with multiple sub-conditions, always try ordering them such that the least effort is required. For example,
- If you're a big chunk of logic, which is going to revolve around a single functionality, try breaking that into multiple smaller methods. It increases reusability, plus it becomes easy for a new developer to understand the code easily. Instead of writing everything in a single method, and giving it the look and feel of complex logic, divide it into smaller readable chunks of methods.
- Comment your magic code. Ruby provides a lot of metaprogramming methods, which help reduce your effort and are time friendly. But they’re not always that easy to understand when you want to refer back to them, it’s always a good idea to add appropriate comments so that when you come back later to take a look, it’ll be easier for you to reconnect.
- Use before_filter, instead of repeating yourself in the controller.
- Use model callbacks to avoid writing too much code into controllers for the actions that revolve around the basic CRUD operations.
- FORMATING: there are certain gems which makes your life much easier : awesome_print ; pretty print ; rubocop.
- Always follow the practice of Code Review in Git. Code that’s written by one developer, should be reviewed by other team members before merging with the main branches, as that helps eliminate any potential errors or unexpected outcomes. It also helps in keeping every member informed and updated about what their colleague is working on.
- Statements that extend post 80 characters should be broken down into next lines so as to avoid scrollbar when viewing code in other mediums like GitHub.
- When committing code to your repository, git diff tells me what you did, your commit message should say why you did that.
- DO NOT OPTIMISE for performance — OPTIMISE FOR CLARITY OF CODE
- Unit testing is always a good idea to ensure the functionality is working as you expected. Help by Aspect: Rails by default generates one helper for every controller. Eliminate them and try using helpers which are aspect-oriented like ; -> link_helper –> menu_helper
- As per the convention of MVC, one should avoid making calls to the database from the View layer. Move that part of your code into controllers to ensure the separation of concerns.
- Reduce calls to databases. If an often visited page triggers more than a couple of calls to the DB, it’s worth spending a little time to reduce the number of calls to just a few. In many cases, this is just a matter of using .includes() or .joins().
- It becomes a tedious task to check your model structure time to time, as a resort to that, include your model structure at the top of the file as a reference.