Creating quality code should be the foremost thought on every developer’s mind. In this Agile world, code produced by a developer is not individually owned. So, we should not be afraid to provide useful code-review comments and should appreciate the code feedback we get from team members. One often-overlooked item in development is the Naming convention. One way developers can practice ‘kind programming’ is by leaving code in better shape than it was in when they got it. (Boy Scout rule?)
There are plenty of articles on coding, design and refactoring. So, this blog will take some sample code, analyze it piece by piece, modify it, and touch upon some theoretical concepts along the way. The end result will be better code. Important concepts to read about further are in bold and links to explore more are in [square brackets].
I chose Java for the code example in this post. However, this is applicable to any programming language.
The example code I chose reads a comma-separated string from a text file and creates a list of objects from it. Please take a moment to look over the three screenshots below.
Screenshot #1 Contents of products_data.txt file
Screenshot #2 Product POJO
Screenshot #3 ProductsService class for operations related to Products
At first glance, notice that apart from the class name ProductsService, the naming convention for the variables and methods is not proper.
The name of the method is generic, however the statements inside the method perform the specific function of reading a specific file from a specific location.
Below are better suggestions for naming the variables.
See the definition of Refactoring below. When refactoring, we should be doing so iteratively to avoid test failures. As common sense suggests, it would be illogical to create better code at the risk of affecting the functionality.
Refactoring: Refactoring is the process of changing a software system in such a way that it does not affect the external behavior of the code yet improves its internal structure. [https://refactoring.com/]
Below are better suggestions for naming the variables.
Okay, let’s deviate a little on a design aspect. See the calling of the setter methods of the Product inside the lambda block? PAUSE here. What’s going on?
Product POJO
How do we ensure the Product object is not modified inadvertently in some other function or by some other thread? This is a perfect use case to make the Product object immutable.
Immutable: An object is considered immutable if its state cannot change after it is constructed. Maximum reliance on immutable objects is widely accepted as a sound strategy for creating simple, reliable code. [https://docs.oracle.com/javase/tutorial/essential/concurrency/immutable.html]
Many ways to make a Java object immutable may be found in the Java documentation. For this post, I am not going to overly reengineer using Reflections.
The simplest trick is to remove the setter methods and mark the instance variables as final and introduce a constructor with these three final variables as parameters. One important rule in Java’s immutability is that the methods inside a class should not leak object handles. getCreatedTime() method returns a LocalDateTime which is immutable. However, if it is a type of java.util.Date, the getter should return a clone or a copy.
One other design consideration on the constructor is: what if there are five more fields to initialize and/or some fields are optional? Builder pattern comes to the rescue.
Builder Pattern: The builder pattern is a design pattern designed to provide a flexible solution to various object creation problems in object-oriented programming.
The intent of the Builder design pattern is to separate the construction of a complex object from its representation. It’s one of the Gang of Four design patterns. [https://en.wikipedia.org/wiki/Builder_pattern]
One hot debate (not discussed here) is whether to use a static factory method to initialize or a public constructor. However, it should be the best decision to consider. An example: say you have a class called Customer, with 2 constructors, one with 2 String parameters and another with 3 String parameters. Wouldn’t it be better to use meaningful static factory methods instead of exposing the constructor? Check out the definition and learn more in the link provided.
Screenshot #4 Static Factory Method example
Static Factory Method Vs Constructor: One advantage of static factory methods is that, unlike constructors, they have names. If the parameters to a constructor do not, in and of themselves, describe the object being returned, a static factory with a well-chosen name is easier to use and the resulting client code is easier to read. [Effective Java by Joshua Bloch]
Below is how our Product and ProductsService class would look after making the naming and design changes.
Screenshot #5 Modified Product POJO
Screenshot #6 Modified ProductsService class
References: http://www.pitt.edu/~vat16/prices.html
We hope you found this information helpful. Lastly, if you have any additional questions around creating quality code through meaningful naming and design practices, please don’t hesitate to reach out to us. We’d love to help you out.
Necessary cookies are absolutely essential for the website to function properly. These cookies ensure basic functionalities and security features of the website, anonymously.
Cookie | Duration | Description |
---|---|---|
cookielawinfo-checbox-analytics | 11 months | This cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Analytics". |
cookielawinfo-checbox-functional | 11 months | The cookie is set by GDPR cookie consent to record the user consent for the cookies in the category "Functional". |
cookielawinfo-checbox-others | 11 months | This cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Other. |
cookielawinfo-checkbox-necessary | 11 months | This cookie is set by GDPR Cookie Consent plugin. The cookies is used to store the user consent for the cookies in the category "Necessary". |
cookielawinfo-checkbox-performance | 11 months | This cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Performance". |
viewed_cookie_policy | 11 months | The cookie is set by the GDPR Cookie Consent plugin and is used to store whether or not user has consented to the use of cookies. It does not store any personal data. |
Functional cookies help to perform certain functionalities like sharing the content of the website on social media platforms, collect feedbacks, and other third-party features.
Performance cookies are used to understand and analyze the key performance indexes of the website which helps in delivering a better user experience for the visitors.
Analytical cookies are used to understand how visitors interact with the website. These cookies help provide information on metrics the number of visitors, bounce rate, traffic source, etc.
Advertisement cookies are used to provide visitors with relevant ads and marketing campaigns. These cookies track visitors across websites and collect information to provide customized ads.
Other uncategorized cookies are those that are being analyzed and have not been classified into a category as yet.