Classes & Interfaces

Java Best Practices Series

Classes & Interfaces

15. Limit Accessibility To Classes And Members

Generally, any class or member of a class should have the lowest possible access level, which still allows for its functionality to work.

API Example:

Take the case of an externally exposed API, where the interface represents all public accessible methods. Any implementation of this interface should only have public access level on the implemented methods.

The additional members of the implementing class should never be made public. Ideally private or package-private if required for unit testing.

In the case of the exposed API, any publicly available member of the implementation will have to be supported forever, if they have once been published. If members are degraded to a lower access level, it will ruin the API’s backwards compatibility.

16. Public Classes Should Have Access Methods To Fields

If a class is publicly exposed, no fields should be made public. Instead they should be accessed through getter-methods.

Making the fields retrievable through getter-methods, allows for alterations within the same public method, whereas a direct access to a field cannot be changed.

17. Create Immutable Objects

Immutable objects require five rules to be followed:

  1. Don’t provide methods that change the object’s state.
  2. Limit the class from being extended.
  3. Make all fields final, so that they cannot be changed.
  4. Make all fields private. (see 16.)
  5. Mutable fields should never be accessible or providable.

18. Composition Is Preferred Over Inheritance

Essentially you should always strive to use independent object compositions instead of inheriting unless you really plan for it. (see 19.)

Inheritance creates fragile architecture, since subclasses must rely on the functionalities of the superclass.

It can be difficult to gain an overview of the change’s effects of a superclass, when multiple subclasses extend it.

Many design patterns are for this reason based on composition. (e.g. decorator, strategy, and composite)

19. Make Plans And Documentation When Inheriting

If you plan to create a inheriting class structure, it is highly recommended to plan out the intended use cases and document the proper way of utilizing the extendable class.

Which methods should be available for overriding? How are we making sure that none of the overridable methods are not being called within the constructors? Do all overridable method have the proper documentation.

20. Prefer Interfaces Over Abstract Classes

Both interfaces and abstract classes are designed to enforce method implementation on the classes which inherit from them.

However, abstract classes are more constraint since Java only allows for one class extension. Whereas for interfaces, multiple can easily be implemented on the same class.

21. Design Interfaces To Guide Implementations, Not Control

Since Java 8, the default method has been introduced, and with it all the possible scenarios which could go wrong.

The default method is intended to define a concrete method for all implementations of the interface to use.

However, unlike the regular interface method, which are defined by the implementation, the default method controls how and what should happen within all its implementations.

This might never become a compile error, but it might create runtime errors. This is because it will be difficult

to manage how all the implementations handle the functionality of the default method.

22. Interface Are Used As Types, Not Constants

Similar to what have been said in item 21, interfaces have many possible ways of implementing functionalities or fields into all inheriting classes. (e.g. default methods and constant fields)

Regardless of these functionalities, it is still recommended to view an interface as a type declaration for the implementing class.

For example: all classes implementing a user-interface, can be considered a variation of a user. (e.g. admins, customers, editors etc.)

Thereby promising that any class implementing a given interface will also have the same methods.

Methods inside an implementation can be changed over time. Whereas, constant fields and default methods cannot after they once have been published to the public.

23. Never Make A Tag-Class

A tag-class is a class which serves multiple purposes based on which constructor is invoked or what arguments it is given. (e.g. a shape-class, could both be invoked as a circle or square)

Regardless of how you want to avoid this (composition or inheritance), actions should be taken, so that you never end up in a scenario where a class can serve multiple purposes.

24. Prefer Static Members Over Nonstatic

Whenever you create a class member, which does not require any reference to the instance’s other members, it should be made static.

Static methods ensures that you do not need to make a new instance of the member’s class whenever you want to use it.

25. One Top-Level Class Per Source File

Within any source file in Java, it is allowed, by the compiler to have more then one top-level class. (aka. non-inner-classes)

However, regardless of this being possible, it is highly not recommended to do so, since it only provides

organizational disadvantages.

If you need two classes, make two source files.

Recommended Reading

Video Tutorial 

  • Effective Java for Android Developers (Item #13, matching item 15) – Fragmented – YouTube
  • Effective Java for Android Developers (Item #16, matching item 18) – Fragmented – YouTube
  • Effective Java for Android Developers (Item #17, matching item 19) – Fragmented – YouTube

Article

  • Item 21 — Design interfaces for posterity – Matthew Dolan
    – Blog

Books

About

Hi, I'm the Author

My name is Daniel H. Jacobsen and I’m a dedicated and highly motivated software developer with a masters engineering degree within the field of ICT. 

I have through many years of constantly learning and adapting to new challenges, gained a well-rounded understanding of what it takes to stay up to date with new technologies, tools and utilities. 

The purpose of this blog is to share both my learnings and knowledge with other likeminded developers as well as illustrating how these topics can be taught in a different and alternative manner.

If you like the idea of that, I would encourage you to sign up for the newsletter.

Cheers! 🍺

Didn't Find What You Were Looking For?

Generic selectors
Exact matches only
Search in title
Search in content
Search in posts
Search in pages
Scroll to Top