Skip to content

Coding Standards

Elena edited this page Oct 28, 2022 · 6 revisions
  1. Set Kotlin code style (https://kotlinlang.org/docs/reference/coding-conventions.html):
  2. To configure the IntelliJ formatter according to this style guide, please install Kotlin plugin version 1.2.20 or newer, go to Settings | Editor | Code Style | Kotlin, click on "Set from…"link in the upper right corner, and select "Predefined style / Kotlin style guide" from the menu.

To verify that your code is formatted according to the style guide, go to the inspection settings and enable the "Kotlin | Style issues | File is not formatted according to project settings" inspection. Additional inspections that verify other issues described in the style guide (such as naming conventions) are enabled by default.

then set Use single name import

Use Ctrl+Alt+l after change classes before commit!

  1. use $gradlew ktlint to check code style - if this task failed - there is report in build\reports\ktlint where you can find what is wrong and fix it manually or you can use $gradlew ktlintFormat to fix it automatically if $gradlew ktlint task is failed - build project would be also failed so you need to fix code style in any cases

  2. we do not use extra brackets {} in single line after condition

if (true) println("not use brackets {} if it is a single line after condition")

  1. lets not use extra lines between code lines - fun would be shoter and more readable. use it in very random cases, when you really have to mark different semantic code blocks - but remember, that you can separate semantic code blocks in different funs, as uncle Bob says. let's follow his approach and make code cleaner, shorter and readable.

  2. MR life cycle:

  • MR should have title like #TaskNumber #Task_Title and description like #TaskNumber #Task_Title what was really done in this MR
  • after create MR - place it in team chat.
  • after approve team members team lead should merge MR or those on whom it is assignee.
  • descuss all ideas about MR in MR comments, please.
  1. Here are basic packages and major tips:
  • Advice is for handling exceptions globally across the whole application. There is no need to carry an exception occurred in dao to a controller. The advice takes care of it whenever an exception is thrown. An exception as it is should not be propagated to an end user.

  • Controller is for getting a request and sending a response with an appropriate headers. Stick to the following:

  • Use REST operation appropriately. For example, post for creating new objects, put for changing existing ones and so on Validate input by means of @Validated Use log.debug { } to log input* When it comes to multiple request params, make use of data class with a postfix Filter so that to reduce the number of the method params Annotate methods with ApiResponses, ApiOperation and ApiImplicitParams Try to minimize the number of http requests from a user perspective. For instance, provide a user with an ability to send an array of objects instead of a single one Version your rest api Converter is to transform an object to another one. It helps to keep application code layer in a consistent state. For example, a dao layer works with entities and yet a service one does with dtos

  • Dao is to communicate with data store Use interfaces Use log.debug { } to log input Operate with entities Make sure that entities have a unique business key(or a compound key) to override equals and hash code

  • Exception is tofine-grained control over all exceptions Should extend RuntimeException (or another BusinessException that extends RuntimeException) Whenever possible, use standard exceptions from stdlib For custom exceptions, provide 2 constructors: one is for a message and second is for a message and a cause. Fill a cause, If there is an opportunity

  • Service is to do some business logic in between of a controller and a dao Use interfaces Use log.debug { } to log input* Make use of converters to transform an object to another one Use a service rather than a static code when it comes to some business logic that is bigger than a small utility method. Never forget that static code cannot be mocked and thus is ran every time a unit test call it explicitly or implicitly Testing

  • It a must have junit 5 unit tests covering fully all the written code as per a user story Use Mokito only when you have to mock spring beans. For example, ExceptionControllerAdvice just instantiates a new instance and uses it for testing without any mocks While writing a unit test, mock all the downstream beans. For example, a controller unit test should use a mock bean instead of a real one. In turn, a service should be tested on its level only. Ideally, a piece of code is called only once during testing Mark integration tests with IntegrationTest annotation so that to separate unit and integration tests Even though we use mock mvc, integration tests are quite heavy. Therefore, cover all possible if branches, positive and negative cases with unit tests. Integration once should not be overused. They are for some general cases. Each test should have 3 separate blocks: GIVEN (input data), WHEN (action/actions) and THEN (assertions) If you need a utility method in tests, put it in a proper utility class under the test directory, see for example TestUtils When it comes to test a single method with different bunch of params, make use of @ParameterizedTest

  • Naming https://kotlinlang.org/docs/reference/coding-conventions.html#naming-rules "When using an acronym as part of a declaration name, capitalize it if it consists of two letters (IOStream); capitalize only the first letter if it is longer (XmlFormatter, HttpInputStream)."


*log.debug{} eliminates the need to create a new string