Jump to:

23368 Posts in 18143 Topics by 2863 members

General Questions

SilverStripe Forums » General Questions » Instanting Objects

General questions about getting started with SilverStripe that don't fit in any of the categories above.

Moderators: martimiz, Sean, biapar, Willr, Ingo, swaiba, simon_w

Page: 1
Go to End
Author Topic: 218 Views
  • Bonner
    Avatar
    Community Member
    19 Posts

    Instanting Objects Link to this post

    I have a query regarding the various ways you can create a new instance of an object. I was wondering why there are 4 ways we can create an object in SilverStripe:

    1. Using the singleton function
    2. Using dependency injection
    3. Using a Factory
    4. Autoloading

    Is there a specific reason there are so many options?

    I am aware that autoloading allows multiple instances of the same class, and dependency injection gives you the option to reuse an object or create a new object, but then we have a Factory and a singleton function.

    In my view, it is all a bit of a mess at the moment.

  • martimiz
    Avatar
    Forum Moderator
    1067 Posts

    Re: Instanting Objects Link to this post

    If iyou need to instantiate an object 'by hand', in version 2.x, you'd use

    $myobj = new MyObject(...);

    Of course this still works in version 3, but there's an alternative: the static factory method create(). It lets you instantiate objects in a lazy fashion, which should lead to better performance and it allows for the chaining of methods, like:

    $myobj = MyObject::create(...)->setSomeValue($value);

    (Chaining now works in core, but for it to work in your own modules, you'd have to make sure your objects methods return $this)

    A singleton object is special in that it is only instantiated once. if you try to instatiate it again, it returns a reference to itself. Use it in situations where you don't want/need to create multiple instances of the same class. Google for examples. This is basically it, not really a mess.

    As for the Injector class, to which I think you're also referring:
    http://doc.silverstripe.org/framework/en/3.1/reference/injector

    This is a special class, targeted at far more then just creating a simple object. So although you could use its create/get methods to create objects/singletons, you probably wouldn't, if that is all you were going to do. As for creating Sevices/using a Factory - I guess that's far beyond the scope of simply instantiating objects

    I hope this answers some of your questions

    Martine

  • Bonner
    Avatar
    Community Member
    19 Posts

    Re: Instanting Objects Link to this post

    Hi martimiz

    Thanks for your response, it confirms what I thought.

    So that said, can we look at the theory and logic behind each method.

    I'll start with DI, you said:
    "So although you could use its create/get methods to create objects/singletons, you probably wouldn't."

    My question is why wouldn't you?

    As you have made a statement about two different subjects, I will cover each within their own merit from my point of view.

    You wouldn't use DI to create an object, because if I'm not mistaken, autoloading takes care of dependency injection, meaning you can just create a new instance of a class like so:

    $myobj = new MyObject;

    You wouldn't use DI to create a singleton because instead of using singletons you would just ensure encapsulation to start with.

    So the Injector class is obsolete in my view.

    Chaining is a neat feature, but it is badly abused. In my view, a method should return a value produced by the method and in relation to what the method has just done. If a method does one thing AND another thing, this is a code smell. A method doing something AND returning an instance of the object is a code smell.

    Chaining should be used to pass objects that are requested by calling the method, take the following example:

    class SessionStateHandler {
    public function save () {
    // xxx save the session
    }
    }

    class HttpContext {
    protected $session; // Instance of SessionStateHandler;

    public function getSession () {
    return $this->session;
    }
    }

    class HttpApplication {
    protected $context; // Instance of HttpContext

    public function getContext () {
    return $this->context;
    }
    }

    $application = new HttpApplication;
    $session = $application->getContext()->getSession();
    $session->save();

    I can't see how using a factory leads to better performance over the standard convention of the following so can you please explain how it does:

    $myobj = new MyObject;

    Do you get where I am going? If I'm not making sense please say, as I'm trying to dumb down the examples and explanations to make my points more concise.

  • Marcus
    Avatar
    Administrator
    86 Posts

    Re: Instanting Objects Link to this post

    So the 4 main mechanisms you've mentioned

    1. Using the singleton function

    Only use this when you want to retrieve the same global instance of a particular object used everywhere else; Given the 'global' nature of it, it's probably best to avoid using it if you can. Using the dependency injector to instead wire in a dependency would be preferable.

    It's effectively shorthand for doing $injector->get('Object');

    2. Using dependency injection

    The dependency injector handles the creation of the object, and subsequent creation/association of any dependent objects into place

    3. Using a Factory

    Using the MyObject::create($param) notation is effectively just a shortcut for using $injector->createWithArgs('MyObject', $param), so is using the injector under the covers.

    4. Autoloading

    By "autoloading" are you referring to PHP's __autoload mechanism? This doesn't have anything to do with the dependency injector at all. If you create an object using `new MyObject()`, none of its defined dependencies will be wired up.

    Basically, methods 1 and 3 are shortcuts to the underlying dependency injection functionality.

  • Bonner
    Avatar
    Community Member
    19 Posts

    Re: Instanting Objects Link to this post

    Globals are very dangerous, in my view they should not be used at all when developing applications that will be used in production environments.

    PHP provides autoloading, so why reinvent the wheel by writing an Injector class?

    "Using the MyObject::create($param) notation is effectively just a shortcut for using $injector->createWithArgs('MyObject', $param), so is using the injector under the covers."

    If this is the case then I've already pointed out why I think that this is pointless due to autoloading.

    "By "autoloading" are you referring to PHP's __autoload mechanism? This doesn't have anything to do with the dependency injector at all. If you create an object using `new MyObject()`, none of its defined dependencies will be wired up."

    Autoloading ensures the class is available for use so we don't need to use composer which then allows for native DI like so...

    class SessionStateHandler {
    public function save () {
    // xxx save the session
    }
    }

    class HttpContext {
    protected $session; // Instance of SessionStateHandler;

    public function __construct (SessionStateHandler $session) {
    $this->session = $session;
    }
    }

    class HttpApplication {
    protected $context; // Instance of HttpContext

    public function __construct (HttpContext $context) {
    $this->context = $context;
    }
    }

    $session = new SessionStateHandler;
    $context = new HttpContext($session);
    $application = new HttpApplication($context);

    What is wrong with the above? What is the Injector class trying to achieve, what problems is it solving, etc.? Maybe including an example of why you would use the Injector class over the above might help explain what the point of it is because at the moment it isn't making much sense at all. The documentation on what the Injector class does isn't very clear either because the examples don't present a problem, and how the Injector class solves the problem.

    So in my view, the singleton function is obsolete and should be deprecated. The Factory should be deprecated, and we should only use one standard way of achieving DI, and at the moment I can't really see a case for using the Injector class.

  • Bonner
    Avatar
    Community Member
    19 Posts

    Re: Instanting Objects Link to this post

    In an effort to find harmony and peace of mind, are there any more thoughts on this?

    218 Views
Page: 1
Go to Top

Want to know more about the company that brought you SilverStripe? Then check out SilverStripe.com

Comments on this website? Please give feedback.