Git Product home page Git Product logo

Comments (5)

MichaelBrenden avatar MichaelBrenden commented on July 17, 2024

Since our Day 1 using this gem, years ago, we've just always set shared = true.

"By far the most common real-world usage of Dependency Injection is to enable a single instance of an object to be accessible to different parts of the application." -- absolutely agree with this; this is 99.99% of how and why we use DI -- as a userspace/class version of 'globals'. It's a 'cheat' but awful truth is every single thing in webapp requires the config info, the server info, the user and ACL info, the memcache and database info...and usually on the way to end-feature request, there's a string of things all related to goal, all "inter-needed", and we've found DI to be perfect, easy, faaaast solution. Without DI and particularly Dice, our code and reality would be less.

That said, I prefer the default as-is, off, because it seems closer to purity. Besides, not so hard to set shared on...kinda makes you think about what's really going on. IMHO.

Thanks, Tom (and everyone who has been maintaining this gem), for a really wonderful tool!

from dice.

TRPB avatar TRPB commented on July 17, 2024

If you want that behaviour you can add a default rule:

$dice = $dice->addRules([
    '*' => [
        'shared' => true,
    ]
]);

However, it's worth noting that it's probably not desirable in most cases. Things like database connections and loggers, yes but otherwise Models, controllers, templates, framework infrastructure, etc should always be their own instances.

And, in a land where immutability is the default it makes even less sense to have shared instances.

If you think about it, it's only because in PHP each object is destructed and reconstructed on each request that we can get away with making everything shared. Imagine a desktop application where clicking a button displays the details about a customer's order in it's own window/tab: You wouldn't want the model, controller, window/tab, etc to be shared instances because you'd be displaying different records. Clicking a button on the window for one order shouldn't affect other windows (tabs, panels, whatever) you have open.

from dice.

Racso avatar Racso commented on July 17, 2024

Thanks for the answers!

Short answer: I discovered that specific use of default rules soon after posting my message. And you are right: it's easy to get the behavior. Thanks!


Longer answer (the discussion might become philosophical, so please feel free to skip it):

@TRPB I believe that, in most cases, even things like Models are shared by default: if a Controller and a View have a reference to a Model (or VM), it's very probable that it should be the same reference for both.

As for Controllers and Views themselves, I would say that it doesn't matter for them, because only the "front-controller" would have reference to them, and it would be exactly 1 reference. Let's imagine that this function represents the front-controller for a specific endpoint:

function frontControllerMethodForSpecificWebhook(WebhookController $controller, WebhookView $view)
{
    $controller->run();
    $view->render();
}

If Dice injects the Controller and the View (and each of them has some Model injected, probably the same Model for both), that will work, and it doesn't really matter if the Controller and the View are shared or not because nothing else should have references to them.

And IF we REALLY wanted to inject the Controller/View somewhere else for some reason, then maybe it would make more sense to get a reference to the same Controller/View you actually used to resolve the request, so you can do whatever you need with them?

Regarding your desktop example: I believe that in that case, neither option is the correct one: you should not have a single instance of everything, but at the same time you probably don't want a new instance of everything for every dependency you have. Depending on the context, you may want, for example, a "hierarchy-based DI", where elements of each window are injected with instances that correspond to that specific window (but they are shared in the context of that window!): one button might interact with a Model (through a Controller), and two Views might listen to events triggered by that same Model and display data accordingly (and they would both be in sync). Again, the Model is shared (only that, this time, sharing is somehow limited to a specific context, in this case, to that window).

I think that what I'm trying to say is that, from my POV and based in my experience, the "new instance every time" approach isn't the natural default in practice. And specifically in PHP, the "shared instance" approach is more natural as a default for me.

from dice.

TRPB avatar TRPB commented on July 17, 2024

As for Controllers and Views themselves, I would say that it doesn't matter for them, because only the "front-controller" would have reference to them, and it would be exactly 1 reference. Let's imagine that this function represents the front-controller for a specific endpoint:

But from a purity point of view, sticking with the online shop example if we had a HMVC architecture and we wanted to display two products side by side on a page, we could use the same MVC triad but we'd need two instances of each model, view and controller.

Generally there are better ways to achieve that on the web, but technically you could and having a shared model would mean you could only display the same product next to itself.

Again, the Model is shared (only that, this time, sharing is somehow limited to a specific context, in this case, to that window).

Indeed but that's exactly what Dice's shareInstances configuration option is for, to share an instance (or multiple instances) throughout an object tree from a given starting point, but have an instance per unique tree.

One of the other reasons shared by default is a bad idea is that by design it will prevent the garbage collector from freeing instances from memory. If an object isn't marked as shared, it can be cleaned up during GC. If you mark it as shared, Dice has to keep a reference to it in case it's needed again. By marking everything as shared, any instance created by Dice will remain in memory until the script exits. While it's probably fine for very simplistic applications, long running commands and scripts that iterate over a lot of data could cause problems.

from dice.

Racso avatar Racso commented on July 17, 2024

Just to clarify: my comment about Controllers and Views being exactly 1 and only being referenced by a "front-controller" was strictly speaking about standard PHP web applications, where you [usually?] want one controller and one view per request.

In the HMVC example, you're right in that you would not want a single shared model for everything, but in that scenario, you would be able to configure it to not be shared ("shared by default" just means that you need to explicitly set stuff as not-shared).

But all in all, I get your points. The GC argument is a very strong one in favor of "not-shared by default", not only because of the consequences on garbage collection itself, but also because it clearly shows that the simplest, purest behavior of the tool is to "instantiate and return" (not shared), rather than "instantiate, cache and return" (shared).

shareInstances is a great feature, btw.

from dice.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.