Registry design pattern...good or bad?
The article claims it is using the "registry design pattern"; is that the universal name for this design in the industry?
Yes, but the implementation could obviously differ. Basically, a registry is a container for shared objects. In the really basic version, you could use an array. As such, the variable $GLOBALS
could be called a registry.
Is there another similar patter out there that would be a better option?
There are two variations of a registry. There is the global registry (Which is far the most common, and which this is an example of). And there is a local registry. A local registry is passed to objects that need it, rather than obtained through a global symbol (static class, singleton etc.). A local registry has a lower degree of coupling, but is also slightly more abstract, so there is a tradeoff there.
You can also go even further and use full dependency injection, where you explicitly pass all the dependencies to the objects that need them. This can be a bit tedious in larger applications. You can couple this with a dependency injection container, which is a piece of code that "knows" which dependencies which classes have. This is even more complex than a local registry, but has a very low degree of coupling.
Is this pattern considered to be good practice to implement in the context of an MVC framework?
It's common practise. If it's good or bad is a judgement call. Personally I'm willing to accept some complexity in return of decoupling, but ymmv.
I'm of the opinion that generically speaking, there isn't really such a thign as a "bad pattern". That being said, some techniques should be used more sparingly than others, and the notion of a global registry is one which is often less than elegant. The issue with it is that dependencies between given objects are handled through name-based addressing, which is akin to simply using global variables, rather than by the indirection of strategizing by having dependencies be provided — which is what's commonly referred to as dependency injection.
How this can impact the reuse and flexibility of software is actually very clear. Consider a request handler of sorts which integrates with an OAuth2 provider for authentication. If you define an object with a well defined interface for making requests to this OAuth2 provider, you have the ability to change the provider in the future by creating another object which implements the same interface.
Now let's say for discussion sake your first implementation needs to access Facebook. But then next week, you make the decision that you should also support Yahoo, who implements OAuth2 in a way which follows the specification more closely than Facebook does, actually using JSON in the authorization token request rather than name value pairs. And on top of that, there are different pairs of URLs and Keys and whatnot which need to be kept.
Well if you were looking up your authentication provider by name using the registry pattern or service locator patterns, you now have a problem. You need to either copy the code and make the minor changes to it so you can support both at once, or find another solution such as passing keys around and adding hash tables in all locations to find all these elements and detect these variances. Meanwhile if you used dependency injection, you can simply create another implementation of your authentication provider which implements the minor variance of parsing the authentication token, and create a new instance of your request handler which uses that object and has already been tested, and then deploy it to a new location.
The indirection saved you work, reduced the amount of code necessary, and ultimately made your software cheaper, better and faster.
With that said, there are times when the two patterns are not directly interchangeable. Let's say for instance you are building a sort of framework which attaches event handlers to nodes of an XML document. You describe the locations of nodes in an XML document using XPath or JQuery's implementation of CSS selectors. But in order to attach an event handler, you also need to refer to some code. Preferably, you'll refer to some method of some object — well, there's no way to find this "some object" without giving it a name, so now you need a service locator, so you can look things up by name. But do keep in mind that even in this example, there's nothing stipulating that the name must be global.
Creating a local service locator, or local registry as you are calling it here, is a reasonable solution to a problem of this nature. If there can be two instances of the registry in the same application, some of the aforementioned reuse problems can occasionally be mitigated.