Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Priority tag #628

Closed
theofidry opened this issue Nov 17, 2016 · 6 comments
Closed

Priority tag #628

theofidry opened this issue Nov 17, 2016 · 6 comments
Milestone

Comments

@theofidry
Copy link
Member

As described in #388, the fixtures are generated in the following order:

  • instantiate all fixtures — if a fixture needs to be injected during instantiation, alice will generate that fixture completely first before injecting it
  • hydrator all the fixtures
  • do the method calls on the fixture
  • allow a configuration step

However maybe an object expects a complete object to be given during the hydration step or the method calls step. If that object is not immutable, there is no guarantee that will be the case. I think it would be nice to have a priority flag to allow that behaviour:

@theofidry theofidry added this to the 3.0.0 milestone Nov 17, 2016
@theofidry
Copy link
Member Author

Although interesting, this shouldn't be needed. For example if you consider the following scenario:

[
    Dummy::class => [
        'dummy' => [
            'title' => '@another_dummy->title'
        ],
        'another_dummy (priority)' => [
            '__construct' => [
                'create' => [
                    'Alice',
                    0,
                ],
            ],
            '__calls' => [
                [
                    'setTitle' => [
                        'Bob'
                    ],
                ],
            ],
        ],
    ],
],

you can see here that dummy will need the title property of another_dummy. If another_dummy is not complete yet when dummy requires its title, the it will get the value Alice, and if another_dummy was complete Bob.

With the current implementation, when @dummy->title is being resolved, the resolver tries to get the complete another_dummy, so no need for the priority flag.

@julienfalque
Copy link
Contributor

julienfalque commented Jul 7, 2020

Actually this might be useful for cases where dependencies are hidden from the resolver, e.g.:

A:
    a1:
        __construct: []
        __calls:
            - doStuffThatHasSideEffectsOn: ['@b1']
B:
    b1:
        __construct: []
C:
    c1:
        __construct: ['@b1']

In this example, if the constructor of C has a rule that requires $a1->doStuffThatHasSideEffectsOn($b1) to have been called, this is a dependency the resolver cannot see. This will work if a1 is instanciated and method calls are done before passing b1 to the constructor of c1, but it's not guaranteed.

I faced a scenario like that and was able to make it work by:

  • decorating FixtureSetResolverInterface services to force a specific fixtures generation order
  • hacking some changes into SimpleObjectGenerator to force completion of a specific fixture (didn't try decorating it properly yet, but should be feasible)

Having flags would be a convenient way to solve this issue natively:

  • (priority:<int>) (if such syntax is possible): allows to change the priority of fixtures generation (the higher the priority, the sooner the fixture is generated)
  • (always-needs-completion): forces a fixture to always be complete, even if it is not explicitly required by another fixture

Also it might be useful to have a way to hydrate objets after performing method calls (e.g. when you use a constructor and method calls to create an object and need to override some property through reflection). This is not related to the issue exposed above though.

What do you think?

@theofidry
Copy link
Member Author

Would a complex way of trying to prioritize be really worth it? I'm wondering if a "simple" (complete) tag would not solve the issue.

Also it might be useful to have a way to hydrate objets after performing method calls

I'm much less sure on how that should be approached tbh, much less how to enable it on a fixture basis. Wouldn't it be easier and more robust to create a custom factory there?

@julienfalque
Copy link
Contributor

Do you mean you would use the (complete) tag to prioritize fixtures (instantiating those with the tag first)? This would solve the issue in my simple example but if a1, b1 and c1 all have the (complete) tag because another entity d1 requires all of them to be complete, the order of generation of a1, b1 and c1 would be unguaranteed again.

@julienfalque
Copy link
Contributor

Small update: I tried to decorate SimpleObjectGenerator properly and it solved my issue.

Implementing (priority:<int>) and (always-requires-completion) flags seems quite simple and doesn't seem to have unexpected consequences. I'm willing to give it a try if you agree.

@theofidry
Copy link
Member Author

If you have a PoC would love to have a look 👌

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

No branches or pull requests

2 participants