klekker has asked for the wisdom of the Perl Monks concerning the following question:

Dear Monks,

I've got a question regarding KISS (keep it simple and short) in general and not necessarily related to perl.

Some time ago I was arguing with a former colleague about extending a class by inheritance: we had a class that contained an instance variable for each form element (objects) on a webpage for a multitenancy java webapplication. Now it was necessary for two tenants to have different form elements.

Since it was java and actually nobody had strong feelings about letting eclipse generate myriads of getter and setter in a single class, one (my) suggestion was:

1) No big deal... create a new base class and two inheriting classes. Write a getter for every necessary component in the base class (some might be abstract) and for the extra components the required getter in the subclasses. Advantages: you see at first glance which components are different/overridden

the colleague suggested to

2)implement a container in the old class that contained all necessary elements (objects) for this old class. And with this container, the constructor in each new subclass was responsible for removing and adding the appropriate elements. You need one class less...

I was not involved in this project so I didn't implement my solution. But nevertheless...

Solution '2' is shorter in loc but in my opinion it is not simpler. And in my opinion '1' doesn't hurt the DRY principle much more than writing getter and setter. Well... '1' is not as 'smart' as '2', you can't write additional code to show how clever you are (I might be a little bit biased...) but you can finish your task faster and imo it's easier to understand . And even if you had a common base class with this container in case '2': you would have no way to ensure that a necessary element is in this container without writing additional code.

But his arguments where that solution '1' would add too many methods and that his approach is more -uhm- generic. In my opinion his solution is like 'packing your tennis bag by packing your soccer bag first and then removing all non-tennis parts before adding the tennis-stuff...)

I still would prefer solution '1'. But I'm also interested in different point of views. So I'd like to ask my esteemed fellow monks: what's your opinion?

Thanks in advance,
k

Replies are listed 'Best First'.
Re: your definition of KISS
by JavaFan (Canon) on Feb 07, 2012 at 22:40 UTC
    From your description of the problem I get is that you have a bunch of variables, and you want to access them. You're also want a KISS solution, and then both you and your coworker discuss OO solutions.

    The KISS is to use a struct. Or in Perl parlor, a hash.

    Now, there may be all kinds of good reasons to use objects, but you want a KISS solution, you'd use a hash. There will be no DRY, with a hash you have 0 setters and getters.

      Well, somehow we got stuck keeping the existing OO approach since it was already there; sometimes it's hard to get a view from the outside by yourself...:/

      My greenfield approach would have been something like
      if ($config->hasFeatureA()) { // show feature A or put it into the container }
      (Depending on the project and just to get the idea).

      Thank you for your answer and sharing your point of view,
      k
Re: your definition of KISS
by wrog (Friar) on Feb 07, 2012 at 22:25 UTC
    The question that matters:

    How much work will you have to (want to) do when you get a 3rd tenant?

    Figure there's almost never just two of anything -- and there should probably be an acronym for that. Or if there really will never be a 3rd tenant, ever, then arguably both options are are a waste of time.

    The answer for your situation depends on stuff you haven't specified, e.g., how much are the various tenants are likely to differ, how much pain is involved in writing a new class for (1) vs. a new constructor call for (2), or the extent to which it's appropriate that new tenant configuration be data-driven rather than code-driven (which would argue for (2)).

    Not knowing any of the details, I would fall back on my own prejudice that I generally find inheritance to be overused (and would thus prefer something like (2))...

    ... it may seem "simpler" to just define a new subclass so that you can re-use a given piece of code, but if this governs how your hierarchy develops, then you risk ending up with a spaghetti hierarchy that's actually more difficult to maintain, whereas if you take the time to figure out where the code in question actually needs to live (so that it'll be where people are expecting to find it), that makes life simpler in the long run.

    And one can, of course, take this too far and waste time pre-designing for cases that are never actually going to arise. YMMV

      Thank you for your answer!

      I agree with you about the "spaghetti hierarchy". They 'inherited' the "spaghetti hierarchy" in some parts already because it is an old legacy project.

      So in my experience it is less difficult to judge if a subsubsubsubclass already contains a special form element or not, if you take the getter-approach (1). And if your IDE is fancy enough, you almost get this information for free.
      At least it is easier to see (for me) than 'subclass removes A,B and adds C, subsubclass removes B again and adds E... now what does subsubsubsubsubclass contain' as described in (2)

      Well, the application design is not really a good example for customer related configuration and I would pursue another and less hardcoded approach, too.

      So regarding this context I should have asked which of these two solutions is less painful.

      And I completely agree: there should probably be an acronym for that! ;)
      k
Re: your definition of KISS
by Anonymous Monk on Feb 07, 2012 at 17:04 UTC

    I can't say either approach is appealing :) as both seem to miss the real problem, object oriented design, how to model tenancy (i rent you rent we rent a dwelling, not Multitenancy principle of software architecture )

    From what little I can understand, and from what I've seen over the years, the common pattern , often seen in database tutorials, is to have a collection, a tenant is a tenant (name, contact info, financials...), addTenant, removeTenant ... just rows in a tenants table

      Thanks for your answer.
      Multitenancy is not relevant for the problem; there are -and I agree with you- better ways to model multitenancy (as NOT in i rent, you rent...)
      Important for me was just the inheritance-part.

      k
Re: your definition of KISS
by locked_user sundialsvc4 (Abbot) on Feb 07, 2012 at 21:30 UTC

    Both of these sound quite ugly, but your colleague’s suggestion might have some useful merits if we could say, for example, that “the essential difference between the two (public) classes is the particular set of features that they do or do not expose (said features being taken from a common bag).”   If this way of thinking about the problem proves useful, then it suggests that the common-ancestor class is never meant to be publicly exposed or used; it has no un-protected getters or setters of its own.   But it does provide “the bag of tricks” used in various ways by any of its descendents.   The ancestor provides the universe; the descendents provide the various accessible heavenly bodies.

      Yes, I didn't feel comfortable with both 'solutions' either. But the worst feeling I had with the 'bag of configurations'.
      The ancestor provides the universe; the descendents provide the various accessible heavenly bodies.
      :)

      Thanks for your answer,
      k