How To Be A Tech Ninja: Coding Guidelines, Tips, and Tricks

editor
Selling Cars
Est. Reading Time:
8 mins

Cars24 CODING STANDARDS

You Build It – You Run It – You Secure It – You Monitor it

Coding guidelines are an extremely important part of a professional developer’s day to day practices. Following these guidelines distinguishes one as an experienced developer as opposed to a rookie. It’s ironic that so many companies still ignore them and produce poor quality code that results in very expensive maintenance over time and is so fragile that every time you add a new feature immediately bugs creep in.

Some items developers might not agree with but these guidelines are based on personal experiences and many of them are borrowed from classic texts. 

SERVICE DEVELOPMENT


GENERAL CODING GUIDELINES

MICROSERVICES

Calling different services in a microservices environment is pretty common and it may lead to some complex and unexpected behavior. That is why one should always assume something will go wrong with the external system and design the system accordingly. 

CLASS DESIGN

  1. Class should not be more than 600 lines.
  2. Constructor should not have any complex logic and has to be exception-safe.
  3. Prefer composition over inheritance.
  4. Follow one responsibility rule everywhere.
  5. Design for extensibility.
  6. If in Object Oriented language always define an interface.
  7. Avoid circular dependency.
  8. Follow Design Patterns – https://springframework.guru/gang-of-four-design-patterns/

UNIT TESTING

COMMENTS AND ERROR MESSAGES

  1. Write comments at all critical places in your code including variable name, their usage, function signature (input/output/parameters).
  2. During commit its mandatory to mention Jira Id in your commit message. 
  3. Add Comment In Code for Jira Ticket for Feature as Well As Bug Fix.
  4. Add Name and EMail as your signature and best to use IDE shortcut for the same.


IF/ELSE STATEMENTS

  1. Do not write deep nested if-else statements.
  2. If nesting is getting deeper break your code into multiple functions.
  3. Operator precedence for your language can introduce nasty bugs in your code which are extremely hard to debug. Follow a policy of using parentheses while writing if-else conditions.
    1. if (a == b and b != c) 
    2. if ( (a == b) and (b != c) ) 

IMPLEMENT OOPS

  1. It is recommended to implement OOPS in your code as much as possible.
  2. Program to an interface (contract), not class. Do not change the interface as much as possible.
  3. Try to make an abstract class for a business service (in case of python/C++, an interface in case of Java).
  4. Follow DRY Principle (Don’t repeat yourself). Use Design Patterns to promote code reusability

JAVA BEST PRACTICES

FUNCTIONS

  1. The function should not be more than 25 lines.
  2. Always check for valid parameters inside public functions. Throw an exception to report an error in params.
  3. To group the statements logically, try to divide different sections of a function into other smaller functions. E.g. Separate function for initializing values for every possible activity.
  4. Use functional programming capabilities if your stack supports it. I.e. pass around functions to write reusable code.
  5. Follow Single Responsibility Rule as closely as possible.
  6. Functions have to be testable (I should be able to write unit test case for this function). In other words, promote loose coupling via Dependency Injection or otherwise.
  7. To continue with loose coupling follow the rule “Prefer composition over inheritance”.
  8. If you are working with Java8 Never return null. Consider returning Optional
  9. Try to avoid multiple return statements. This can put nasty bugs inside programs so it’s best to avoid them as much as possible.
  10. Check the Big O Complexity of the algorithm you are writing. Especially for the case, where you are writing a lot of lines of code or for functions that are on a critical path.

Function overloading should follow convention

  1. foo(int), foo(int,double), foo(int, double, object) i.e. least needed parameter at the last.

LAYERED ARCHITECTURE

Follow layered architecture in true spirit. Upper Layer should call into lower layers and each layer has to be designed for a specific purpose. E.g. while following MVC, Logic in views has to be related to view and all heavy lifting shall be done by the service layer.

In Layered architecture, an entity should be referenced in only one repo interface/class and it must be accessed via only the specific service.

PACKAGE STRUCTURE AND NAMING CONVENTIONS

 LOGGING/TRACING

  1. It is recommended to use logging, wherever possible. The purpose of the logging is to diagnose any potential issues in production. Logging is useful but it incurs significant overhead on the application so it must be used wisely and only information required shall be logged.
  2. Logging should not be cluttered, it must follow the same consistent pattern across the application. Identify a pattern for logging for your specific use case
  3. While logging, make sure to log needful information for debugging purposes. Logging like log.info(“Some simple text“) does not help at all, adding some field param along with this would be helpful to know for which request this info is logged.
  4. Logging libraries are incredibly useful. Use their package level capabilities to switch on/off selective logging at different levels.
  5. Log back is one of the most widely used logging frameworks in the Java Community. For more understanding, please go through the Logback Guide.

 EXCEPTION HANDLING

WEB PROGRAMMING

SPRING BEST PRACTICES

DATABASE BEST PRACTICES

Security Practices

c2c/{repo-name}/{env}

mysql.userid

Mysql.password

redis.userid

redis.password

RELEASING THE SOFTWARE

  1. All Java services should follow the microservices architecture and be packaged as Fat Jar.
  2. Docker is used to deploying the software.

Maven Project Naming & Versioning 

GroupId : com.cars24 (always)

ArtifactId : name of your service (must be matched with the repository name

Version 

Dependencies conventions

  1. Dependencies should be used with release version only and version should be explicitly mentioned
  2. The version used of different dependencies should be declared in the properties tag
  3. Avoid cyclic dependencies
  4. Artifacts specified in the <dependencies> section will ALWAYS be included as a dependency of the child module(s).
  5. Artifacts specified in the <dependencyManagement> section will only be included in the child module if they were also specified in the <dependencies> section of the child module itself. You specify the version and/or scope in the parent, and you can leave them out when specifying the dependencies in the child POM. This can help you use unified versions for dependencies for child modules, without specifying the version in each child module.

REST BEST PRACTICES

  1. No need for redundant phrases inside api url — @PostMapping(“/addappversion”) here add has no relevance as POST is CREATE
  2. POST means create a resource, PUT means update, GET means read

File IO

  1. Use non-blocking APIs of Java instead of synchronous APIS. use java.nio package

Dates

  1. java.util.Date is extremely buggy. Please don’t use it for dealing with Date and Time. Instead, rely on java.time apis
  2. Use Instant class for the current time

PERFORMANCE BEST PRACTICES

Curated by and with inputs from Devender Kumar, Senior General Manager, Technology, CARS24

Sell Car in One Visit

Start Car Evaluation