Additional Blogs by SAP
cancel
Showing results for 
Search instead for 
Did you mean: 
0 Kudos

<p>

From time to time one recognizes methods like

<pre>

String getProperty(String)

void setProperty(String, String)

Map<String, String> getProperties()

</pre>

for some factory provided by an API. Eh, what...? , one will say, especially when not familiar to that API. In very many of the cases there is only a restricted set of allowed or supported parameters for these methods. If one is lucky these are defined as static constants in the factory or are at least documented in the javadoc. Especially in the former case it can be annoying when there are more constants defined (for other purposes) than are keys accepted.

</p>

<p>

Another prominent example I struggle over very often is something like:

<pre>

Foo doSomething(String path)

</pre>

In many cases this doesn't make problems, but what if the environment one is using the API in doesn't allow direct file system access via paths? One of the problems with it is that normally one does not know its installation location but the platform allows easy access to resources in the installation. If the platform is flexible in its packaging, this might be plain files as well as packed entities, so the natural thing a platform returns is an URL. How to convert it to a file system path? </p>

<p>

What do these examples have in common? They are using String for entities which have a semantic meaning. What is the natural way to express something with a semantic meaning in a typed language? Yes, you choose an appropriate type for it. In many cases java.lang.String is not worth much more than java.lang.Object.

</p>

<p>

In the first example an enum (in 1.5) or the typesafe enum pattern (below 1.5) will do the job. Even if you are reading a properties file, nobody prevents one from putting the recognized keys into a typesafe construct. One has to hardcode the recognized keys anyway. This will be an easy place to remember the supported keys when you are in doubt half a year later or when you have to hand over the code.

</p>

<p>

In the second example: What will doSomething normally do? It will construct a stream to read the contents.

Than the API should take an InputStream if only sequential reading is required. If an URL suffices (eg. for an external database driver which can be bound via an URLClassloader) this should be the parameter. In the rare cases where really file system access is required the parameter should be exactly that: java.io.File.

</p>

<p>

Another prominent example of this category is javax.xml.parsers.DocumentBuilderFactory which allows one to set properties for specific implementations. What can this be good for? If I require properties of a specific implementation than I will use that directly. In xml parsing I did not find so far any use case where one requires a property optionally (but I may be wrong since I do not use that often). If you are bound to a specific implementation call it or cast to it. This requires you to refer it directly and to think about how to package it with your solution.

</p>

<p>

As a conclusion I would ask any provider of an API: be specific to the level your API requires and tell the client with your interface what you are expecting. This will increase the usability of an API a lot AND give the compiler a chance to check your requirements.

</p>

4 Comments