amcneil36.github.io

Additional Coding Recommendations

1) Favor depending on an interface over depending on an implementation of an interface.

Lets say you have FooImpl which implements FooInterface.

2) Favor interfaces over subclassing when needing re-usability

3) Favor interfaces over abstract classes

Abstract classes are less-reusable than interfaces due to the issues outlined above on subclassing.

4) Test behavior, not implementation

5) Know what to test in an application

6) Override hashcode, equals, and toString on entity/pojo/value object classes

7) Do not make code changes that exist solely for the sake of testing. Here are some anti-patterns below:

8) All of your code should be easily testable by passing in mocks to parameters

Do not do anything hacky in your tests. If doing something hacky is the only way to test your code, then you are following poor design practices. This means that you are too coupled to implementation details. Here are some anti-patterns below that might appear when some people try to unit test poorly designed code.

9) Constructors should have no side effects or logic. They should just do assignment

Having a constructor throw if invalid parameters are passed in is fine. Other than that, the constructor should only do field assignment. For example, it should primarily be “this.field1 = parameter1; this.field2 = parameter2;” etc. Do not create any new objects or put side effects in the constructor.

10) Either fix warnings or suppress them.

If you are going to suppress a warning, add a source-code comment explaining why you are suppressing it. The correct approach most of the time will be to fix the warning. However, don’t fix a warning just because it is a warning. If you have done some research and you feel that the warning is not worth the time to fix or that it is not really an issue, go ahead and suppress it.

11) Aim for one assert per test

If a test with multiple asserts fails, it takes longer to determine what actually went wrong.

12) No tests should affect other tests. The order that the tests are ran should not affect the output

If tests are modifying any objects that are used throughout the class, those objects should be re-initialized before each test.

13) Never return null

Returning null requires the consumer to have to do a null check which makes the code more cluttered. We can return default values, an optional, or throw instead.

14) Do not use interfaces for POJO/entity/value objects

This causes adding a field to the class to be a non-passive change, assuming a corresponding getter needs to be added to the interface.

15) A client should not be forced to depend on methods that it does not use (Interface Segregation Principle)

16) Favor immutable fields over mutable fields

This makes code thread-safe and easier to follow.

17) Methods should be small-generally five lines of code or less

18) Classes should generally be 300 lines of code or less

If a class starts doing too much, extract some of the work out into another class.

19) Favor one logical statement per line of code over method chaining except for when using fluent interfaces

20) Ya Ain’t Gonna Need It (YAGNI)

21) Keep It Simple Stupid (KISS)

22) Don’t pass in one object as a means of getting another object. Pass in directly what you need (law of demeter)

23) Only validate parameters at the boundary points of your application

24) Don’t repeat yourself (DRY)

25) Do not optimize for performance without having metrics

Suppose you have two possible solutions to a problem in mind. One solution is predicted to be easier to implement than the other but is predicted to have worse performance. You should generally try the easier solution and performance test it to see if the performance is OK. We want to performance test our solution as early as possible. This might even include writing some dummy code to mirror the easier solution and performance testing that. This way, less code gets tossed if our performance test is unsatisfactory. If our performance test results in slow results, then try the more complicated solution. Most of the time performance will not be an issue.

Sources

  1. Fowler, Martin and Beck, Kent. Refactoring: Improving the Design of Existing Code. Addison-Wesley, 1999.
  2. Martin, Robert. Clean Code: A Handbook of Agile Software Craftsmanship. Prentice Hall, 2009.
  3. Bloch, Joshua. Effective Java. Pearson Education, 2018.
  4. McConnell, Steve. Code Complete: A Practical Handbook of Software Construction. 2004.
  5. Martin, Robert. Clean Architecture: A Craftsman’s Guide to Software Structure and Design. Prentice Hall, 2018.