Keep API simple
I want to share a success story of designing a simple API, when the problem seemed to be complex at first glance.
Recently we got a task. We had to log every action that user does on the web. In other words, we would need a simple class (API) which could be easily used from almost all the controllers in our web. Additionally, we should log different parameters depending on action.We also have got a draft solution for this task from unknown developers. We are not going to look inside logging; we are interested in how easy is to use logging (it’s API). Below you can see a typical controller code for logging user action:
private void logUserAction(User user) throws Exception {
UserActionModel model = new UserActionModel();
model.setAction("Buy a ticket");
List<String> values = new ArrayList<String>();
values.add("PersonCode");
values.add("UserName");
values.add("ContactInformation.EmailAddress");
values.add("ContactInformation.Language");
model.setParams(LogUtil.getParamsWithFieldNames(user, values));
LogUtil.log(model);
}
Probably you guess how LogUtil.getParamsWithFieldNames works. Given a “user” object and list of Strings, it calls corresponding getters: user.getPersonCode(), user.getUserName() etc.
It’s it nice?
Look what a mature, multi-purpose solution! It doesn’t depend on concrete class - it could be User, Client, Customer or whatever else. You can pass any object and list of field names, and this universal LogUtil can log all these fields. Yeah, that’s a smart API!
But
But you know what? You just don’t need this smartness.Stop for a while and think: couldn’t it done easier? Of course it could!Why do you need reflection? Why loose compile-time check of getter names? Why bother with handling reflection (checked) exceptions? Dude, just use getters!
Finally
The final solution didn’t use reflection and was not smart - it was simple.The following is the typical controller code for logging user action:
Action action = new Action("Buy a ticket")
.add("PersonCode", user.getPersonCode())
.add("PersonName", user.getPersonName())
.add("EmailAddress", user.getContactInformation().getEmailAddress())
.add("Language", user.getContactInformation().getLanguage());
LogUtil.log(action);
As simple as possible.
Archived comments
Ivo 2011-10-19T12:24:13.531Z
Why would you implement this programmatically anyway? IMHO this is a clear case for aspect usage …
Our recent stories
Partnering with Nicigas in their Energy Development Business
In Codeborne we have built energy information systems in Estonia, Sweden, Norway, Denmark, Luxembourg, Austria, and Japan. With Nicigas we combined our expertise and skillset to create something new on the Japanese market.
From wine tasting to digital innovation- the birth of the Wine Experience Club
We recently sat down with our client, Rait Maasikas, to go deeper into the story behind one of our more unusual recent projects- the Wine Experience Club.
Innovating the Austrian energy market with Spotty Smart Energy Partner
Spotty Smart Energy Partner GmbH, an Austrian energy provider, partnered with Codeborne to enhance their services and bring innovative energy solutions to the market