Fluent interfaces
At a recent project, we need to write code for extract some data from another system. Data come like a fixed-length text file. It’s not a file at all but for sake of simplicity let it be. It’s not a new problem to be solved. Alias, since more than ten years ago at same company programmers have to deal with few hundreds of different file formats everyday. They are used to do it this way:
... Customer c = new Customer(); c.setName = outputString.substring(10,70); c.setAge = Integer.parseInt(outputString.substring(80,82)); ...
Some fields need to be trimmed. Some need to be formatted, like a date for example. So, it’s not hard to guess how many code has been repeated. And come on, it’s not human-friendly put a lot of x.substring in all the code.Then, I wrote this way:
Definition File Example
...
output()
.field("name",60)
.field("age", 2).integer().valid(new RangeValidator(18,65))
.field("customer_since", 8).date()
.field("tags",30).occurs(10)
;
...
Of course,
...
.field("age", 2).integer().valid(new RangeValidator(18,65))
...
can be more fluent:
...
.field("age", 2).integer().valid().range(18,65)
...
But it requires change in API at each new validator. It’s a trade-off. At a range, for example, I prefer second way. In case of MyJustOnceUsedFancyValidator, I prefer first one. My API has both cases.Once it was defined, you could invoke that and get a Map:
...
Map output = myDefs.connect(inputparams);
Customer c = new Customer();
c.setName((String)output.get("name")); //No, we don't have JDK5
c.setCustomerSince((LocalDate)output.get("customer_since"));
c.setAge(Integer.parseInt((String)output.get("age")));
...
Now, definitions are separated from client code. Extracting code are isolated too. This code need to be wrote just once. Client don’t know what is going behind the scenes. It sees just a Map. Abstraction was improved. Code is now a bit more human-friendly.Better?
No comments yet
Leave a reply

