Jump to content

Recommended Posts

Hello, I just finished reading the post about 10 Signs of Crappy PHP Software by John Kleijn

 

This is an overview!

 

I'm on my way to create a message board, because I'm tired of phpBB, smf, vanilla. in coding terms they don't offer much flexibility, except Vanilla, I only opened the code once, after that I dared not to.

 

So I set the main priority of my forum is to be mostly flexible and be able to create extensions painlessly, not to mention the template system which is most painful. I'm half way implementing the MVC design with URL "rails-style" routing.

 

Now, some of you might say, why not use an existing framework? pretty simple, it's not because "i don't trust their code" it's because I want to learn and to feel more accomplished that I understood and implemented it.

 

Anyway! To my true post:

 

I just wrote a Registry singleton, one of the issues that the post mentions is that the data is still available to everyone and one can change variable to anything. I did keep that in thought so my registry is a bit more strict with the aim of stability.

 

Here is the code

 

In simple terms:

If the key is explicit, it cannot be removed to modify again, most of what the registry currently carries is, systempath, templatepath, extensionpath, BaseURL, Database.

 

What should I keep in mind to avoid the overuse of singleton patterns when I need an object?

 

 

 

Link to comment
https://forums.phpfreaks.com/topic/164981-singleton-pattern-question/
Share on other sites

Couple of things  ;D  instead of allowing someone to set a registry entry to explicit simply create a list of internal keys that can never be overwritten, deleted or changed only viewed, and let the rest do as they please.

 

Allowing someone to set a key as explicit could set keys that are needed for other modules/sections/apps and now cannot be overwritten because of this, also you would want a core registry class set to a final class so i cannot be implemented inherited or modified in any way.

 

What do you mean by "avoid the overuse of singleton patterns when I need an object" if you are creating a registry to store objects only use it for the application critical objects that are used everywhere and need that kind of accessibility otherwise autoloading...

 

Here is an example of a framework registry that stores all information the framework process has and uses the example i mentioned above

 

See Here

 

Couple of things  ;D  instead of allowing someone to set a registry entry to explicit simply create a list of internal keys that can never be overwritten, deleted or changed only viewed, and let the rest do as they please.

 

Allowing someone to set a key as explicit could set keys that are needed for other modules/sections/apps and now cannot be overwritten because of this, also you would want a core registry class set to a final class so i cannot be implemented inherited or modified in any way.

 

What do you mean by "avoid the overuse of singleton patterns when I need an object" if you are creating a registry to store objects only use it for the application critical objects that are used everywhere and need that kind of accessibility otherwise autoloading...

 

Here is an example of a framework registry that stores all information the framework process has and uses the example i mentioned above

 

See Here

 

autoloading... do'h! (and type hinting)

 

Thanks for the solution on the registry keys, that was also on my mind, couldn't help to think that if users started writing extensions they would use the explicit option which would be annoying.

 

 

one of the issues that the post mentions is that the data is still available to everyone and one can change variable to anything.

 

The latter is only true for a Singleton Registry, where it is easy to override a key with an object of a different type. The alternative to the former is using Dependency Injection, either manual (passing dependencies through the constructor and setters), or if you want to get fancy using a DI framework. I'd stick with manual for now.

 

One thing I can recommend is using a Service Layer (an interface to the Model Layer), which comes in the variant thin (which is basically just a Facade) and thick (which includes more logic). Both variants have the property of defining a simplified interface to the Model, reducing coupling. It may be possible (depending on the application) to find places to define an interface to a subsystem or layer. You can use the Facade pattern to provide a single interface to the layer. This has the effect of better defined access to the layer, possibly resulting in less coupling. This may sound daunting, but it isn't half as complicated as you may think. For a Service Layer, instead of letting the controller operate directly on the Model classes, send your request to the Service Layer and let it figure it out. That's basically what it comes down to: letting the layer figure it out internally.

 

As for getting rid of Singletons, in an MVC application the Controller layer is the obvious choice for providing the other layers with the necessary initialization parameters. During startup it gathers configuration, and can pass it to the Model and View when dispatching. No global data needed.

 

Hope this is making sense to you.

Hello

 

Thanks answering :) I'm still submerging myself into design patterns and application design so yea I'm a bit new. I'll be looking up those patterns, the PHP world seems to be evolving more oriented than ever so I don't want to be left behind

 

It does make sense, a little, but I'm getting there. I'll try it today and come back if I don't understand a pattern

one of the issues that the post mentions is that the data is still available to everyone and one can change variable to anything.

 

As for getting rid of Singletons, in an MVC application the Controller layer is the obvious choice for providing the other layers with the necessary initialization parameters. During startup it gathers configuration, and can pass it to the Model and View when dispatching. No global data needed.

 

Using a facade pattern would provide an alternate means to communicate between the layers of the application presented from the Controller in an MVC application, but you will need to reference that object to anything that is used outside of the scope of the Controller that modifies run-time for any layer within the application whether it is the Model, View or Controller which would make things much more complicated than necessary and why not follow KISS.

 

For example object D (event plugin) needs to use data present in object A (controller) which would mean that either we need to statically access the information or reference it through A -> B -> C -> D, but what happens when object B is modified .. since object C is coupled down to B it now needs modification to continue to pass the needed reference to object D. This is only a small example but you an see the problem that would exist.

 

I personally don't see a valid reason to remove a Registry Singleton from an application, there are many arguments discussing against this but that is a different discussion, if properly used using a singleton registry for access to common data used in various layers of the application such as the controller accessing the model, the controller will be coupled only to the registry and object D would not need the extra coupling to access data.

one of the issues that the post mentions is that the data is still available to everyone and one can change variable to anything.

 

As for getting rid of Singletons, in an MVC application the Controller layer is the obvious choice for providing the other layers with the necessary initialization parameters. During startup it gathers configuration, and can pass it to the Model and View when dispatching. No global data needed.

 

Using a facade pattern would provide an alternate means to communicate between the layers of the application presented from the Controller in an MVC application, but you will need to reference that object to anything that is used outside of the scope of the Controller that modifies run-time for any layer within the application whether it is the Model, View or Controller which would make things much more complicated than necessary and why not follow KISS.

 

You should try breaking up your sentences. This is hardly readable. What I can gather is that you are saying passing references is complicated. It's not. Having an application littered with static calls can easily become much more complicated.

 

For example object D (event plugin) needs to use data present in object A (controller) which would mean that either we need to statically access the information or reference it through A -> B -> C -> D, but what happens when object B is modified .. since object C is coupled down to B it now needs modification to continue to pass the needed reference to object D. This is only a small example but you an see the problem that would exist.

 

I have used this argument in the past (I shared this view at one time), but unfortunately it's invalid. If B and C are in between A and D which share a dependency, A and D should have a reference to each other, or at least A should have a reference to D. If this is not the case, your design is at fault.

 

I personally don't see a valid reason to remove a Registry Singleton from an application, there are many arguments discussing against this but that is a different discussion, if properly used using a singleton registry for access to common data used in various layers of the application such as the controller accessing the model, the controller will be coupled only to the registry and object D would not need the extra coupling to access data.

 

Using a Singleton Registry *everything* is coupled to everything in it. Maybe not right away, but over time it will. You didn't put it in the global space because it looks so pretty, you put it there so *everything* can use it, potentially causing coupling to everything. It really isn't that difficult to understand if you let your guard down for a sec.

 

I have used this argument in the past (I shared this view at one time), but unfortunately it's invalid. If B and C are in between A and D which share a dependency, A and D should have a reference to each other, or at least A should have a reference to D. If this is not the case, your design is at fault.

 

This is true, but in the example I had given object D will never know object A exists nor will A know D. As with a triggered event (plugin) using the Observer Pattern D will execute from C , C -> B etc etc...

 

A having no idea that the D object exists it cannot reference it and the same goes for D -> A.

 

Using a Singleton Registry *everything* is coupled to everything in it. Maybe not right away, but over time it will. You didn't put it in the global space because it looks so pretty, you put it there so *everything* can use it, potentially causing coupling to everything. It really isn't that difficult to understand if you let your guard down for a sec.

 

And I still do not see how if a "properly designed" Singleton Registry meaning the coupling done within the Singleton Registry is loose coupling, all libraries stored within the Registry are cohesive, using the registry only for abstraction, would cause issues. 

Using a Singleton Registry *everything* is coupled to everything in it. Maybe not right away, but over time it will. You didn't put it in the global space because it looks so pretty, you put it there so *everything* can use it, potentially causing coupling to everything. It really isn't that difficult to understand if you let your guard down for a sec.

 

And I still do not see how if a "properly designed" Singleton Registry meaning the coupling done within the Singleton Registry is loose coupling, all libraries stored within the Registry are cohesive, using the registry only for abstraction, would cause issues. 

 

When you put something in a registry, it's free for all to use and you cannot know which objects are going to use it, hence the inter-dependencies and coupling.

 

I have used this argument in the past (I shared this view at one time), but unfortunately it's invalid. If B and C are in between A and D which share a dependency, A and D should have a reference to each other, or at least A should have a reference to D. If this is not the case, your design is at fault.

 

This is true, but in the example I had given object D will never know object A exists nor will A know D. As with a triggered event (plugin) using the Observer Pattern D will execute from C , C -> B etc etc...

 

The Observer pattern does not work like that, it does not have the effect of a chain. Perhaps you are confused with Chain of Responsibility? As far as DI for an observer implementation goes, I don't see why that would be problematic. The Subject can just inject the dependency. Regardless, even in a Chain of Responsibility this is a moot point. Yes you have to pass the dependency down the chain, but that is the essence of the pattern and it is no different from the rest of the message that you send down the chain (unless of course you're creative enough to pass it through the chain to somewhere else  ::)).

 

Using a Singleton Registry *everything* is coupled to everything in it. Maybe not right away, but over time it will. You didn't put it in the global space because it looks so pretty, you put it there so *everything* can use it, potentially causing coupling to everything. It really isn't that difficult to understand if you let your guard down for a sec.

 

And I still do not see how if a "properly designed" Singleton Registry meaning the coupling done within the Singleton Registry is loose coupling, all libraries stored within the Registry are cohesive, using the registry only for abstraction, would cause issues. 

 

Man. Your sentences are garbled, that's just not funny any more. Are you seeing anyone for this condition? No offence, I'm dead serious. I'll see what I can extract.

 

"properly designed" Singleton Registry

 

There is very little you can design about a Singleton Registry. It is what it is. And that's global. You can improve internal cohesion and decoupling, but that's about it.

 

meaning the coupling done within the Singleton Registry is loose coupling

 

Coupling with (or did you really mean within, as in between methods, or between the objects in the map?) the Singleton Registry is always static, thus always coupled with the global space. One can hardly call that loose coupling.

 

all libraries stored within the Registry are cohesive

 

Eh? How so? Aside from the fact that storing "libraries" in a map rather than objects is quite an accomplishment (I imagine you would have to concatenate many source files together to accomplish it), I'd say you'd have all sorts of objects in a Singleton Registry, responsible for all sorts of stuff. How is that cohesive?

 

using the registry only for abstraction, would cause issues

 

Using a Registry for abstraction? Not making any sense.

Been reading articles and so on about patterns, visiting wikipedia, checking on solutions to apply on my first application (I'm still vigilant on not overkilling the application with the overuse of patterns)

 

Now, I don't really plan to remove the Registry Singleton, it's still good to carry common application data but what I want to avoid the most is making the application to rely heavily on the Registry. I don't want users to see available objects they are never going to use in the registry. In fact if I can help it I don't want objects at all to be loaded onto the registry at first instance.

 

So far, the base controller (abstract) gathers the database layer, session layer, views layer which should suffice for now for simple extensions(applications)(methinks) What I want to avoid is people loading lets say, the Router class into the registry because it wouldn't make sense. (at least to me). (which is also somewhat 448191 mentioned but I'm making a few exceptions because not everything needs to be loaded onto the controller)

 

About the models, that's actually a great idea, models were actually out of my thoughts process because I was absorbed reading some patterns stuff, etc etc.

 

I've been refactoring some code and folder structures which so far I don't see any problems. Time for some whining :P, man it's a bit tough to grasp, but better do it now than never... if the design I create is correct then I don't have to worry about future upgrades. </whine>

 

Another reason I want to avoid the use of registry singleton is because I plan to use PHPUnit. It's also something new I have never used so I drive some tests to ensure my work is behaving like it should. So far I've read registry singleton makes unit testing a bit harder. Is this correct?

It's also something new I have never used so I drive some tests to ensure my work is behaving like it should. So far I've read registry singleton makes unit testing a bit harder. Is this correct?

 

I'd say so. It's not impossible, but the issue with anything static or global is that it takes extra effort to isolate the tests. The idea is that every test is isolated from the next, that becomes an issue when the first test modifies the global space the next has to execute in.

http://en.wikipedia.org/wiki/Library_(computing)

 

I must be wrong that a set a classes designed for a specific task would not be considered a library.

 

I think you are taking things a lot farther out of the scope of what I am discussing or possibility misunderstanding a few things.

Observer Pattern

An object that makes itself observable to other objects and sends messages to observing objects when it state changes ... I believe this is the correct definition so I do believe I am not confusing myself with the Chain of Command.

 

So,

 

Therefore what I said was in-fact correct. A will send a state change (triggered event) to B (the observable object) -> C (Collection Of objects listening to B) -> D (Object stored in C waiting for state change in B)

 

Where do u get these assumptions that the Registry will store "all sorts of stuff" I don't see it very wise to make arrogant assumptions based on your own coding standards, knowledge or lack thereof

 

Take a peak at Magento a highly powerful and flexible e-commerce application, it uses the same registry example I am discussing. I'm sure they know thats its wrong though correct?

 

Also about testing, if you properly design your libraries (or classes if you like) there would be no issue regarding the registry. The libraries would be exactly what they are called a collection of classes used to perform certain tasks, which would allow you to single them out on their own and test to your hearts desire. Example would be an ACL library in a Framework this collection of classes should be able to be taken directly from the Framework and run completely independent of any other part of the framework.

I must be wrong that a set a classes designed for a specific task would not be considered a library.

 

No, you aren't (edit: I didn't see there is a double negative in there, so my response should actually be "yes, you are". sorry about that). But you can't put classes in an array, nor libraries. Objects, yes, even instances of other data types, could you believe it.

 

I think you are taking things a lot farther out of the scope of what I am discussing or possibility misunderstanding a few things.

 

If there's anything I am misunderstanding it is most likely what you were trying to say, because in one thread you've managed to produce two sentences that are practically incomprehensible. Could be that our views are not as much apart as I think, just because I can't understand your sentences.

 

An object that makes itself observable to other objects and sends messages to observing objects when it state changes ... I believe this is the correct definition so I do believe I am not confusing myself with the Chain of Command.

 

That's an approximation of the definition, close enough.

 

Therefore what I said was in-fact correct. A will send a state change (triggered event) to B (the observable object) -> C (Collection Of objects listening to B) -> D (Object stored in C waiting for state change in B)

 

Euh... I think objects B and C are a little superfluous here, wouldn't you agree? Maybe C could be an actual object (implementing Traversable), but I would hardly say it's coupled to the objects it holds, and especially not to any dependencies that need to be passed to any Observers.

 

Where do u get these assumptions that the Registry will store "all sorts of stuff" I don't see it very wise to make arrogant assumptions based on your own coding standards, knowledge or lack thereof

 

Well, that's generally why people want a globally available Registry, right? To store all their "stuff" (read "objects of varying types"). If they're all the same type, or closely related, why would you need it to be global?

 

Take a peak at Magento a highly powerful and flexible e-commerce application, it uses the same registry example I am discussing. I'm sure they know thats its wrong though correct?

 

For all I care the pope, Jesus, Mohammed, president Obama, the Queen of England, or the whole freaking world would be using Singletons. That doesn't make it a good idea.

 

Also about testing, if you properly design your libraries (or classes if you like) there would be no issue regarding the registry. The libraries would be exactly what they are called a collection of classes used to perform certain tasks, which would allow you to single them out on their own and test to your hearts desire. Example would be an ACL library in a Framework this collection of classes should be able to be taken directly from the Framework and run completely independent of any other part of the framework.

 

Euh.. Yes?... No?... Can you repeat the question? (If am making any sense of this I think you thinking too statically).

Where do u get these assumptions that the Registry will store "all sorts of stuff" I don't see it very wise to make arrogant assumptions based on your own coding standards, knowledge or lack thereof

 

I don't know if this was either directed to 448191 or me. If it was to me then let me tell you that having that thought makes you pretty arrogant instead of being more open.

 

Sure, I'm not a genious, and I don't believe there is a programming genius anywhere. It takes a great amount of practice and comprehension to reach a decent skill. If I'm lacking, then why do you see me here? I won't pretend I know everything and well I'm here to learn what the community members offer.

 

As for my assumption, it just that.. even if I protect the keys, it will inevitable be global.

 

I'm starting to believe there is a secret fanbase for registry singletons..

 

lol no allen I was not refering to you.

 

Sorry, Slight mistype on the first sentence....448191

 

In regards to the Observer issue,

Yes you would need each the B and C objects,reason is B is the observable object its only purpose is to send state changes to C. C is the registry of Observers that are awaiting to be triggered based on state changes, if you have not guessed D would be the object that is called once C notifies its registry of Observing objects.

 

You could do it your way and have D perform all aspects ... but this provides 0 support for scalability ...

 

In the Registry Singleton I am speaking of there will be only minimal "objects" stored on run-time, likely the exact same ones that the Controller will retrieve. I believe you think that the most simple things such as Framework Helpers for example would be loaded from the registry if you do, you are sadly mistaken. Like I said before If the Registry is properly designed it is a very useful Design Pattern.

 

I will repeat myself for you (since you seem to have a hard time understanding)...

When it comes to testing, the registry singleton will not be of any issue, as with a good design for any library it should run independently of the application or say a "mini-app" in itself. Thus allowing you to test this "mini-app" out of the registries scope, completely on it own.

 

 

It also has come to my attention this debate is getting nowhere with the my-way-or-highway attitude you are expressing

 

lol no allen I was not refering to you.

 

Sorry, Slight mistype on the first sentence....448191

 

In regards to the Observer issue,

Yes you would need each the B and C objects,reason is B is the observable object its only purpose is to send state changes to C. C is the registry of Observers that are awaiting to be triggered based on state changes, if you have not guessed D would be the object that is called once C notifies its registry of Observing objects.

 

Then you don't need A. There need only be two types of objects be involved in the traditional implementation of Observer (GoF:295): an instance of concrete subject (your A and B), and a multitude concrete observers (your D). Your C, while it could exist (it could just as well be a basic array), has no coupling of mention with the objects it holds, and certainly not with any dependencies in D (am I repeating myself?).

 

But lets forget about Observer for now, I do know what you are trying to say. You think that the alternative to using a Singleton Registry is having objects which have no business with the object, pass it along because somewhere in the underlying object structure, another object needs it. Like I said before, I used to share this view. I drew up this pretty funny cartoon about it, I remember it being pretty well received. It's a shame the image is gone though. I'm not the funniest guy in the world, so when I am I cherish the moment. I'm sorry, what were we talking about?

 

Oh right, you think that it is unavoidable to pass dependencies deep into objects structures. You've probably gathered that I am going to tell you it is not. The solution is simple enough (in concept at least): don't make objects deep within an object structure dependent on something that's not deep within the object structure. It's quite possible that something deep into the object structure needs something that is not created at that level of composition.

 

But instead of blindly passing the whole object, only delegate the part of the message that is relevant to the object, but make it a new message. In simple code: $messageB = new MessageB($messageA->getSomethingThatIsRelevantToTheReceiverOfMessageAAsWellAsTheReceiverOfMessageB());. Hardly rocket science. That object may then do the same for the objects it holds a reference to. Only talk to your neighbours, the rest of the block can tend to themselves. To be honest, I don't give a shit if the dalmatian of the guy at no 10 does his thing on the lawn at no 12. Sorry, getting a bit too much into character here. The point is if you want to make objects oblivious to objects not directly related, all you have to do is "tell them what they need to know". Nothing more, nothing less.

 

Of course this only works if your system is pretty cohesive. When it turns out that you've made a design decision that makes this difficult, it's certainly easy to take the "bail out card" and make something global. Of course the appropriate course of action would be to refactor the fruits of your bad design choice that got you in this trouble in the first place, but with your manager breathing in your neck and spraying Saliva (yes, with a capital S) all over your face when he yells at you, I can imagine the appeal. Hell, I've been there, and I'll probably visit from time to time.

 

You could do it your way and have D perform all aspects ... but this provides 0 support for scalability ...

 

My way? I don't know what you think "my way" is, but it certainly doesn't entail having "D perform all aspects". Especially since "all aspects" is quite vague.

 

In the Registry Singleton I am speaking of there will be only minimal "objects" stored on run-time,

 

Hmmm.. I wonder why "objects" is in quotes? Dagnabbit, now I did it myself. Hmmm.. Minimal objects stored at run time. At run time. As opposed to...

 

likely the exact same ones that the Controller will retrieve. I believe you think that the most simple things such as Framework Helpers for example would be loaded from the registry if you do, you are sadly mistaken. Like I said before If the Registry is properly designed it is a very useful Design Pattern.

 

Hmoakydoky, I get this. You are saying "it's ok to use my global Registry because I don't put much in there". Well that completely negates that fact you can blindly couple the objects in there, albeit few in numbers but no doubt large in usage count. Who said sarcasm doesn't work on the Internet! Yet another myth defused.

 

I will repeat myself for you (since you seem to have a hard time understanding)...

 

It's not so much repetition I find myself longing for in this thread, but rather rephrasing. You did a little better in this last post though. There may be hope, don't give up.

 

When it comes to testing, the registry singleton will not be of any issue, as with a good design for any library it should run independently of the application or say a "mini-app" in itself. Thus allowing you to test this "mini-app" out of the registries scope, completely on it own.

 

I see. And when it's time to put these "mini-apps" back together?

 

It also has come to my attention this debate is getting nowhere with the my-way-or-highway attitude you are expressing

 

I don't remember expressing that. But if you mean that I am unwilling to adjust my views to condone using global data, you are absolutely right. I keep this alien view, despite your oh-so convincing arguments to just couple everything to the global space whenever it's convenient.

 

Well, that was certainly entertaining. We should do this again some time. What are you doing next week? We could have a discussion about microwaving steak. You can take position going on about how convenient it is and I'll take the culinary purist position and argue that it just doesn't taste the same. Should be interesting.

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.