This anti-pattern is about Using String instances all the time instead of more powerful objects. This is a special case of primitive obsession.

Examples

Here are some flavours of this anti-pattern:

  • String as keys in a Map: I have seen calls to toString() on objects just to use their String representation as a key in a Map: map.put(myPerson.toString(), « someValue »).
  • String as enum (« In Progress » , « Done », « Error »), with tests using equal() to trigger the corresponding logic.
  • Array or Collection of String to mimic a data structure, in which case the ordering matters: {« firstname », « lastname »}.
  • String with a special format that makes it parsable: « value1_value2″, but used all over the place as is, with parsing code all over the place.
  • String in XML format used everywhere as is, rather than a corresponding tree of objects (a DOM); again there is a lot of parsing everywhere.

The problem

string_obsessionWhy not use « real » Java objects instead of Strings? Value Objects would be much easier to use, and would be more efficient in many cases, whereas String obsession comes with serious troubles:

  • Repeated parsing is CPU-intensive and allocates a lot of new objects each time
  • The code to parse and interpret a String must be spread all over the code base, leading to clutter and plenty of quasi-duplication
  • When used to represent meaningful domain concepts, Strings have no method dedicated to the business. The domain operations must be managed elsewhere and selected with conditionals; on the contrary, using value objects makes your life easier everytime you use them.
  • String values also need to be parsed to be validated. String values do not catch potential issues early, they will only be discovered when really used; on the other hand, value objects can be validated and can catch issues as soon as they are constructed

Solution

Use Value Objects, that are immutable, with efficient and safe equals() and hashcode(), the convenient toString() and every useful member method that can make them easy to use and. On inputs, convert the incoming format (e.g. String) into the corresponding full-featured object as soon as possible, and use the object as much as possible. In practice the objects can be used everywhere, everytime, as long as they remain within the same VM.

Why the String obsession?

Sure, there are some reasons why some people favour Strings rather than creating additional objects:

  • String are already available in i/o, hence you may consider it is memory efficient to just keep them
  • String are immutable, behave well as keys, and are easy to inspect in debug
  • You may assume that i/o represent the majority of cases in the application
  • You may consider that creating additional value objects mean more code therefore more effort and more maintenance

I strongly believe all these reasons are short-sighted, if not wrong. The burden of having to interpret the business meaning of a String each time is definitely a loss compared to creating a object with a meaning as soon as possible in i/o and use the object and its methods thereafter. Even for persistence and on-screen display, having an object with methods and accessors make our life easier than just using Strings!

Share/Save/Bookmark

Comments are closed.