When you have more people using your Java APIs, your projects grow and naturally you become a better engineer. You become more likely to increase your incomes and join great new projects. It also enables people to get their jobs done faster. So it’s a win-win situation.
To keep those people who already use your API and attract more, you need to eliminate these 4 mistakes.
Mistake 1: Force the Clients to Write Bad Code.
In his excellent book “20 API Paradoxes”, Jaroslav Tulach does an analogy of developers to artists. For both artists and developers, the beauty of their art matters. We like to look at our code and see beauty. So, when you force your users to create unpleasant or error-prone code, they get disappointed and frustrated.
An example of an API that forces the client to write bad code is the interface org.osgi.framework.Bundle
. It provides us the method getLocation()
which returns a String
value. The problem is it doesn’t specify a format for that value, and it’s the only method that can provide the bundle’s location. As the API doesn’t specify a format, the implementation is free to use anyone.
As you can see on the following image, the Equinox OSGi implementation returns the location in a way that the clients need to parse the value to find the file.
Now the clients have two problems:
-
The API is forcing them to create an implementation lock-in. The clients depend on how the implementation formats the location.
-
The API is forcing them to create a version lock-in. The format can vary between the different versions of the implementation.
The API designers could solve that problem by adding to the Bundle
interface a method that returns a Path
or File
.
Another solution could be to make the getLocation()
method originally return a Location
class, and that Location
could have the attributes needed. That solution would let explicit what the implementation must return and would not force the clients to parse a String
.
Mistake 2: Lack of Consistency in Nomenclature.
One of the 3 principles that sustain great frameworks and libraries is about ease of use. If your API is hard to use, you’re losing clients.
When you don’t have a standard for naming classes and interfaces, your API becomes hard to use. Don’t mix different names that have the same meaning in your API.
For example, the words “fetch”, “retrieve” and “get”. All of them have the same meaning. By mixing them, the clients won’t know how to search for a method, because sometimes you use “retrieve”, sometimes “fetch”, and sometimes “get”. So choose one of them and stick with it.
Mistake 3: Centralize Access to the Features in a Single Class
We may think that by centralizing access to our API’s features in a super class, we would make the client’s life easier. At first, it seems a good idea, since after all, all the clients need to do to access a feature is to call an inherited method.
Let’s look at an example to see it clearer.
public class GreatApi { public CoolFeature getCoolFeature() { return new CoolFeature(); } public NiceFeature getNiceFeature() { return new NiceFeature(); } public AwesomeFeature getAwesomeFeature() { return new AwesomeFeature(); } }
public abstract class GreatApiClient { private GreatApi greatApi; public GreatApi getGreatApi() { return this.greatApi; } }
public class ClientClass extends GreatApiClient { public void doClientStuff() { getGreatApi().getAwesomeFeature().doAwesomeStuff(); } }
Straightforward for the client to use the feature, right? But that approach will bring us tremendous problems in the future.
One problem is that every client class that needs to use the API will depend on GreatApiClient
and GreatApi
classes. We don’t want that because the more spread out an artifact is, the more difficult is to change it.
Testing also would become difficult because the client would end up having to mock many classes.
Another problem is that the GreatApi
class would become huge because the access to all the API’s features would be made through that class. Besides violating the Single-responsibility principle, this would bring concurrency problems as well.
An excellent alternative to that is to use dependency injection instead of having the classes GreatApi
and GreatApiClient
. This way, the client class would depend only on the classes that it really needs.
import javax.inject.Inject; public class ClientClassUsingDependencyInjection { @Inject private AwesomeFeature awesomeFeature; public void doClientStuff() { this.awesomeFeature.doAwesomeStuff(); } }
Mistake 4: Don’t Use Immutable Objects
Immutable classes are thread-safe. That alone is a good argument for writing immutable classes. But there are more advantages to using those classes.
Joshua Bloch states in his “Effective Java” book:
An immutable class is simply a class whose instances cannot be modified. All of the information contained in each instance is fixed for the lifetime of the object, so no changes can ever be observed. The Java platform libraries contain many immutable classes, including
String
, the boxed primitive classes, andBigInteger
andBigDecimal
. There are many good reasons for this: Immutable classes are easier to design, implement, and use than mutable classes. They are less prone to error and are more secure.
You can find out how to create immutable classes in Oracle’s Java Tutorial.
Enable Your Clients to Enjoy Using Your API
Having good performance and being bug-free is fundamental for a great API. This is not what will make you have more people using your Java APIs. This is the minimum that people expect. Do more than just that. Make your clients happy by using your API. They want to create great code, so don’t force them to use bad practices. Instead, use your API to encourage and inspire them to use the best practices.
This will help you become a better professional and will empower you to grow your career.
What’s preventing you from having more people using your Java APIs? Leave a comment here or send me a message on my social media. It will be great to help you attract more clients to your product.