We had a conversation about the difference between registering by name and registering by interface. I passed some motivations, stating that:
- when you place a interface into inject object (ie. use annotation), both your IDE and static code analyzer know what fields & methods it has (great!),
- there are times when you don't have possibility to provide an interface that all implementations inherit from (with factory methods in particular); then you can use registering by name,
And now I have the ultimate reason to differ between interface & name registration. Consider following example (exaggerated a bit, but only a tiny):
class ISession:
@property
def id(self): ...
def save_data(self, key, data): ...
def get_data(self, key): ...
class RedisSession:
... # implementation
class ISessionWithUser(ISession):
user: entities.User
class UserRedisSession(ISessionWithUser):
... # implementation
# registering sub-interface
container.register_by_interface(ISessionWithUser, UserRedisSession)
# ... allows finding them with their parent interface
container.find_by_interface(ISession)
# >>> returns UserRedisSession instance even though its registration
# interface was more specific than the one given at the lookup call
Three notes:
- do you want to implement this use case in this issue or is it enough for you?
- here I see some benefit using a decorator to indicate that something is an interface for something: you do not have to look every time in the runtime iff queried interface has some subclass which provides a constructor
- we already have an util to find all subclasses of a class (
pca.utils.inspect.get_all_subclasses), so it isn't too hard to implement
- if getting all sub-interfaces sounds time-consuming, you could use registration time (ie. application startup time; as then exist all super-interfaces of registered interface).
Eventually, described feature is just an application of Liskov Substitution Principle to our Dependency Injection solution.
Tell me what do you think about this.
Originally posted by @lhaze in #19 (comment)
We had a conversation about the difference between registering by name and registering by interface. I passed some motivations, stating that:
And now I have the ultimate reason to differ between interface & name registration. Consider following example (exaggerated a bit, but only a tiny):
Three notes:
pca.utils.inspect.get_all_subclasses), so it isn't too hard to implementEventually, described feature is just an application of Liskov Substitution Principle to our Dependency Injection solution.
Tell me what do you think about this.
Originally posted by @lhaze in #19 (comment)