Ridiculous class and interface names, fear of change and the new operator

One of the important tasks when designing software (or probably anything for that matter) is creating appropriate/correct/reasonable names for things, whether it be for classes, interfaces, methods or variables.  Why?  Simple… When someone reads your code they should ideally require little additional documentation, third party contact or alternative education/context to work out what something means, or determine it’s purpose.  Perhaps it’s not always the case, but it’s a good goal.

While it may seem easy experience shows that creating reasonable names often requires a lot of thought.  In the Coherence team we invest a lot of time in finding names and defining the language of concepts, not only for ourselves, but also for external groups that depend on our code (like customers). Likewise in the Coherence Incubator team, we critically review the names we’re proposing for things, because we know that customers (and competitors) will read our code.  Many a “warm argument” has occurred due to the naming of things, and to me it’s both one of the toughest and most enjoyable things to do.  It’s a critical part of our design process.  There’s nothing like finding a good name to describe something elegantly.  So much so, we often invest time searching dictionaries and thesauruses just to find inspiration.  To me… a name is worth a thousand words.  Unfortunately we don’t always get it right, but we do try, and we try very hard.

When I look at a problem, design or have to reflect on an existing architecture, I start with the names of things.  If I find a name I’m uncomfortable with, or something that requires a lot of explanation, I start to challenge that design is possibly wrong.  ie: It’s overly complex or overly generic and with more thought it could be radically simplified.  Why?  I think this steams from my strong belief that the purpose of writing (commercial) software is to deliver a solution, and with that, there needs to be simplicity (such that we can deliver on time and provide value).   This doesn’t mean a lack of features. It simply means delivering something that is easy to use and is suited for purpose.  It’s about keeping customers happy.  Like Coherence.  Small, remarkably simple yet powerful without a massive API.

SIDE NOTE 1: Sometimes thing’s just can’t be simple… but it’s a good goal to ruthlessly attempt to achieve.

Personally I believe one of the biggest challenges when naming something is the fear of change and the apparent need for developers to “allow for the future”.  Delivering software is a tough enough job as it is, but having to design in solutions involving predictions about the future,with an uncontrollable urge to make things extensible only makes things much harder and more complicated. When I look at a system I intentionally try to limit the amount of “framework building” (accept when asked to develop a framework that is), and instead focus on providing a solution as soon as possible.  I strongly believe that the future is for another version.  ie: Don’t attempt to build 2.0, 3.0, 4.0 etc into 1.0.   Ruthlessly protect and deliver version 1.0, because that may be your last version.

So how does this related to names?  Let me give you a simple example.

Say I need a class to represent a Person.  It has a few attributes, say, First Name, Last Name and Address. You know, it’s nothing to complicated.  That’s all I really need for version 1.0.  While it sounds simple, here’s often what I see happening;

1. Developer decides to model this as a simple Person class.  Great.  Satisfies version 1.0 requirements.

2. Then out of fear for the future, change, the pain change can inflict and the remote posibility that they may need alternative implementations, they change their mind and instead introduce the Person interface (in .NET land they’d create IPerson) to represent the Person as an abstract concept.

interface Person {
   public String getName();

Not a big change, so seems reasonable.

3. In Java they’d declare the setters/getters in the Person interface, then create a concrete class for Person, calling in something like PersonImpl.  (In the Coherence Engineering group we’d call it something like DefaultPerson or SimplePerson).

4. Now that they have an interface, the question arrises “how should you create an instance of a Person?”. That is, although we have the PersonImpl class, “we should not expose that to the core of the application, so we need a way of hiding creating instances”.  (Unfortunately most languages don’t allow overriding the behavior of “new” like this “new <interface>”. It would be great if you could tell the compiler, hey if you see “new Person” I actually mean “new PersonImpl”).  Anyway, to solve this problem and keep the code “pluggable”, they decide it’s time to use the “Factory Pattern” or potentially the “Builder Pattern” to create Person instances.  Hence the PersonFactory is born.

5. But… what if we need to replace the Factory?  Ok… easy… “just introduce a PersonFactory interface, and then introduce a PersonImplFactoryImpl class to create the Person instances as we need them”

Can you see how the names are starting to sound strange/ridiculous?  What once was a simple problem to solve, has now blossomed into the Person framework.  The names are starting to look ridiculous and to me, this gives the first indication of over-genericizing.

SIDE NOTE 1 (revisited): It’s very possible that something like this may actually be needed, but more often than not, it’s pretty rare.  Sometimes you just can’t simplify something that is intangibly complex.

SIDE NOTE 2: This is not over-engineering.  Over-engineering occurs when you make a product unnecessarily stronger or more durable.  The above does not increase strength (performance, availability, reliability or scalability).  It increases flexibility for the future and often a requirement that no one demands up front.

But we’re not finished yet.

6. The last and often ugliest of all steps is to consider how to create instances of the PersonFactory interface.  And you guessed it… it’s time for another factory, the PersonFactoryFactory interface.

Of course this sounds even more ridiculous, so it often becomes the PersonFactoryService 😛

So what went from a simple Person class and using the new operator to create instances, we now have a completely generic pluggable Person framework requiring the Person, PersonFactory and PersonFactoryFactory interfaces (an SPI if you like), together with the PersonImpl, PersonImplFactoryImpl and PersonImplFactoryImplFactoryImpl classes (to be completely correct)… just to say person.getName() and person.setName(…).

SIDE NOTE 3: I’m guessing you could simplify the factory names to PersonImplFactory and PersonImplFactoryFactory, but it’s not much better.

With this simple example it’s easy to see why inversion of control (IoC) has taken off.  In any system with 5 or 10 artefacts like this the complexity of wiring together an application is so great that it’s hard to know where to start…. and why?  All essentially so we can get back to saying something like “new Person”, but without being committed the Person implementation. No wonder we have the term “plain old java objects” (POJO), just to tell people “you can use the new operator on this class”.

Are we crazy to continue to build systems like this?  Isn’t OSGi (et al) making this any easier?  Spring has tried to, but even it’s download and dependencies are getting massive.

Perhaps the world is no longer as simple as it use to be, wants to be or needs to be.

There is help though… If you’re stuck for a class/interface name, you should check out http://www.classnamer.com

PASSING NOTE: The Java Beans specification and thus the introduction of the term Bean (essentially to mean a Object with getters and setters) often makes naming things even more ridiculous.  While I really like the Bean spec, it can be brutal on class names.

Person -> PersonBean
PersonFactory -> PersonBeanFactory (or PersonBeanFactoryBean)
PersonFactoryFactory -> PersonBeanFactory (or PersonBeanFactoryBeanFactoryBean)


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s