Why do Data Classes Smell?

Not for 'how-to' coding questions but PHP theory instead, this forum is here for those of us who wish to learn about design aspects of programming with PHP.

Moderator: General Moderators

Xoligy
Forum Commoner
Posts: 53
Joined: Sun Mar 04, 2007 5:35 am

Post by Xoligy »

ole wrote:With an array you have to remember what the keys are.
You do with a class as well...? Unless your referring to your IDE's code insight feature, but surely that's a problem with the IDE, not PHP.
ole wrote:You can add new keys (through typos) without be notified of your error.
As for the typos, you should always code with warnings on, then you'll get notices if $array['bob'] doesn't exist.

I don't see using classes as a valid way of correcting your mistakes. Not only is it a lot more code, but I'm pretty sure classes use more resources.

Surely those variables belong to the class that is going to be manipulating them. Unless of course you intend to extend the rabbit with other classes that affect the rabbit, I can see point in that.
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

Xoligy wrote:
ole wrote:With an array you have to remember what the keys are.
You do with a class as well...? Unless your referring to your IDE's code insight feature, but surely that's a problem with the IDE, not PHP.
ole wrote:You can add new keys (through typos) without be notified of your error.
As for the typos, you should always code with warnings on, then you'll get notices if $array['bob'] doesn't exist.

I don't see using classes as a valid way of correcting your mistakes. Not only is it a lot more code, but I'm pretty sure classes use more resources.

Surely those variables belong to the class that is going to be manipulating them. Unless of course you intend to extend the rabbit with other classes that affect the rabbit, I can see point in that.
I can see both sides. Languages like Java would use a class (HashMap) but I'd bet my left sock the only reason for that is because you cannot create an associative array. With a class you can type-check in one statement rather than checking for the existence of each variable, but then you have to create a new class for each collection of values. I'd only use a class if it's clear what your collection is for and if you're going to pass it around a bit.

I think old meant that $arr["foo"] = 42; won't throw any warning because it's an assignment... but then $obj->foo = 42; won't neither.
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

For strictly value object type stuff, I'd generally prefer passing an array around unless I'm trying to be totally object-oriented.

Possibly something like

Code: Select all

class Value
{
  private $values;
  public function __construct(array $valueNames)
  {
    foreach($valueNames as $valueName)
    {
      $this->values[$valueName] = null;
    }
  }

  public function __set($var, $value)
  {
    if (array_key_exists($var, $this->values))
    {
      $this->values[$var] = $value;
    }
    else
    {
      throw new UnexpectedValueException();
    }
  }

  public function __get($var)
  {
    if (array_key_exists($var, $this->values))
    {
      return $this->values[$var];
    }
    else
    {
      throw new UnexpectedValueException();
    }
  }
}
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

Passing an object around does have it's pluses in terms of scalability. You can easily extend it, you can add methods, it's (arguably) more readable. It's just unwanted fluff until the need for those things arises though. You're certainly reducing the risk of large re-writes of the code if the values are to be used all over the place.
User avatar
Ollie Saunders
DevNet Master
Posts: 3179
Joined: Tue May 24, 2005 6:01 pm
Location: UK

Post by Ollie Saunders »

You do with a class as well...? Unless your referring to your IDE's code insight feature, but surely that's a problem with the IDE, not PHP.
You can refer to the prototype:

Code: Select all

public function __construct($age, $weight, $cuteNess)
As for the typos, you should always code with warnings on, then you'll get notices if $array['bob'] doesn't exist.
does this produce a warning?

Code: Select all

$array = array();
$array['bob'] = 1;
Last edited by Ollie Saunders on Wed Mar 14, 2007 1:48 pm, edited 1 time in total.
User avatar
Mordred
DevNet Resident
Posts: 1579
Joined: Sun Sep 03, 2006 5:19 am
Location: Sofia, Bulgaria

Post by Mordred »

Begby wrote:I code classes like this a lot. Yeah you can use an array, but its not a fixed structure and since PHP is not strongly typed a class makes it harder to mess up.
Just to note that an object is not a fixed structure either, and that it is perfectly valid (in PHP and some other nice languages) to add members to an object, which are not present in its class.
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

ole wrote:does this produce a warning?

Code: Select all

$array = array();
$array['bob'] = 1;
No. Does this?

Code: Select all

$obj = new Rabbit();
$obj->bob = 1;
Does this?

Code: Select all

$array = array();
$x = $array['bob'];
Does this?

Code: Select all

$obj = new Rabbit();
$x = $obj->bob;
User avatar
Ollie Saunders
DevNet Master
Posts: 3179
Joined: Tue May 24, 2005 6:01 pm
Location: UK

Post by Ollie Saunders »

But this does:

Code: Select all

$flopsy = new Rabbit();
consider the constructor prototype.
User avatar
mikeq
Forum Regular
Posts: 512
Joined: Fri May 03, 2002 3:33 am
Location: Edinburgh, Scotland

Post by mikeq »

but then you could use the __set function to detect when someone is trying to set a property which does not exist and issue a warning/error, just as feyd's code pointed out.
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Post by Christopher »

This is all fine, but the source of the problem I think was the erroneous refactoring step "move in behaviour" that ole found somewhere. Ignoring the fact that it is impossible to move methods that don't exist ... I think it was probably not targeted at Value Object at all, but perhaps Transfer Object which is a Value Object in a specific circumstance and relationship to a set of other objects.
(#10850)
Xoligy
Forum Commoner
Posts: 53
Joined: Sun Mar 04, 2007 5:35 am

Post by Xoligy »

ole wrote:
You do with a class as well...? Unless your referring to your IDE's code insight feature, but surely that's a problem with the IDE, not PHP.
You can refer to the prototype:

Code: Select all

public function __construct($age, $weight, $cuteNess)
As for the typos, you should always code with warnings on, then you'll get notices if $array['bob'] doesn't exist.
does this produce a warning?

Code: Select all

$array = array();
$array['bob'] = 1;
" you should always code with warnings on" What's that supposed to mean? If I code with notices on, you can bet your right sock that I've got warnings on. Only an idiot would code with warnings off.

Code: Select all

$array = array();
$x = $array['bob'];
Creates a notice, as does:

Code: Select all

$obj = new Rabbit();
$x = $obj->bob;
So I don't see how your typo argument is valid.

Also, arrays have a lot more tools for manipulation. It's what they were designed for. It's a lot harder to search through an object for a variable's value. As for the constructor argument, you're making things extremely hard for yourself in terms of flexibility by having to predefine all your variables. Perhaps it would make more sense to spend those few seconds double checking you've spelled it correctly.

Apart from possible scalability (but you should have your software planned out and decide whether you'll need to extend the class in the first place) your only other reasonings are to prevent your bad mistakes. I don't see that as a valid reason of using a class. It's like using a table for layouts in HTML - unnecessary, slower, poor standards, and more footprint.
User avatar
Ollie Saunders
DevNet Master
Posts: 3179
Joined: Tue May 24, 2005 6:01 pm
Location: UK

Post by Ollie Saunders »

" you should always code with warnings on" What's that supposed to mean? If I code with notices on, you can bet your right sock that I've got warnings on. Only an idiot would code with warnings off.
I edited my post actually. I was quoting someone else but forgot to add the
tags.
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Post by Christopher »

Xoligy wrote:Apart from possible scalability (but you should have your software planned out and decide whether you'll need to extend the class in the first place) your only other reasonings are to prevent your bad mistakes. I don't see that as a valid reason of using a class.
I think using a Value Object is a different type of contract than using an array. They are simply different. For a classic C struct type data structure, neither are a perfect replacement and I can see one or the other as more appropriate in different cases.
Xoligy wrote:It's like using a table for layouts in HTML - unnecessary, slower, poor standards, and more footprint.
Uhhhh ... unless what you are laying out is tabular ...
(#10850)
Xoligy
Forum Commoner
Posts: 53
Joined: Sun Mar 04, 2007 5:35 am

Post by Xoligy »

By "for layouts" I meant to hold images and the like. I'm yet to find a layout that is tabular.
Post Reply