Ruby on Rails - Check My Code: Tips to Keep Ruby Code Smell-Free - ruby on rails tutorial - rails guides - rails tutorial - ruby rails
How to check my code in ruby?
- In this, we will discuss a few common Ruby code smells and how to best freshen them.
- Code smells are symptoms of a deeper problem, and by eliminating them, we can leave our code elegant and odor free!
- Common code smells include long classes, large methods, dead code, and repetition.
- These issues are not only bad practice, but they indicate that there is probably a structural issue with our code.
- Code smells might not cause an error immediately, but they make code difficult to maintain and might cause errors for edge cases.
- Below, we cover a few different smells, including dispensable code, long conditionals, classes with attributes but no methods, poor variable naming, and over commenting.
Learn ruby - ruby tutorial - learn ruby tutorial - codes in ruby check my code - ruby example - ruby examples - ruby programs
Check My Code for Smells: Ruby edition
Dispensable Code: If ___ Return True, Else Return False
- The pattern, “If __ return true, else return false” shows up again and again.
- Returning true or false from an if statement is redundant as we will see below.
- This pattern is an example of code that is dispensable and will make our program bloated and difficult to read.
- Below we discuss two different ways to code this pattern: one is long and redundant, and the other is concise and elegant.
- Check out the following method on the Animal class, which determines if an animal is_a_peacock?.
- Do you smell it? The conditional type == “peacock” already returns a boolean, so we don’t need to include it in an if statement. This six-line phrase can and should be simplified into just one line. See below:
- Ahh, that’s better! We will keep this in mind whenever we find ourselves falling into the “if ___ return true, else return false” pattern.
- By removing dispensable code, we can make our code clean and easier to understand. Let’s move onto smellier smells!
Long Conditionals
- There are a few different ways we can do this, but some are much more odorous than others
However, this strategy is still long and wordy. We can improve on this even further!
- By mapping majors to responses, we can simply hash the major input and get the appropriate response as the output.
- We set a default value that is returned if the major entered is not included in major_responses
- After setting up our major/response mapper, we only need one line, which finds the response in constant time.
- Note that if we were trying to write a solution that optimizes for space complexity, this would not be an appropriate solution.
Class With Attributes but No Methods
- As we know, classes are used to organize objects that behave similarly and have the same properties.
- But what if we have an item that has no methods or no actions? See below.
- As we can see, a Person has many attributes. But in our example, a Person does not have any actions.
- For this reason, a class is not the best way to represent this object. While functionally, a Person class does the job, it is best practice to use a Ruby struct. Structs are used to create simple classes and can be initialized much more concisely.
- Below are two different examples of how to create a struct.
Or,
- We can now create a person like so:
- And Sally’s attributes can be accessed exactly like we access attributes for an instance of a class.
- From now on, we can “de-smell” our code by using structs whenever we have an object that can be fully represented by only its attributes.
- As a side note, structs also come in handy when dealing with node-based data structures such as linked lists, trees, and graphs.
Variable Naming
- Name your variables appropriately. We’ve heard it before, and we’ll hear it again! While a, b, x, and, y are easy to type out, going back and understanding your logic days later is a pain.
- Poor variable nomenclature is a symptom of unmaintainable code and should always be avoided. See below.
Now our code almost reads like plain English which makes it easy to understand and maintain.
Indexing Into JSON Objects with Long Chains
- Let’s say we are trying to access data deep inside a large JSON object that we have imported and parsed into a Ruby hash.
- This pattern is common when accessing APIs.
- We want to access some piece of data that is inside a hash, which is in an array, which is in a hash, which is in another hash.
- While it may be tempting to just keep indexing until we have arrived at our destination, this technique often leads to errors down the road.
- Let’s take a look at this example response from a sample API that returns information about geographic regions.
Response for California
- If we want to use this API to find the email address of one of our senators , we may be tempted to write a method like so:
- While this method will work for most of the responses, we must consider the edge cases that it will fail on.
- We can’t just assume every state will have senators and each of those senators will have emails.
- Check out this response from the same API for Washington DC.
Response for Washington DC
- Washington DC has no senators (taxation without representation!), so our previous method get_senator_emails will throw an error like this one : NoMethodError: undefined method '[]' for nil:NilClass.
- If we are not completely certain that our JSON object will have the same format for every possible response, it is dangerous to chain methods. Instead, we should write the get_senator_emails method like so:
- By checking the return value of senators before chaining another method onto it, we can provide the user with helpful error information.
- We can now be confident when we call .first["email"] that we will not get a NoMethodError.
- Every time we add another link to our chain, we have to be careful and check that the previous item will always be the expected return value.
Over and Under Commenting
- The last code smell we cover in this tutorial is poor commenting.
- Comments are important, but we should make sure that they supplement our code in a way that is helpful, not repetitive.
- There is a fine line between comments that are useful and those that just obfuscate code.
- Below is a sample of a method that determines if an integer, n, is prime. One solution is over commented, and the other has one much more useful comment.
Over Commented
Helpfully Commented
- As we can see, the first example’s comments just reiterate what the code is doing and doesn’t provide any extra information.
- The second sample has a single helpful comment, and is not redundant.
- One useful trick is to think of comments as an explanation of why we are doing something and the actual code as an explanation of how we are doing something