I am looking at this example
Relevant excerpt from above:
class AlbumController
{
public function getAlbumTable()
{
if (!$this->albumTable) {
$sm = $this->getServiceLocator();
//* My Question Lies Here:
$this->albumTable = $sm->get('Album\Model\AlbumTable');
}
return $this->albumTable;
}
}
What is $this->albumTable
? Its type is AlbumTable
. What is AlbumTable
? It's a class that manages a an instance of class TableGateway
of ZendDb module of ZF2.
The problem
In a way, AlbumController
depends on TableGateway
. ServiceLocator just makes this chain of dependencies slightly more hidden away.
It actually makes $this->albumTable
seem like a "variable that contains data" and adds ability to "call that variable from anywhere inside the code on a whim" -- kind of like declaring an int
data type, you declare TableGateway
that is tied to your own entity, along with ability to add your own custom business data access and retrieval functions. I concede that it is pretty cool ...
So? What's my problem with it?
Problem: class AlbumController
contains dependency on TableGateway
.
I wanted to seek out more clarification on why this is acceptable in terms of Single Responsibility Principle and other similar OO separation concerns. Perhaps I am taking it a bit far, but all AlbumController needs is the data that TableGateway can provide -- namely things like data of Album()
type. Why not implement a mechanism that can get AlbumController
its data but without the indirect dependency on TableGateway? There are design patterns that exist that can make that happen.
To Summarize
- Why tolerate dependency on TableGateway inside your Controller class?
- How did ServiceLocator come about -- it is seemingly used to "put that dependency as far away as possible while still keeping it there". Is that the purpose of
SeviceLocator
? - Why not use some other OO facilities (Factories, Builders, etc) to provide/populate Controller directly with data it needs (i.e.
Album
), instead of weighing it down withTableGateway
?
Spirit of the Question
What is the purpose of ServiceLocator Pattern? Why is it there why is it needed what problem does it really solve, when it seems to just push things off dependency-wise
Also, ServiceLocator is a dependency in every ZF2 Controller that extends AbstractController... Thus making our custom AlbumController depend on both ServiceLocator and anything that ServiceLocator decides to call (i.e a thing like TableGateway). You can thus call any Service that you care to out of any Controller place you wish. What happened to dependency injection and inversion of control concepts?
UPDATE:
It seems like Zend has deprecated ServiceManager::getServiceLocator()
as of v3.0.0. Recommends to "use the container passed to the factory instead".
See also this blog post on deprecating ServiceLocatorAware