Navigation Menu

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

Rework InfectionApplication class and remove 'application' service #146

Merged
merged 4 commits into from Feb 2, 2018
Merged

Rework InfectionApplication class and remove 'application' service #146

merged 4 commits into from Feb 2, 2018

Conversation

sidz
Copy link
Member

@sidz sidz commented Jan 31, 2018

The main my idea of this PR is avoiding of creation application service as it's not needed in the container.
But here is a couple improvements what this PR is bringing as well:

  • Infection Logo is showing only in the InfectionCommand but with this PR Logo will be shown for any command.
  • SelfUpdateCommand is included for phar package only as it doesn't make sense to have it for both cases.
  • pimple container was updated to the 3.2 version as it brings PSR11 ContainerInterface.

Copy link
Member

@maks-rafalko maks-rafalko left a comment

Choose a reason for hiding this comment

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

Thank you @sidz

Seems like there is no line break anymore between some progress reporters. Could you please check?

Besides that, LGTM.

no-break

new Command\InfectionCommand(),
]);

if ('phar:' === substr(__FILE__, 0, 5)) {
Copy link
Member

Choose a reason for hiding this comment

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

noticed report from EA Extended plugin:

0 === strpos(__FILE__, 'phar:')
Use strpos instead of substr to check the start of a string. Substr invokes additional memory allocation, which is not needed in the context. Strpos will do the same job, but without any overhead (it's just searching a string)

@sidz
Copy link
Member Author

sidz commented Jan 31, 2018

Done.

Also I've seen this issue with Creating mutated files and processes line before and right now I'm not sure how to resolve it.

it's not happened each time when you start infection.

p.s. It might be caused by XdebugHandler

Copy link
Member

@theofidry theofidry left a comment

Choose a reason for hiding this comment

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

Did a rough review. Looks much better :)

use Symfony\Component\Console\Output\OutputInterface;

/**
* @method Application getApplication()
Copy link
Member

Choose a reason for hiding this comment

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

why is that necessary?

Copy link
Member Author

@sidz sidz Feb 1, 2018

Choose a reason for hiding this comment

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

phpstorm autocomplete. As getApplication by default will return Symfony's Application class which doesn't have getContainer method

public function getContainer(): Container
{
if ($this->container === null) {
$this->container = new Container($this->getApplication()->getContainer());
Copy link
Member

Choose a reason for hiding this comment

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

$this->getApplication()->getContainer() should be enough here no need to instantiate the container of a container

Copy link
Member Author

Choose a reason for hiding this comment

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

Pimple default container doesn't have get/set methods so this wrapper: https://github.com/silexphp/Pimple/blob/master/src/Pimple/Psr11/Container.php give us these methods.

also this wrapper protects our container and doesn't give ability to modify it. I think this is a big plus.

Copy link
Member Author

Choose a reason for hiding this comment

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

but if we will inject all dependencies through the constructor we don't need to have this wrapper.

@borNfreee thoughts?

Copy link
Member

Choose a reason for hiding this comment

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

as far as I understand, to inject dependency to constructor we still need to do new App($container->get('dependency'), right?

If this is a case, let's have psr11 interface. Who knows, maybe one day we will replace pimple with something else

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 it will look like this

$commands = array_merge(parent::getDefaultCommands(), [
            new Command\ConfigureCommand(),
            new Command\InfectionCommand(
                $this->container['dep1'],
                $this->container['dep1'],
                $this->container['dep1'],
                ......
             ),
        ]);

Copy link
Member

Choose a reason for hiding this comment

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

let's keep psr11 ($this->container->get('dep1'))

Copy link
Member

Choose a reason for hiding this comment

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

meh, indeed not much better, I thought pimple would resolve those deps I see

* @var ConsoleHelper
*/
private $consoleHelper;
protected function configure()
Copy link
Member

Choose a reason for hiding this comment

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

missing the inherit doc bloc and for the others as well; unless you don't ever want to put them?

Copy link
Member Author

@sidz sidz Feb 1, 2018

Choose a reason for hiding this comment

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

haven't ever had a plan to add anything there and not sure what we need to add :)

Copy link
Member

Choose a reason for hiding this comment

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

I mean to add @inherit doc blocks when the method has a parent one; but nvm if you don't like that practice. I kinda like it because you can easily tell if it has a parent one without comparing the parent class but that's it

$this->buildDynamicDependencies($input);
try {
/** @var EventDispatcher $eventDispatcher */
$eventDispatcher = $this->getContainer()->get('dispatcher');
Copy link
Member

Choose a reason for hiding this comment

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

instead of relying on a service locator, couldn't we inject those dependencies through the constructor?

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 we can do it manually from our new Application class

}

return 0;
} catch (InfectionException $e) {
Copy link
Member

Choose a reason for hiding this comment

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

I think you can skip this whole try/catch: the Console command handles very well exceptions:

  • the return value is non 0 when one occurs
  • you get the exception type & message
  • depending of the verbosity you also get the stack trace

return new DotFormatter($this->output);
}

throw new \InvalidArgumentException('Incorrect formatter. Possible values: dot, progress');
Copy link
Member

Choose a reason for hiding this comment

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

  • what about when there is no formatter specified?
  • I would put in quotes dot and progress: 'Incorrect formatter. Possible values: "dot", "progress"'
  • missing use statement

Copy link
Member Author

@sidz sidz Feb 1, 2018

Choose a reason for hiding this comment

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

what about when there is no formatter specified?

dot will be by default. fifth parameter

->addOption(
                'formatter',
                null,
                InputOption::VALUE_REQUIRED,
                'Output formatter. Possible values: dot, progress',
                'dot'
            )

missing use statement

not sure what do you mean. If you suggest to add InvalidArgumentException to the use section I don't really like this.

Copy link
Member

Choose a reason for hiding this comment

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

If you suggest to add InvalidArgumentException to the use section I don't really like this.

Why? It's a dependency like another. The only difference between \InvalidArgumentException and \Acme\InvalidArgumentException would be that the later is namespaced. But for both I think it's more readable to import them with a use statement like everything

Btw if you wanna roll some optim, using fully-qualified calls is always better and the only alternative to it is use statements (func, class & const). I plan to have that with php-scoper in the PHAR but if you want to have it outside of the PHAR send I think waiting/helping for the PHP-CS-Fixer to get that would be good

$eventDispatcher->addSubscriber(new Listener\MutationGeneratingConsoleLoggerSubscriber($this->output, $mutationGeneratingProgressBar));
$eventDispatcher->addSubscriber(new Listener\MutantCreatingConsoleLoggerSubscriber($this->output, $mutantCreatingProgressBar));
$eventDispatcher->addSubscriber(new Listener\MutationTestingConsoleLoggerSubscriber($this->output, $this->getOutputFormatter(), $metricsCalculator, $this->getContainer()->get('diff.colorizer'), $this->input->getOption('show-mutations')));
$eventDispatcher->addSubscriber(new Listener\FileLoggerSubscriber\BaseFileLoggerSubscriber($this->getContainer()->get('infection.config'), $metricsCalculator, $this->getContainer()->get('filesystem'), (int) $this->input->getOption('log-verbosity')));
Copy link
Member

Choose a reason for hiding this comment

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

I must say I'm not a big fan of those super long lines that requires horizontal scrolling, what about:

$subscribers = [
    new Listener\InitialTestsConsoleLoggerSubscriber(
        $this->output, $initialTestsProgressBar,
        $testFrameworkAdapter
    ),
    // ...
];

foreach($subscribers as $subscriber) {
    $eventDispatcher->addSubscriber($subscriber);
}

@@ -162,19 +367,18 @@ private function buildDynamicDependencies(InputInterface $input)
* @param InputInterface $input
* @param OutputInterface $output
*
* @throws \Exception
* @throws \RuntimeException
Copy link
Member

Choose a reason for hiding this comment

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

I wouldn't document this throws, anything in PHP can throw a RuntimeException


class Application extends BaseApplication
{
const NAME = 'Infection - PHP Mutation Testing Framework';
Copy link
Member

Choose a reason for hiding this comment

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

instead of having a constant here what about putting it in the constructor in bin/infection? It allows to pick a different name during the tests for example if you want to

Copy link
Member

Choose a reason for hiding this comment

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

you could also leverage default values in the constructor instead:

function __construct(
    Container $container,
    string $name = 'Infection - PHP Mutation Testing Framework',
    string $version = '@package_version@'
) {
    // ...
}

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 I thought about it but decided to extract this strings into constants. As for me it's static information which won't ever change.

@borNfreee what do you think?

give me a shout if you think that we should put these strings into constructor by default or move them into bin/infection

Copy link
Member

Choose a reason for hiding this comment

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

As for me it's static information which won't ever change.

I have no idea why we need to test/replace this string. It's up to you guys. Current implementation is ok IMO

Copy link
Member

Choose a reason for hiding this comment

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

I like to do it like that because avoids a constant declaration and is aligned with a couple of other projects I check. But I really don't think it matters all to much it's just personal preferences so roll with whatever you prefer :)

{
$this->buildDynamicDependencies($input);

$output->writeln(self::LOGO);
Copy link
Member

Choose a reason for hiding this comment

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

Composer among a few other projects were putting it in getHelp() instead. Maybe it's just personal preferences I didn't really notice any difference in practice. Eventually it may be a better practice in case you leverage parallelism? Well whatev, if you're happy with it we can keep it, otherwise we can align otherselves to the others

Copy link
Member Author

Choose a reason for hiding this comment

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

composer doesn't show logo when you execute composer install for example. I'd say that we can leave it as is right now

@maks-rafalko
Copy link
Member

Could you please rebase @sidz to resolve conflicts?

@sidz
Copy link
Member Author

sidz commented Feb 2, 2018

@borNfreee done

@maks-rafalko
Copy link
Member

Thank you @sidz 👍 🎉

@maks-rafalko maks-rafalko merged commit cd2ce8d into infection:master Feb 2, 2018
@sidz sidz deleted the exclude-application-from-container branch February 10, 2018 18:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants