Skip to content
This repository has been archived by the owner on Feb 6, 2020. It is now read-only.

Remove the need for the $checkAbstractFactories flag #48

Closed
wants to merge 132 commits into from

Conversation

weierophinney
Copy link
Member

In updating zend-mvc to v3 of zend-servicemanager, I ran into a subtle issue: has() does not look in abstract factories by default, and requires that you pass an additional flag, $checkAbstractFactories, with a boolean true value, if you want to test if an abstract factory can resolve the given $name.

This breaks the Liskov Substitution Principal, as it means that the behavior of has() depends on how the ServiceManager is configured. Users then must be aware that an abstract factory might supply a dependency, and cannot rely on has() per the container-interop contract to work for the specific use case of zend-servicemanager.

As such, I'd like to remove the flag, and check abstract factories whenever a service or factory matching the provided $name is not found.

weierophinney and others added 30 commits July 23, 2015 16:50
:
: Please enter the commit message for your changes. Lines starting
: with '#' will be ignored, and an empty message aborts the commit.
:
: Date:      Tue Jul 21 14:13:04 2015 +0200
:
: qrebase in progress; onto afcc387
: You are currently editing a commit while rebasing branch 'rebase' on 'afcc387'.
:
: Changes to be committed:
:	deleted:    src/AbstractFactoryInterface.php
:	deleted:    src/Config.php
:	deleted:    src/ConfigInterface.php
:	deleted:    src/DelegatorFactoryInterface.php
:	deleted:    src/Di/DiAbstractServiceFactory.php
:	deleted:    src/Di/DiInstanceManagerProxy.php
:	deleted:    src/Di/DiServiceFactory.php
:	deleted:    src/Di/DiServiceInitializer.php
:	deleted:    src/Exception/CircularDependencyFoundException.php
:	deleted:    src/Exception/CircularReferenceException.php
:	deleted:    src/Exception/InvalidServiceNameException.php
:	deleted:    src/Exception/RuntimeException.php
:	deleted:    src/Exception/ServiceLocatorUsageException.php
:	deleted:    src/FactoryInterface.php
:	deleted:    src/InitializerInterface.php
:	deleted:    src/MutableCreationOptionsInterface.php
:	deleted:    src/MutableCreationOptionsTrait.php
:	deleted:    src/Proxy/LazyServiceFactoryFactory.php
:	deleted:    src/ServiceLocatorAwareInterface.php
:	deleted:    src/ServiceLocatorAwareTrait.php
:	deleted:    src/ServiceManagerAwareInterface.php
:	deleted:    test/Di/DiAbstractServiceFactoryTest.php
:	deleted:    test/Di/DiServiceFactoryTest.php
:	deleted:    test/Di/DiServiceInitializerTest.php
:	deleted:    test/Exception/ServiceLocatorUsageExceptionTest.php
:	deleted:    test/MutableCreationOptionsTraitTest.php
:	deleted:    test/Proxy/LazyServiceFactoryFactoryTest.php
:	deleted:    test/Proxy/LazyServiceFactoryTest.php
:	deleted:    test/ServiceLocatorAwareTraitTest.php
:	deleted:    test/TestAsset/AbstractFactoryWithMutableCreationOptions.php
:	deleted:    test/TestAsset/Bar.php
:	deleted:    test/TestAsset/BarAbstractFactory.php
:	deleted:    test/TestAsset/CallableWithMutableCreationOptions.php
:	deleted:    test/TestAsset/CircularDependencyAbstractFactory.php
:	deleted:    test/TestAsset/ExceptionThrowingFactory.php
:	deleted:    test/TestAsset/Foo.php
:	deleted:    test/TestAsset/FooAbstractFactory.php
:	deleted:    test/TestAsset/FooCounterAbstractFactory.php
:	deleted:    test/TestAsset/FooException.php
:	deleted:    test/TestAsset/FooFactory.php
:	deleted:    test/TestAsset/FooFake.php
:	deleted:    test/TestAsset/FooFakeAbstractFactory.php
:	deleted:    test/TestAsset/FooInitializer.php
:	deleted:    test/TestAsset/FooPluginManager.php
:	deleted:    test/TestAsset/GlobIteratorService.php
:	deleted:    test/TestAsset/MockSelfReturningDelegatorFactory.php
:	deleted:    test/TestAsset/TrollAbstractFactory.php
:	deleted:    test/TestAsset/WaitingAbstractFactory.php
:	deleted:    test/bootstrap.php
:
- Fixes two tests for options usage to use `build()` when providing
  options.
- Switches to phpcs for CS checks.
- Fixes several CS issues, including long lines.
- Provides tests covering remaining uncovered functionality of the
  LazyServiceFactoryFactory.
- FactoryInterface does this already; InvokableFactory should as well.
This commit achieves 100% test coverage, and attempts to test all behaviors of
the refactored ServiceManager.

In particular:

- Re-added 'services' to the configurable options; this was done for feature
  parity with the original, and because some cases, such as configuration, will
  not need factories.
- Ensured that invalid delegator factory types now raise exceptions.
- Tested that lazy-services are created and proxy as expected.
- Proper grammar, plus now matches what bookdown is looking for.
- Updated `configure()` docblock to properly reflect what it accepts; also
  updated `__construct()` and `withConfig()` docblocks to link to `configure()`
  for purposes of documenting the configuration array.
- Changed verbiage of inline comment in `configure()` to refer to service
  construction.
- Ensure that the `$options` argument is nullable. If null, it should *not* be
  passed to constructors!
- Wrote delegators and lazy-services chapters, based on originals from ZF2
  manual and adapted for new usage.
- Edited all other chapters.
Lazy services were added after the ServiceManager had an established API, and
as such had to rely on optional integration. This patch alters that relationship
to make lazy service configuration a first-class citizen of the ServiceManager.

This allows:

- Removing the `LazyServiceFactoryFactory`.
- Passing `lazy_services` configuration to the constructor or `withConfig()`
  method.
- Direct instantiation of the `LazyServiceFactory` when first encountered as a
  delegator factory, using the `lazy_services` configuration composed in the
  ServiceManager itself.

The usage is thus simplified, as all configuration for all service types is now
directly handled by the ServiceManager itself.
- Often necessary for determining if configuration or dependencies
  required for creating instances exist.
weierophinney and others added 22 commits October 1, 2015 13:02
Previous behavior of the service manager allowed specifying aliases when
creating the `shared` configuration. Prior to this patch, that did not
work with the refactored code.

This patch updates the code to check for a cached service under the
_requested_ service name, not the _resolved_ service name, which allows
specifying sharing configuration based on aliases.

Internally, it caches up to twice:

- If the resolved service name is supposed to be shared, it will cache
  under the resolved name.
- If the requested service name is supposed to be shared, it will cache
  under the resolved name.

This allows having separate instances based on service name.
…aliasing

Cache by requested service name
Prior to this patch, calling `withConfig()` on a plugin manager would
reset the `creationContext` to the plugin manager itself — instead of
retaining the original creation context. This patch updates
`ServiceManager::withConfig()` to ensure that if the creation context is
different than the original instance, it gets injected into the clone.
…manager-with-config

Ensure plugin manager creation context travels with clone
With the most recent changes to allow unshared aliases, aliases to
explicitly registered services no longer worked. This patch adds logic
to get() to check if:

- the alias is shared, AND
- the resolved service is present

and, if so, registers the service under the alias, returning it.
…-service

Ensure aliases can reference explicit services
…ers-to-config-test

Feature/add covers to config test
@weierophinney weierophinney added this to the 3.0.0 milestone Nov 4, 2015
@weierophinney
Copy link
Member Author

Ping @bakura10

The flag breaks the LSP, and requires that a user know how a given
service might be configured inside the container. Removing it provides
easier interoperability, and removes unexpected false negative lookups.
@weierophinney
Copy link
Member Author

Closing; I opened against the wrong branch.

@bakura10
Copy link
Contributor

bakura10 commented Nov 4, 2015

I can't fight against a breakage of the Liskov law =).

More seriously, no problem with that. Best practices encourage not to use many abstract factories so the introduced overweight should be negligeable. Go on! ;)

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants