zendframework / zend-servicemanager

ServiceManager component from Zend Framework
BSD 3-Clause "New" or "Revised" License
188 stars 89 forks source link

[Docs] Service Naming Convention: class or interface #134

Closed RalfEggert closed 8 years ago

RalfEggert commented 8 years ago

In one of my projects based on ZF3 Service-Manager I noticed that the InvokableFactory does not work properly when I use an interface for the naming of a service. That makes sense but leads to a question:

What is the best practice to name a service? Use the class name or the interface? For example Zend\I18n uses both concepts:

https://github.com/zendframework/zend-i18n/blob/master/src/ConfigProvider.php

Is there a clear definition and should that be documented?

RalfEggert commented 8 years ago

Another example from a tutorial uses an alias:

https://docs.zendframework.com/tutorials/in-depth-guide/models-and-servicemanager/#registering-services

Would that be an alternative?

Ocramius commented 8 years ago

Use the class name or the interface?

I'd say the interface name: keep implementations obscure to consumers as much as possible. You'd simply have to use an actual factory.

RalfEggert commented 8 years ago

Or add an alias like in the second link?

Ocramius commented 8 years ago

Aliases are problematic and will always be problematic. Regardless the situation, I cannot endorse them, ever.

RalfEggert commented 8 years ago

So, if you prefer the interface for service naming and you don't endorse aliases, in consequence you need to create a factory for every classes since you cannot use the InvokableFactory with an interface service name and without setting an alias. Right?

How about controllers? Would you create an interface for every controller to use as a service?

Don't get me wrong. I don't want to be picky here, I just want to identify best practices for service name conventions.

Ocramius commented 8 years ago

How about controllers? Would you create an interface for every controller to use as a service?

Currently writing controllers defining only __invoke, so no need to define interfaces for them.

Also, controllers are kind-of the "end of the line", not abstractions that can be reused, so there's no real need to give them super-meaningful names anyway...

RalfEggert commented 8 years ago

Ok, to summarize the standard is to use an interface for the service name but there are some exceptions for this rule, i.e. controller.

Ocramius commented 8 years ago

Well, the point is: would you interface a controller?

RalfEggert commented 8 years ago

No, not at all. I really support that convention. Just wondering, if there are other exceptions to this rule. What about view helper for example?

weierophinney commented 8 years ago

@RalfEggert I tend to assign the interface to the factory that creates and returns a concrete instance of that interface. As an example, I might write a factory of the name MongoSessionStorageFactory, and assign it to SessionStorageInterface. This accomplishes the goal of using interfaces for service names, and allows me to replace the entry easily later (by assigning a different factory to the service name).

I also concur with @Ocramius - for things like controllers, there's no need to use an interface, and, in fact, it doesn't make sense, because you'll be using many different implementations, and each needs to be named discretely. Unlike service class interfaces, it's not a 1:N relationship (1 service name can be fulfilled by many concrete services), but rather a 1:1 (1 service name refers to exactly 1 concrete implementation).

This is true even for view helpers, because even if you have multiple implementations, you're still in the 1:N relationship: 1 service name, but N potential implementations that are compatible. In these cases, you're replacing the implementation.