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

Feature: generated injector delegator #51

Merged
merged 13 commits into from
Dec 31, 2019
Merged

Feature: generated injector delegator #51

merged 13 commits into from
Dec 31, 2019

Conversation

michalbundyra
Copy link
Member

@michalbundyra michalbundyra commented Jan 9, 2019

In documentation we are suggesting to create in manually. I think we can have it in the library as it's generic code.

See: https://docs.zendframework.com/zend-di/cookbook/aot-guide/#5-add-aot-to-the-service-manager

Documentations needs update if it is going to be accepted.

  • Are you creating a new feature?
    • Why is the new feature needed? What purpose does it serve?
    • How will users use the new feature?
    • Base your feature on the develop branch, and submit against that branch.
    • Add only one feature per pull request; split multiple features over multiple pull requests
    • Add tests for the new feature.
    • Add documentation for the new feature.
    • Add a CHANGELOG.md entry for the new feature.

As it could be used comonnly would be nice to have it out of the box.
@tux-rampage tux-rampage self-assigned this Jan 9, 2019
@tux-rampage tux-rampage added this to the 3.2.0 milestone Jan 9, 2019
Copy link
Contributor

@tux-rampage tux-rampage left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes sense. Thanks a lot for your effort. Just a view nitpicks that needs to be fixed before a merge.

I also think it makes sense to add it to the ConfigProvider

src/GeneratedInjectorDelegator.php Outdated Show resolved Hide resolved
src/GeneratedInjectorDelegator.php Outdated Show resolved Hide resolved
@michalbundyra
Copy link
Member Author

@tux-rampage

I also think it makes sense to add it to the ConfigProvider

I am not sure about it, what if someone already has it added there (the custom one) or if someone what to use another?

@tux-rampage
Copy link
Contributor

@tux-rampage

I also think it makes sense to add it to the ConfigProvider

I am not sure about it, what if someone already has it added there (the custom one) or if someone what to use another?

Good point. Could you update the AoT guide?

@michalbundyra
Copy link
Member Author

@tux-rampage

Could you update the AoT guide?

Docs is updated now.

Copy link
Contributor

@tux-rampage tux-rampage left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found some additional minor things that we may need to address.

Thanks for your effort to improve this component 👍

src/GeneratedInjectorDelegator.php Show resolved Hide resolved
src/GeneratedInjectorDelegator.php Outdated Show resolved Hide resolved
Copy link
Contributor

@tux-rampage tux-rampage left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @webimpress

sorry for the delay on this. Just one thing with the exception you throw. After that I think we're good to go.

src/GeneratedInjectorDelegator.php Outdated Show resolved Hide resolved
test/GeneratedInjectorDelegatorTest.php Outdated Show resolved Hide resolved
This will improve readability and makes the unit easier to test.
It will also offer a typed information to consumers to get rid
it.
@tux-rampage
Copy link
Contributor

@michalbundyra As discussed in slack, I've addressed this one. Can you pleas re-check?

{
$config = $container->has('config') ? $container->get('config') : [];
$aotConfig = $config['dependencies']['auto']['aot'] ?? [];
$namespace = empty($aotConfig['namespace']) ? 'Zend\Di\Generated' : $aotConfig['namespace'];
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe better "empty or non-string" here?

Copy link
Contributor

@tux-rampage tux-rampage Dec 16, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
$namespace = empty($aotConfig['namespace']) ? 'Zend\Di\Generated' : $aotConfig['namespace'];
$namespace = empty($aotConfig['namespace']) || ! is_string($aotConfig['namespace'])
? 'Zend\Di\Generated'
: $aotConfig['namespace'];

Like this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, please

test would be with an array, for example, as it can't be casted to string

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was just going to make this change and saw it would render the next 3 lines useless:

        $config = $container->has('config') ? $container->get('config') : [];
        $aotConfig = $config['dependencies']['auto']['aot'] ?? [];
        $namespace = empty($aotConfig['namespace']) ? 'Zend\Di\Generated' : $aotConfig['namespace'];

        if (! is_string($namespace)) {
            throw new InvalidServiceConfigException('Provided namespace is not a string.');
        }

I'd argue to leave it as is. This will be explicit to the user that there is an unusable misconfiguration instead of hiding it behind a default value that may cause failures which may become hard to debug. At least it's not obvious what's the issue that cause incorrect behavior.

I'll change the test from an int fixture to an array though.


use Psr\Container\ContainerExceptionInterface;

class InvalidServiceConfigException extends LogicException implements ContainerExceptionInterface
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure if LogicException as a parent is the correct one

Maybe better InvalidArgumentException?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

InvalidArgumentException actually is a LogicException.
But in this case I'd argue that this is not cased by a function argument but a (service)configuration value. This could also be seen a RuntimeException.

I chose LogicException since it's the developer's job to configure the services correctly, and if they don't provide a namespace-string, they made a logical mistake.

https://www.php.net/manual/en/class.logicexception.php
Exception that represents error in the program logic. This kind of exception should lead directly to a fix in your code.

But I'm happy if you provide a better fit.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, sounds good to me.

I just wonder if we should have then another exception before if the namespace is provided but is not null and not a string? Maybe we shouldn't ignore invalid value. What do you think?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this already the case or am I missing something? 🤔

@@ -27,7 +28,7 @@ public function testProvidedNamespaceIsNotAString()

$delegator = new GeneratedInjectorDelegator();

$this->expectException(ContainerExceptionInterface::class);
$this->expectException(InvalidServiceConfigException::class);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it was quite important check, as container (per specification) can throw only ContainerExceptionInterface instances.

would be nice to have it somewhere

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is a unit test really the correct scope? We could assert that InvalidServiceConfigException implements ContainerExceptionInterface. So that whenever this changes this test fails:

Suggested change
$this->expectException(InvalidServiceConfigException::class);
self::assertInstanceOf(ContainerInterface::class, new InvalidServiceConfigException());
$this->expectException(InvalidServiceConfigException::class);

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, probably it should be separate test case, but I am happy to have it here for time being.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess a separate test would be out of scope for now. I'm not entirely sure if this is the correct place or way to cover this. Maybe we find something more appropriate in the future. 😉

Until then I added the assert as suggested.

```

After this we need to add configuration to the `ConfigProvider` class we created
First, we'll use a delegator `Zend\Di\GeneratedInjectorDelegator` to decorate
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to note that GeneratedInjectorDelegator is available since version X.Y.Z.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Absolutely

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Docs are updated. If somebody has a more elegant phrasing or suggesstion, I'd appreciate to hear it.

@tux-rampage
Copy link
Contributor

Static analysis is failing: https://travis-ci.org/zendframework/zend-di/jobs/625613032#L425
This was introduced in #56

@michalbundyra michalbundyra merged commit a7092d6 into zendframework:develop Dec 31, 2019
@michalbundyra michalbundyra deleted the feature/generated-injector-delegator branch December 31, 2019 05:22
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.

None yet

2 participants