tags:

views:

238

answers:

5

Let's say that you are setting up a POJO.

What do you define when you setup the class?

Here's my list

  • Constructor to create an object with supplied fields (so that I can make fields final and hence immutable)
  • toString
  • equals
  • hashcode
  • implements comparable
  • get methods (where applicable)
  • [Optional] copy constructors for mutable fields - to guarantee immutability of the class
  • [Optional] Define interfaces to access fields and methods.
  • [Optional] implements Serializable and implement a versioning scheme.

Is this overkill or sound engineering? Anything missing that you would add?

A: 

It all depends on what the object has to do. For example, if the object is mutable it shouldn't implement equals and hashCode or be comparable. If it is never going to be serialised, there's no point in implementing Serializable and worrying about versioning. If the object is immutable, there's no need for a copy constructor.

I usually start with an interface that defines what some other object in the system wants the new object to do. Implementing that interface will "pull" the rest of the class into existence.

Nat
+5  A: 

If I know what I want to do usually write a test first and then write the class to make it run.

boxofrats
+1  A: 

I'm assuming that because you mentioned a versioning scheme, that we're talking about persistable classes.

I'd say you have a nice list there, but (depending on your ORM engine), I also tend to determine what values (other than the autoincrement ID), define the 'uniqueness' of any record.

I only mention this because hibernate has weird behaviour with Sets, if you use the ID in hashCode, because it is liable to change halfway through the process.

Also worth noting that it's worth your time to look at which collections are going to be Lazy or Eager, especially for the toString method (which may cause Lazy-Inits if you do a toString when you are detached from the persistence context).

Chaos
We are not using an ORM. We use serialization to that we can persist results to the file system as backups and archived data sets.
Fortyrunner
I'd be interested to see how you get around serialVesionUID mismatches, or handle changes to the serializable class over time. I.e. if your class changes, how do you restore from the 'backup'?
Chaos
+1  A: 

If you have a lot of fields, I would consider a builder - if immutability is that important.

In terms of is this overkill, it really depends a lot on the use case. If this an internal object for use in your own code or among a few close collaborators, I would say yes, it is most definitely overkill to do all of this prematurely. It makes evolving the design harder (think how much you have to change if you add one field) and most likely creates a lot of code that won't get used.

If, on the other hand you are looking at a larger, distributed project, or a public API, I think this hits the fundamentals. At a minimum, everything on this list should be thought about, even if it is ultimately decided that the class can be mutable for example, at least the decision was made intelligently.

Yishai
Its a large project and once stuff gets created - it doesn't tend to change. My main concerns are thread safety and collection safety. I also want to make things as easy as possible for Hotspot.
Fortyrunner
I agree that larger projects have dynamics that require more upfront design.
Yishai
A: 

Complete overkill. Apply YAGNI.

Design your classes to do what is required of them by client code, and perhaps test. Nothing more. If you are writing a library then of course you will need to be a bit more complete. Even so, as a rule, have at least three clients before you think about committing.

Tom Hawtin - tackline