RFC: Refactoring nette/application dependencies

5 years ago

Jan Tvrdík
Nette guru | 2563
+
+13
-

Refactoring nette/application dependencies

This RFC proposes to split nette/application into 4 packages and reduce their dependencies.

Current state

Currently the nette/application contains the following responsibilities:

  1. Routing (IRouter, Request, Routers\)
  2. Application life-cycle (Application, Responses\, IPresenter, IResponse…)
  3. UI layer (UI\Presenter, UI\Control. UI\Form…)
  4. Micro framework (MicroPresenter)

Among the dependencies is nette/di.

Proposed state

Note that the dependency on nette/di will be entirely removed.

Classes in nette/routing package will be moved to new namespace Nette\Routing:

  • Nette\Routing\IRouter
  • Nette\Routing\AppRequest (?)
  • Nette\Routing\Routers\CliRouter
  • Nette\Routing\Routers\Route
  • Nette\Routing\Routers\RouteList
  • Nette\Routing\Routers\SimpleRouter
Proposed version

This RFC targets Nette 2.3 2.4.

Impact on backward compatibility

This breaks all packages which depend on nette\application ~2.2 and require anything from UI layer. We can possibly workaround this by creating one more package but I recommend not doing so.

Rationale
  • You can use routing independently.
  • You can use micro-framework without installing tons of stuff you do not need
  • Cleaner dependencies
Open questions
  • Names of the 3 new packages.
  • New name for Nette\Application\Request
    • Nette\Routing\Request
    • Nette\Routing\AppRequest
    • Nette\Routing\ApplicationRequest
    • Nette\Routing\InternalRequest
Changelog
  • Updated “Proposed state” section to mention impact on namespaces.
  • Added new open question regarding new name for Nette\Application\Request

Last edited by Jan Tvrdík (2014-11-02 14:52)

5 years ago

enumag
Member | 2128
+
0
-

I was thinking about using Presenters & Controls with a different routing library. No support for that?

5 years ago

Filip Procházka
Moderator | 4693
+
0
-

@enumag you could do that by implementing custom IRoute that will wrap the other routing lib.

5 years ago

Jan Tvrdík
Nette guru | 2563
+
0
-

No. The IRouter interface is very general, use adapter pattern if necessary.

5 years ago

Milo
Nette Core | 1151
+
0
-

@JanTvrdík How would you remove a dependency on Nette\DI from tree? The PresenterFactory has it in constructor. Or UI\Presenter::injectPrimary(Nette\DI\Container $context = NULL, ...)

5 years ago

Jan Tvrdík
Nette guru | 2563
+
0
-

@Milo Good question! A general rule of DI is that nothing should depend on DI container.

Presenter has already been refactored by @DavidGrudl to have DI\Container as optional dependency only. We may remove the dependency entirely or keep it as optional.

PresenterFactory is a bit tricky. It currently has two responsibilities:

  1. Mapping between Application\Request::getPresenterName() and class name.
  2. Creating presenter instances

The first responsibility is OK, only the second one causes trouble. What PresenterFactory should receive instead of DI\Container is a list of factories / callbacks (one for each presenter). Building of the list will be responsibility of someone else. In our case it will be most likely a compiler extension. And yes, that would require all presenters to be registered as services. We may probably figure out some way to keep the registration optional. Although I'm not sure whether we really want to make it optional (registering it has multiple advantages).

Last edited by Jan Tvrdík (2014-11-02 12:47)

5 years ago

enumag
Member | 2128
+
0
-

@JanTvrdík Why not just one callback? (That's how I solve similar cases.)

5 years ago

Jan Tvrdík
Nette guru | 2563
+
0
-

I've updated the RFC to mention impact on namespaces.

Last edited by Jan Tvrdík (2014-11-04 22:56)

5 years ago

Honza Marek
Member | 1674
+
0
-

@JanTvrdík Creating presenter instances is the main responsibility of PresenterFactory. Mapping between names and classes is just an internal detail (and part of the creation process).

5 years ago

Jan Tvrdík
Nette guru | 2563
+
+1
-

@HonzaMarek Yes. The problem is that PresenterFactory does not creates the instances itself but delegates the responsibility to DI container. Which is wrong.

Last edited by Jan Tvrdík (2014-11-03 13:15)

5 years ago

mkoubik
Generous Backer | 734
+
0
-

Should Application\Request really be part of routing? I think the general router should map between Http/Request and some bag (array?) of parameters. Then there would be some bridge between routing and application that would map these parameters (among them method, presenterName, etc.) to Application\Request.

5 years ago

Filip Procházka
Moderator | 4693
+
+1
-

@JanTvrdík actually, I think we should go even further and not even create instances using DIC (by the createInstance method), but have all presenter registered in DIC and then have them created using the DIC properly.

4 years ago

Jan Tvrdík
Nette guru | 2563
+
+4
-

2015 Summer Status Update

  • PresenterFactory no longer (since Nette 2.3) depends on DIC. Good job!
  • All presenters are now (since Nette 2.3) registered in DIC. Good job!
  • It is currently being discussed whether presenters (in general) can and should be autowired.
  • RFC now targets Nette 2.4

This is still something I want to do. I once again work on a web application without HTML interface. Therefore I need to have installed the following packages even though they are useless for me.

  • nette/security
  • nette/reflection
  • nette/component-model
  • nette/application-ui (as part of nette/application)
  • nette/micro-fw (as part of nette/application)

@DavidGrudl Would you accept this for Nette 2.4 or do we need to wait for 3.0?

4 years ago

looky
Member | 100
+
0
-

I would love to see this RFC going somewhere!

4 years ago

David Grudl
Nette Core | 6887
+
0
-

Routing should be moved to new package nette/routing, but it must be independent on Nette\Application\Request, ie. nette/application should depend on nette/routing but not vice versa. Routing can IMHO operate with simple array.

UI can be moved to new package, but it is not so easy, because there are some dependencies in LinkGenerator or Application etc.

To create package micro-fw that will contain only MicroPresenter.php is useless.

Dependency on nette/reflection exists only for back compatibility, due to $presenter->getReflection()->getMethod(...)->hasAnnotation(...). I'd like to remove it in future, but it is BC break.

Dependency on nette/security will be needed (maybe) due to https://github.com/…ation/pull/4.

The fact that you need to have installed packages that you don't need is (unfortunately) normal. NPM installs tons of packages. After splitting into more packages you will have installed less number of packages (for you very rare usecase, application without UI), but majority will have to install more packages for standard use.

ad 2.4 vs 3.0: currently I have no release plan.

4 years ago

Jan Tvrdík
Nette guru | 2563
+
0
-

Routing can IMHO operate with simple array

Why not move Nette\Application\Request to nette/routing as suggested in the original proposal? Because it's too closely related to Nette\Application? It seems a bit strange to replace this

return new AppRequest(
    $presenter,
    $httpRequest->getMethod(),
    $params,
    $httpRequest->getPost(),
    $httpRequest->getFiles(),
    array(AppRequest::SECURED => $httpRequest->isSecured())
);

with this

return [
    'presenter' => $presenter,
    'method' => $httpRequest->getMethod(),
    'params' => $params,
    'post' => $httpRequest->getPost(),
    'files' => $httpRequest->getFiles(),
    'flags' => array(AppRequest::SECURED => $httpRequest->isSecured())
];

UI can be moved to new package, but it is not so easy, because there are some dependencies in LinkGenerator or Application etc.

That's why I wanted LinkGenerator to look more like Nextras LinkFactory.

Dependency on nette/reflection (…) I'd like to remove it in future, but it is BC break.

As long as users can override getReflection() in BasePresenter it is easy to fix.

To create package micro-fw that will contain only MicroPresenter.php is useless.

I disagree with it being useless, although it is currently not as important.

NPM installs tons of packages.

NPM is bad example. It's problem are not small packages (which result in having a lot of them), but having tons of packages which do pretty much the same. So every time you install some NPM package, you end-up with multiple promise implementations, multiple process abstraction, tons and tons of utils packages and even more packages that I don't even understand why they exist in the first place.

you will have installed less number of packages (for you very rare usecase, but majority will have to install more packages for standard use.

Yes, that is good point. Although I would say that not using Application\UI is not that rare and we should educate people (this RFC is one of many steps) to not use Application\UI (e.g. for API or CLI) more.

ad 2.4 vs 3.0: currently I have no release plan

I don't care as much about the version number as about the probability that it would be merged if I started working on this.

4 years ago

David Grudl
Nette Core | 6887
+
0
-

ad router: only $params are needed. The $presenter can be extracted from $params by nette/application. Everything else is direct copy from Nette\Http\Request. So routing can be really only about Http\Request → params and params → URL.

New nette/router should somehow solve current shortcomings, like $refUrl parameter, using modules, enabling https, etc.

ad application: nette/application is closely tied to HTTP, so it is not suitable to be used in CLI. It could be renamed to nette/web-application and new nette/cli-application could be created, but more realistic is to have nette/application and symfony/console.

ad merge: of course I would merge it.

4 years ago

Felix
Nette Core | 957
+
0
-

David Grudl wrote:
ad application: nette/application is closely tied to HTTP, so it is not suitable to be used in CLI. It could be renamed to nette/web-application and new nette/cli-application could be created, but more realistic is to have nette/application and symfony/console.

I'd love to have web-application and cli-application. It could be next generation of framework based on simple commands. Just nette way.