5

After looking at the core data type for frameworks that deal with unstructured data in java:

the common theme seems to be that data are first de-serialized into Map, then transformed into an given class by reflection.
So this raises the question, why not just work with these Map (or sub-type of map) directly? You can extend Map and create your own sub-type, and you will still have all the benefit of OO programming.

Edit I am not concerned with the cost of deserialization, but the flexibility that Map offers when dealing with unstructured data. By this, I mean not having to define a class that the data can be deserialized into.
Edit 2 I am more interested in the "why not (disadvantages)", since the framework I mentioned already demonstrated that it could be done.

  • 8
    It doesn't beg the question it raises the question. Begging the question is a logical fallacy in which one assumption depends on another being true that depends on the first being true. – Michael Brown Feb 21 '12 at 16:38
  • duly noted, updated accordingly. – ltfishie Feb 21 '12 at 17:16
7

The convenience of working with a strongly typed object sometimes outweighs the cost of serializing to/from that object. For instance I usually use JSON to transmit MVVM ViewModels over the wire. Once the data is deserialized, I can take advantage of the functionality embedded in the ViewModel class that works on the data. If I were just passing around dumb data, then I agree it probably makes sense to forgo that extra step.

What is dumb data? To me dumb data is a class that has nothing on it but simple properties/fields and any logic is provided by other classes that consume them (cf. Anemic Domain Model or Data Transfer Object).

If instead you are (de)serializing intelligent objects (like my ViewModel example), there is much more to gain. This goes beyond just validation. If you look at the argument for Rich Domain Models versus Anemic Domain Models, the case is that we are putting the logic that operates on the data with the data itself. That's the entire point of using an Object Oriented language. Presumably you're passing the data around to have some function performed on it. Serialize it into a rich object and put the function on that object so all you have to do is invoke the function. I've touched on the idea in a blog post here.

  • Thanks for your answer. Can you expand on what you mean by "dumb data"? – ltfishie Feb 21 '12 at 17:22
  • Thanks for the update. So would unstructured data be the same as dumb data? Can you list some other gains besides validation? – ltfishie Feb 21 '12 at 18:00
2

... why not just work with these Map (or sub-type of map) directly? You can extend Map and create your own sub-type, and you will still have all the benefit of OO programming.

Good question. Why indeed? In dynamic OO languages (e.g. Ruby, LUA, Javascript, Python, Perl, and others) every object is basically just a map. You can add new properties and methods to objects at run-time. It's very powerful, but you give up compile-time validation of method calls. It's just not the Java way.

2

There is no real reason--you CAN work with hash maps instead of classes and sometimes it makes perfect sense. I tend to use hashes instead of classes for any of the following cases:

  • All the values are of the same type (String)
  • I never directly or individually reference the values in code.
  • Tooling (like the stuff mentioned in the question)

The advantage that a map has over a class is that it's very easy to generically deal with a record at once. Once you put the values into a class you tend to reference the values by name making iterating over them more difficult.

The common alternative to Hashes in this problem space is Java Beans. Beans are a class with just properties and setters/getters for each property. Some people call these pojos, but pojos have no restrictions so if your class is intended to have just setters & getters call it a bean, not a pojo.

Both Beans and Maps are examples of Michael Brown's awesomely named "Dumb data", and that is an issue separate from the choice to use Maps or Beans.

There are two big problems with "Dumb Data" of both flavors, the first is that you need meta-data to know how to use it (Like how to bind it to a GUI control or a database column name or validations)

With maps you have to solve the meta-data problem with some external data file--XML or config files or something--you can intuit a lot of what you want to know (like assuming the column name in the DB matches the key name in the map) but I always seem to need some data.

With beans a neat solution has popped up--annotations.

An annotated bean can work like a map since you don't directly access variables by name, you just iterate over annotated fields. Annotated beans offer an improvement as well because the annotations to define all the meta-data in-line rather than requiring a separate description. This is how most of the ORM tools currently work--but you can create and use your own annotations pretty easily.

The second problem is harder though--it's that the data separated from code--you can't add business methods to a HashMap OR a Bean. This means they are not Objects, they are both more like data structures. They will break ALL your OO code/design if you use them directly--and they will break it in really infectious and hard-to-fix ways.

Normally with OO code you are not supposed to ask your object for data, you ask your object to do something with it's data for you. How on earth do you make this work with "dumb data"?

Lately my solution is that any "Dumb data" used directly by my code has a "Helper" class. As soon as I pull it from the DB (or wherever) I encapsulate it in it's helper class and never expose it to the rest of my codebase. any code that accesses the bean has to go through the helper class, any methods to read/modify/comprehend the data in the bean is put into the helper. Note that I'm not talking about getters and setters either--avoid those wherever possible--they are still cases of "Asking for the Object's data".

After adding this helper, it becomes obvious where to put a lot of code that you used to have distributed throughout the rest of your codebase (Often duplicated). Now you ask the helper class to do something, it interacts with the bean to do it.

I've even had separate wrappers implement business logic on the server and GUI logic/validations on the client each wrapping the same core "dumb data".

I think the most important distinction is not between Maps and Beans, it's between Classes and Dumb Data. Once your dumb data is encapsulated in a class, it's actual implementation (Bean, Hash, ???) is not even very interesting...

  • Well, "it's that the data separated from code" - this is exactly what Functional Programming does :) – Dima Fomin Dec 8 '18 at 22:07
  • Functional programming has it's ideal use case. So does OO. So does shell scripting. If you only have one tool, you'll eventually try to drive a screw in with a hammer. OO's power is organizational and is best applied to huge codebases. Functional programming is great at keeping bugs out of heavily threaded code. Scripts are good for throwing together a working, runnable deployed solution in 2 minutes. – Bill K Dec 10 '18 at 16:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.