4

I am wondering how are you guys handling an optional class properties. Let's say I have a product that can bud doesn't have to have a color property. Is that really the best way of doing that? Should I use null object pattern? Should I use strategy pattern maybe? Should I maybe use a decorator pattern here so I'll have Product and ProductWithColor? What if another property will be added and become optional?

<?php

class Product
{
    private $id;
    private $title;

    /**
     * @var string|null
     */
    private $color;

    function __construct($id, $title, array $color = null)
    {
        $this->id              = $id;
        $this->title           = $title;
        $this->color           = $color;
    }
}
  • 1
    The problem is real, but the example is bad. If you can have an unspecified number of related products, there is no reason why the number can't be 0, so an empty array does exactly what you want. It's when you have something that may have any color or "no color" that you have a design decision to make. – Kilian Foth Aug 15 '14 at 7:25
  • You're right, I'm gonna update the example. – acid Aug 15 '14 at 7:33
  • 2
    While null is workable, I generally prefer to use a more meaningfully named value/enum. For example, "Unassigned/Unknown/NotSet". Usually there's any number of reasons that something can be set to null (frequently because of some error condition) so you might not know why it is null. However, if you see the value as Unassigned/Unknown/Unset then you know you either forgot to assign it or you meant it to be that value. – Dunk Aug 15 '14 at 16:01
1

What if another property will be added and become optional?

I have done precisely this when I needed to inject some new functionality into that method. This does not break existing code; you gotta love that! In my case I bypass the new thing if the parameter is null.

I generally prefer to use a more meaningfully named value/enum. For example, "Unassigned/Unknown/NotSet".

I strongly disagree with this (quote from a comment). Doing this with a string is a big hassle - typos, casing, lack of type checking (I do C#). However if this was an enum then absolutely, have a "undefined" enum value (in C# I would have this correspond to zero because that's the default for enums).

Should I use null object pattern?

Not exactly. We're dealing with a single property, but the idea is the same. Make the optional/default method parameters behave benignly. For example, I set my optional string parameters to string.Empty (C#) so calling members on it does not blow up.

Should I use strategy pattern maybe? Should I maybe ...

No. Strategy is for polymorphic behavior - i.e. functions/methods with the same parameters (signature) on different types.

Optional parameters is a technique for creating concise method overloads.

I'll have Product and ProductWithColor

Well, if your design calls for that but I suspect not. Why are you letting a single optional parameter for a single function drive your design? null has "special handling required", sure, but so would any property with any value that had special meaning. Here it is just a mechanism for allowing client code to ignore color for the call. How is this a whole different class?

  • Your answer focuses on there only being 1 optional parameter. I'm sure the OP is looking for a general answer and is only using 1 parameter in their example to provide something tangible to work with. So what if there were 50 optional parameters instead of 1, would you give the same answers? – Dunk Apr 28 '15 at 19:27
  • 50 instead of 1? The answer would not scale per se (I've used 3 in one method so far - 50 method parameters is nonsense), but if 50 implies a whole class then the null object comes to mind. At this scale there must be consideration of overall design, and there are many possibilities. – radarbob Apr 29 '15 at 1:31
  • I chose 50 to be extreme on purpose because while it is general practice to "break the rules" for one or two special conditions when it is in the interest of getting the job done. However, the more interesting answer would be the general case. – Dunk Apr 29 '15 at 15:26
  • 1
    You seem to be getting at the Open/Close principle here. Frequent class modification suggests a a design issue of some kind. A coherent class would tend to not change - at best would change for one reason; i.e. it's responsibility changed. – radarbob Apr 30 '15 at 1:45

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.