-
-
Notifications
You must be signed in to change notification settings - Fork 5.2k
[DX] ADR usage #8153
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
[DX] ADR usage #8153
Conversation
With the new approach used by the container, the old controller can be replaced easily by the ADR pattern, as Symfony grow, I think it should be the role of the documentation to show how to use the pattern and how to adapt the framework structure. PS : I'm not pretty sure of the 'note' syntax.
Remove the PHP 7.1 syntax.
Removed the ..note block.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one documents part of symfony/symfony#21723 so we may add a note for this feature @Route("/hello", name="hello")
explaining when this only work? and close #7549 then ;) Thanks!
controller/service.rst
Outdated
*/ | ||
final class HelloAction | ||
{ | ||
/** @var EngineInterface */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
docblock can be removed
controller/service.rst
Outdated
* HelloAction constructor. | ||
* | ||
* @param EngineInterface $renderEngine | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
docblock can be removed
controller/service.rst
Outdated
* @param EngineInterface $renderEngine | ||
*/ | ||
public function __construct( | ||
EngineInterface $renderEngine |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should be one line?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe just engine
? this do a bit more than only render
;)
controller/service.rst
Outdated
* @throws \RuntimeException | ||
* | ||
* @return Response | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
docblock can be removed
controller/service.rst
Outdated
in order to work, you must update the services.yml file :: | ||
|
||
parameters: | ||
#parameter_name: value |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can be removed parameters
section?
controller/service.rst
Outdated
|
||
/** | ||
* Class HelloAction | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can be removed
controller/service.rst
Outdated
methods: ['GET'] | ||
defaults: { _controller: AppBundle\Action\HelloAction } | ||
|
||
.. code-block:: php-annotations |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
php annotations should be the first (as recommended way)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
http://symfony.com/doc/current/contributing/documentation/standards.html#formats:
- Routing: Annotations, YAML, XML, PHP
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few more... ;)
controller/service.rst
Outdated
# app/config/routing.yml | ||
hello: | ||
path: /hello | ||
methods: ['GET'] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This requirement has not been configured in the rest of formats so I guess can be removed?
controller/service.rst
Outdated
{ | ||
return new Response( | ||
$this->renderEngine->render('default/index.html.twig') | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should be in one line
controller/service.rst
Outdated
* @param EngineInterface $renderEngine | ||
*/ | ||
public function __construct( | ||
EngineInterface $renderEngine |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe just engine
? this do a bit more than only render
;)
@yceruto For the docblocks, yes, for sure, I've updated the commits. For the code, I'm not in the same position, if you look at the PSR (especially the 2 http://www.php-fig.org/psr/psr-2/#overview), they say clearly that a line should be under 80:
If you pass the __construct in one line, yes, that works but for the Response return, that's over 85 characters long, way too much in my opinion. For the config files, that's a personal opinion but the requirements key MUST be mandatory and in fact, Insight asks for this key if she's not defined, in my opinion, the documentation should show the right way of using the files and classes. For the parameters key, I think she can stay for simple visibility and easier understanding of the whole file but in the "simplest" way of configuring the service, yes, she can be removed. For the PR, I'm not sure of understanding your vision :/ |
controller/service.rst
Outdated
public function __construct( | ||
EngineInterface $engine | ||
) { | ||
$this->renderEngine = $render; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
$this->engine = $engine
? and fix related use
controller/service.rst
Outdated
|
||
public function __construct( | ||
EngineInterface $engine | ||
) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
public function __construct(EngineInterface $engine)
one line?
@yceruto Should be better. |
Please, I'm only address you to Coding Standards for Symfony project (i.e these aren't my personal preferences).
Following http://symfony.com/doc/current/contributing/code/standards.html#structure:
That's applicable to: |
Should be better, I understand your vision, I continue to use the PSR rules into my projects, that's why I recommend the multi-lines approach :). For the annotations panels order, I've just followed the order used in the first part of the document, no more :) |
Change the order of the routing files and deleted the methods key in yaml routing.
@yceruto Should be better, I've removed the methods key and change the order of the recommended routing configuration. For the parameters key, I think about using '//' in order add a reminder that some keys are missing from the example but that's just for the example, what do you think of this approach? // ...
services:
_defaults:
autowire: true
autoconfigure: true
public: false
# Allow to load every actions
AppBundle\Action\:
resource: '../../src/AppBundle/Action/'
public: true |
@yceruto Services.yml corrected, I've use the # ... syntax, Yaml doesn't support // ..., I've thought about this after my comments :( EDIT : Corrected the indentation bug. |
@yceruto Hi, small question about this PR, should I update the usage after the release of Flex (in Alpha mode, I know but that's a major release) via the blog ? Flex change some configuration added via this PR and it's probably a good idea to show via the doc how to inject the ADR logic using Flex. Probably @javiereguiluz can help us to decide ? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for proposing this! Not sure this is the best place to do it though.
controller/service.rst
Outdated
@@ -80,6 +80,98 @@ If your controller implements the ``__invoke()`` method - popular with the | |||
Action-Domain-Response (ADR) pattern, you can simply refer to the service id | |||
(``AppBundle\Controller\HelloController`` or ``app.hello_controller`` for example). | |||
|
|||
If you want to use the ADR pattern rather than the default controller approach, you can use |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this deserves its own article to be referenced here.
controller/service.rst
Outdated
resource: '../../src/AppBundle/Action/' | ||
public: true | ||
|
||
Once the file is updated, delete your Controller folder and create an Action one then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Once the file is updated, delete your Controller folder and create an Action class using the ADR principles, i.e ::"
controller/service.rst
Outdated
namespace AppBundle\Action; | ||
|
||
use Symfony\Component\HttpFoundation\Response; | ||
use Symfony\Component\Templating\EngineInterface; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This component is to be deprecated, a Twig Environment
should be used instead.
controller/service.rst
Outdated
|
||
final class HelloAction | ||
{ | ||
private $render; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be named $twig
or $renderer
.
controller/service.rst
Outdated
|
||
// app/config/routing.php | ||
$collection->add('hello', new Route('/hello', array( | ||
'_controller' => 'AppBundle\Action\HelloAction', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
HelloAction::class
@HeahDude Hi, thanks for the review, in fact, after reading your messages, I was thinking about a different approach, we all know that the doc should reflect the current usage of the framework, in this approach, I was thinking of proposing a new chapter in the "Guides" part, I don't have a specific name in mind but something like "Logic" or "Pattern" could be useful, in this chapter, I was thinking about linking to specific chapter about ADR, API or even MVC (using the Sf approach and actual code), we can build a specific API chapter like @javiereguiluz was talking about in the dedicated Slack then adding the ADR chapter, this way, we can allow the visitor to find and easily see how the pattern/logic can be adapted into Sf via example and dedicated tips, any thought about this ? For the corrections, I correct all your recommendations as soon as I'm back on my computer. |
Updating the classes call and prepare for dedicated article.
@HeahDude Just corrected the classes call and prepare for the dedicated article, gonna clone the repo on my computer and add the new file as soon as possible (probably before Sunday). |
@HeahDude Hi, I've just added the dedicated file and the link from service.rst. |
controller/adr.rst
Outdated
} | ||
} | ||
|
||
Final though |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thought?
Updated the Request call then the Twig render() call. |
controller/adr.rst
Outdated
public function __construct(Environment $twig) | ||
{ | ||
$this->twig = $twig; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thinking again about this approach, if we have just one method/controller, shouldn't be simpler inject the required dependencies into __invoke()
directly? Thus, we are avoiding define one property per service argument, if so the action service needs to be tagged with controller.service_arguments
.
After
final class HelloAction
{
public function __invoke(Environment $twig): Response
{
return new Response($twig->render('default/index.html.twig'));
}
}
@yceruto It can work but this make appear the "controller" word inside a "pattern" who don't use it, for me, it can be strange for newcomer (and even for experimented developer) to use the word controller when your class became an Action. This says, @dunglas can probably say more than me about this pattern. |
Corrected the service injection and services configuration.
@yceruto Just made the corrections on service injection via the tags, sorry for the delay. |
controller/adr.rst
Outdated
AppBundle\Action\: | ||
resource: '../../src/AppBundle/Action/' | ||
tags: ['controller.service_arguments'] | ||
public: true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This behavior has been modified for 3.3, now all the services tagged with controller.service_arguments
are public by definition and according to #8415 we can remove it so.
controller/adr.rst
Outdated
As the framework evolve, you must update the services.yml file in order to | ||
use the latest features of the DependencyInjection component, this way, here's the updates:: | ||
|
||
# ... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can be removed?
@yceruto Should be better. |
@HeahDude Your requested changes stay blocking while they were accepted and corrected, bug? |
Added a Responder call and the configuration linked.
Just added a new block for Responder injection and configuration. |
Fix the yaml call and the extra line in the responder configuration block.
controller/adr.rst
Outdated
|
||
In Symfony, you're used to implement the MVC pattern and extending the default :class:`Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller` | ||
class. | ||
Since the 3.3 update, Symfony is capable of using natively the ADR approach. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe it is worth it to add a link to https://github.com/pmjones/adr
Just added the link to the official ADR repository.
@dunglas Should be better. |
How to implement the ADR pattern | ||
================================ | ||
|
||
In Symfony, you're used to implement the MVC pattern and extending the default :class:`Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Symfony has never promoted the MVC pattern (at least, not since version 2). Instead, we are presenting Symfony as being a Request/Response framework where the controller converts a Request to a Response via a Controller.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, my apologies for this words, the meaning of my "text" was to clearly say that a lot of developers use Symfony with MVC and that using this pattern is way more used than just transforming a Request into Response (which is handled by the framework in a certain way, the actual transformation occurs in the controller).
controller/adr.rst
Outdated
tags: | ||
- 'controller.service_arguments' | ||
|
||
Now that the container knows about our actions, time to build a simple Action ! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
extra whitespace before the !
controller/adr.rst
Outdated
Updating your classes | ||
--------------------- | ||
|
||
As the framework evolve, you must update your classes, first, delete your Controller folder and create an Actions one then a new class using the ADR principles, for this example, call it ``HelloAction.php``: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo: evolves
Keep in mind that this approach can be completely different from what you're used to use, in order to | ||
keep your code clean and easy to maintain, we recommend to use this approach only if your code is | ||
decoupled from the internal framework logic (like with Clean Architecture approach) or if you start a new | ||
project and need to keep the logic linked to your business rules. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand this last paragraph and the supposed benefits. I don't see how this approach or what you refer to the old one is cleaner or easier. I don't understand why this approach is more decoupled than the other one. I'm not saying this is good or bad, just that from a beginner's perspective, the benefits are not very clear.
@@ -80,6 +80,11 @@ If your controller implements the ``__invoke()`` method - popular with the | |||
Action-Domain-Response (ADR) pattern, you can simply refer to the service id | |||
(``AppBundle\Controller\HelloController`` or ``app.hello_controller`` for example). | |||
|
|||
As this approach is evolving faster and can be easily transposed into Symfony, we recommend |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How is it evolving?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At this stage, not so much, like before, there's was an error in the real sense of my words, ADR still young and the "logic" keep evolving with time and usage by the developers, the true meaning was to say that using ADR still a "WIP" in Symfony and as the "logic" of ADR still evolving by the feedbacks of the developers, his implementation inside Symfony can be modified with future evolution of the framework or pattern.
In fact, it was possible since Symfony 3.1 when recompiling the container (or like @dunglas do it, by injecting the classes as controllers and mapping the return of each one of them) but using it in production is way easier since 3.3 and 3.4 (and even easier in 4.0)
This PR was merged into the 4.0 branch. Discussion ---------- Controller naming habits As Symfony isn't an `MVC` framework but a `Request/Response` one (see #8153 (comment)), the name of the class which handles the Request isn't forced to contain `Controller`, it's probably more a common usage than a need to make Symfony works. Commits ------- 5b29f5b Minor reword 2b61e3b suggest(Controller): suggestion about naming habits
What should we do with this proposal? I don't see people talking or promoting ADR on Symfony Slack or blogs or web sites or aggregators like Hacker News. Should we close without merging? |
For me, as ADR is only an evolution of MVC (which is mainly used in today's applications), I think that we can close this PR, it's not the role of Symfony to promote this type of architecture as everyone can have a different point of view when it comes to how to implement it 🙂 |
I agree that this is opinionated and should not be part of the official docs. |
OK, let's close then. Guillaume thanks for being so understanding. Thanks. |
With the new approach used by the container, the old controller can be easily replaced by the ADR pattern, as Symfony grow, I think it should be the role of the documentation to show how to use the pattern and how to adapt the framework structure.
PS : I'm not pretty sure of the 'note' syntax.