Object created will be done by another method. But why?

Hi,

I was skimming a book on object creation and one point got my attention. It said like this:

“Object creation will be done by another method, such as an init()”

So this:


$user = new User();
$user->init($fname, $lname, $age);

Instead of:


$user = new User($fname, $lname, $age);

But why? The book gave a vague answer and somewhat questioning. Somewhere in the lines of “the object should at least be created”. I understood that as a malformed object is no use to the application, which makes sense, but if you can’t create the object correctly from the start, then why create it in the first place?

I don’t see the benefit of using one over another:


class User {
  private $fname;
  private $lname;
  private $age;

  //example 1
  public static function getById($id) {
    list($fname, $lname, $age) = array('John', 'Doe', 35); //normally from a DB
    
    $user = new User();
    $user->init($fname, $lname, $age);

    return $user;
  }

  //example 2
  public static function getById($id) {
    list($fname, $lname, $age) = array('John', 'Doe', 35); //normally from a DB
    
    return new User($fname, $lname, $age);
  }
}

Can someone shed some light? Thank you.

Author’s an idiot, burn the book :smiley:

Seriously.

The only similar pattern that sees actual use is the factory pattern.


$user = $userFactory->fetchUser($fname, $lname, $age);

The reason is that the user factory decouples the exact class that will be serve as a user.


class UserFactory {
  protected $userClass = 'BasicUser';

  public function fetchUser($fname, $lname, $age) {
    try {
      $user = new $this->userClass($fname, $lname, $age);
    } catch ($e) {
      // handle problems
    }
    return $user;
  }
}

The Factory object can negotiate any errors that might arise out of the class at construct time that may result in a malformed object. More importantly since the actual class that handles the user is now decoupled, you can have a separate user class for administrators than basic users, all of which extend off the basic user case.

Having a an init() function separate from __construct that has to be called before the object can actually do anything is what I disparagingly refer to as “busybox” code. It’s stupid - don’t do it.

One other advantage of Factories is they can handle the dependency injection. For example, if the User needs a db object then the Factory has the job of providing it.

I thought this might be a TDD way. I’m currently working on a book an intro to TDD so I’m wasn’t able to tell at the time if this was the reason why he said create some sort of an “init” method to properly create the object.

tdd?

test driven development.

I thought it was some type of technique used to not run into any problems while testing. I don’t really know as I’m in the begining chapters.

Factory pattern would be that, what the author is proposes with init() as a separate method is nonsense.

There could be a good reason sometimes to use init() method. basically it lets you to set values on already existing object.
Sometimes you may find that you need this pattern, then use it, otherwise just pass all values to constructor and create an object the easy way.

Yes, you right, also about TDD, the init() may be used for some sort of tests that we don’t know about.

I’m using TDD for a few projects, and I’ve never ran into the need to create an additional constructor: one will do just fine. As long as you keep in mind not to do too much in a constructor (e.g. setting values is okay, but connecting to a database might not be), there is no reason the testability of the object gets worse than by introducing an init( ) method, which does exactly the same.

The testability gets worse by introducing the init method. You now need to test the object has been fully initialised and is ready to use before doing anything else.

Agreed. Init is a clear sign the author doesn’t know what he’s doing IMO. If an object’s construct is complicated enough use a factory - the only thing Tom and I differ on about this is that I don’t think extremely simple objects warrant a factory, but that’s a YMMV topic anyway.

Hi…

init() is probably bogus. I can’t think of any use for it, so if it arises in real life the need would be extreme - in which case, why is the explanation vague?

It also has nothing to do with TDD.

yours, Marcus

@lastcraft

Well it said something like “We’re going to agree to use init() to properly create an object” and then “To make sure that all objects are properly created”

That just left me asking even more questions than answering. :injured:

Great feed back btw, thank you all.

Make sure you read it carefully,

  • maybe hes talking about some static class that has no constructor (and even then, it’s kind of bad for TDD)…
  • maybe hes talking about the singleton pattern, and he wants you to do something like: $obj = Obj::getInstance(); or something (seen that in other languages than php)…
    If hes not, burn the book…