- The intention of a code review is to find defects and not style variations. Defects can be:
- failures (e.g. certain parameters lead to unexpected behaviour, unspecified results, exceptions or errors reports)
- defects in logic
- security vulnerabilities
- specification mismatch
- missed implementation
- inefficient implementation
- usage of O(n^2) algorithms for the task where O(log(n)) algorithms are available
- similar computations can be done with a smaller version of a program (less code - better)
- similar code is available in a known and well-tested library
- violations of best practices which leads to defects.
- Use words can or could instead of don't in your comments.
- Always show how as a part of any suggestion.
- Be-sentences are forbidden, (e.g. be more patient, be smart, be nice, etc)
- Endpoints contain nouns (and never verbs). Highlights flaws in the API in case of violation.
- Use UUID or random hashes as IDs instead of numbers in order to prevent data leakage.
- There is a test (at least one) which covers added or modified functionality (all cases / branches).
- All method's (or function's) parameters are in use. Preferably: there is an automated check which fails a build when this rule is violated. Highlights "dead" code and missed functionality.
- All configuration parameters are still in use. Highlights "dead" code.
- Exceptions and error conditions are logged properly.
- App doesn't log sensitive data (tokens, raw request or responses, PII).
- Order is not expected in the code which iterates over HashSet values or HashMap keys.
- Is it safe to use default values from configuration in production.
- Serialization and deserialization are aligned and work with same fields in the same order.
- String interpolation is not used for serialization of objects or it's safe to serialize values into string (no escape logic needed).
- Expression is case-insensitive (
(?i)
) or it is clear that it should be case-sensitive. - Expression doesn't rely on position (
^$
). Spaces before first word could bypass checks that use such expressions. - Quantifiers (
{1,3}
) are well-reasoned. Malicious person can bypass such expression using more repetition than expected. - No ReDoS-like expressions
(a+)+
. Payloadaaaaaaa....aaaaaaaab
requires2^n
comparisions. - Quantifiers (
+*
) are well-reasoned. Expressiona'\s+b
won't catcha' space-0-times b
. - Blacklist includes all Unicode-alternatives. Expression
a[\n]*b
won't catcha\rb
.
play.api.libs.concurrent.Execution.Implicits.defaultContext
is used instead ofscala.concurrent.ExecutionContext.Implicits.global
. Use DI:class Service @Inject() (...)(implicit ec: ExecutionContext) { ... }
. This rule can be relaxed for tests.ActorSystem
is properly closed after usage (violation of this rule often happens in tests).- Sequence of
route(app, request)
in tests can be executed in any order and it's expected.
- Expected that
Future.fallbackTo { ... }
code inside curly brackets runs even whenFuture
completes successfully. - Expected that
Option.forall( ... )
orSeq.forall( ... )
returnstrue
for any predicate when the value isNone
orNil
respectively. See Vacuous truth - All fields in case class have either case class type or implement
equals
andhashCode
methods. For example,scala.util.matching.Regex
cannot be defined as a field in a case class. - Variable (
var
) or mutable collection is not a member of class or it is expected that modification of this collection is not thread safe (pattern: read -> modify -> save back).
- All fields of an instance of Singleton can be safely used in multiple threads (i.e. thread-safe). For example,
SimpleDateFormat
in Java requires external synchronization or shouldn't be used as a class field in a Singleton. - Type of elements in collection and the type of an argument in
contains
operation should be the same. The compiler will not fail if one pass an integer into thecontains
operation on list which contains only strings because of the definition of the method:contains(Object o)
.
- String checks with
indexOf
also work for strings in different registers (i.e. case-insensitive).
- Avoid "t2.*" family or make sure that CPU credits will be a positive number in order to avoid performance degradation. Note that initial amount of credits will expire after 24h. In case when credits consumed = credits earned it will lead to performance degradation.