I'd like to add my 2cc to the discussion... I think that all the interfaces proposed up to now are really meaningful and have their own place inside an application.
In the most general sense, a web application is something that receives a request and returns a response. This is exactly the HandlerInterface proposed by Rasmus. I like to call this Application: Request -> Response The second interface proposed by David represents nothing else than an edit to an Application ApplicationModifier: Application -> Application These ApplicationModifiers could be very easily composed to build a complex application just by modifying in several steps a simpler one. This seems to me more generic than a middleware approach. Nothing in this definition of the interface suggests that we are building an application adding layer after layer to our core domain. I'm not saying this is bad, but I guess it goes a little outside the scope of defining a middleware interface. Now, if we want to represent a middleware, or a layer of our application, I guess that it should be something like Layer: Request -> Application -> Response (could easily also be Layer: Application -> (Request -> Response), i.e. an ApplicationModifier) which is exactly what the current proposal describes. In this way it is very explicit that what we are doing is having a layer around an application and not an entire application. At this point a "framework" should be something like this Framework: Application -> [Layer] -> Application where the input Application represents our Domain which does not worry about external layers, the list of Layers are the middleware which surrounds the application. The framework would then modify the input Application step by step with the provided Layers to obtain a new Application. This suggests that the core of the application should not be a Layer, but an Application (in other words, it should not receive a DelegateInterface) >From this point of view, I am tempted to propose to keep all three the proposed interfaces. Then some of them (Application and ApplicationModifier) could be easily reused also in a non-middleware application. Just my 2cc... hope it was clear and somehow helpful On Monday, May 15, 2017 at 1:42:51 PM UTC+2, Stefano Torresi wrote: > > Hey folks, > > To be honest, I don't like any of the alternative approaches proposed so > far; I somewhat recognise the concerns raised here, but I think the strive > to a "purer" design poses a very high risk of being counterproductive. We > have already pivoted from one design to another and, as far as I can tell, > it was worth it. > Pivoting once again, though? That could be too far reaching, leaving alone > the fact I personally don't find the alternatives appealing at all: they > may be simpler in theory, but they completely fail on communicating intent, > having to point at convoluted implementation details to outline where the > dispatching mechanism is, while the dispatching mechanism was outside the > scope of the proposal in the first place. > > To be more concise, I think the current proposal is "good enough"(tm). > It is definitely *easier*. It may be not *simpler*, but frankly I don't > think *simpler* is worth the effort, here. > > The mission is to move the ecosystem forward, so: would PSR-15 accomplish > that as it is? > Considering the sheer amount of framework-agnostic middlewares already out > in the wild, and the enthusiastic comments I hear around and about on what > people are accomplishing with them, I am pretty sure the current proposal > would result in a great success, both in terms of adoption and objective > improvement over the current status quo (which, may I remember to you all, > is mostly fragmented in a lot of > framework-specific-half-custom-backed-unportable-mess-of-over-engineered-mvc-doom). > > Having said that, I like the idea of generalising the "Delegate" interface > into a separate "Handler" one. > > This alone would cause a considerable set-back for PSR-15, though, as it > would need to be put on hold while formalising a separate PSR with the due > process. OTOH, as Rasmus noted, this would leave a door open for a > different specification in the future, both for something with not too much > departure from what will eventually be delivered with PSR-15, and something > not even related to middleware at all. > > I think allowing for this change, but leaving the overall design as it is > (i.e. the delegate being a runtime dependency), could be a good compromise > between the parts. > > I understand where you're coming from, Rasmus, but the current design is > far from being inadequate, and lots of people are already enjoying the > results of implementing it. This probably amounts to something. > > Il giorno lun 15 mag 2017 alle ore 12:24 Rasmus Schultz < > [email protected] <javascript:>> ha scritto: > >> > I would be glad if we can find a way to improve this, but I also >> understand Beau whan he says he does not want this to be at the expense of >> simplicity >> >> Please don't mix up "simplicity" with "ease of use". >> >> If we proceed with PSR-15 as-is, it's for ease of use, in spite of added >> complexity. >> >> That's the only reason I'm even pursuing this alternative - it's simpler. >> >> Either way, if we can all agree that a general handler-interface should >> be defined first, I'd be happy, because it leaves all doors open, and >> allows PSR-15 to move ahead as-is, without creating any road-blocks for >> possible alternatives in the future. >> >> That is, PSR-15 should not define it's own DelegateInterface - we should >> have a general HandlerInterface instead, which will have a lot more uses, >> not least in the context of the current PSR-15 proposal as-is, where at >> least Dispatchers will be able to implement them, which provides an extra >> degree of high-level abstraction, which is currently missing from that >> proposal. >> >> As said, my first priority at this time is not to block PSR-15, but >> merely to make sure it doesn't create roadblocks down the line. >> >> If PSR-15 went ahead with an identical interface for delegates that is >> incompatible with a general handler-interface, that would be very bad, as >> this will be non-interoperable with other types of handlers. >> >> If we can agree to do something about that, I'd be happy with PSR-15 >> proceeding essentially as-is, only with the middleware-interface >> type-hinting the delegate with a general handler-interface, rather than a >> middleware-specific one. >> >> And perhaps with an additional clause that suggests dispatcher >> implementations also implement that interface. >> >> My main priority at this time is to make sure we don't unnecessarily cut >> ourselves off from architectural options in the future. >> >> >> On Mon, May 15, 2017 at 10:06 AM, David Négrier <[email protected] >> <javascript:>> wrote: >> >>> Hey Beau, >>> >>> Thanks a lot for your detailed posts. >>> >>> You understood my idea completely and you are expressing (in better >>> words) exactly what I wanted to suggest. I take my hat of to you. >>> >>> Also, you are 100% right in the critics you make. Indeed, middleware >>> authors would have to write 2 classes (one middleware and one factory). You >>> are also right to state that the factory class is mostly a boilerplate >>> class with a constructor that takes the same arguments as the middleware, >>> except the "next" middleware that is provided at runtime to the factory. >>> >>> I've been looking for ways to write a "generic" factory, but to do this, >>> we have to go back to a convention (like in Stack) so I've not yet found >>> something sexy enough to speak about it. >>> >>> Anyway, I'm glad I could help move the discussion forward. I completely >>> forgot to state it but I have really no strong feeling about which way >>> PSR-15 go. I'm really ok with the way PSR-15 is right now. I understand >>> what Rasmus says regarding the fact that not all middlewares need a "next" >>> delegate (or that some need more than one). I would be glad if we can find >>> a way to improve this, but I also understand Beau whan he says he does not >>> want this to be at the expense of simplicity (my proposal requires writing >>> 2 classes and only one class to write is a plus as it will help widen >>> adoption). It looks to me like so far, unless we can come up with a better >>> idea, there is a tradeoff to be done. Whatever way this is going, I'll be >>> happy ;) >>> >>> ++ >>> David. >>> >>> >>> >>> Le lundi 15 mai 2017 02:43:27 UTC+2, Beau Simensen a écrit : >>>> >>>> On Sunday, May 14, 2017 at 11:13:46 AM UTC-5, Rasmus Schultz wrote: >>>>> >>>>> > the middleware themselves cannot be autowired and *must* be created >>>>> manually by the factory. >>>>> >>>>> Are you highlighting this as a problem? >>>>> >>>>> Of course the factory would need to create the middleware - that's >>>>> what a factory is for. (?) >>>>> >>>> >>>> I think there is confusion between your solution and the middle-ground >>>> David was proposing. I had hoped I kept that post more clear but it >>>> appears >>>> I failed. :( My bad. >>>> >>>> First, yes, it is a problem because a middleware that could previously >>>> be autowired can now only be created manually by a factory, even though >>>> the >>>> middleware has not changed much at all. >>>> >>>> Second, with the existing proposal we don't need a factory. Yes, >>>> David's proposal has a factory so yes, obviously, it should be used to >>>> create the middleware. If we ended up going with something like David >>>> proposed, I do not disagree that this is where the middleware should be >>>> created. :) >>>> >>>> My entire set of example code was intended to show what would happen to >>>> one of my real world middleware if we implemented Davdi's proposal. >>>> >>>> >>>> >>>>> > At the end of the day it comes down to whether the delegate/next of >>>>> a middleware should be a runtime dependency or an instance dependency. I >>>>> think that is the core of what Rasmus is exploring here. It seems like he >>>>> has decided it should not be a runtime dependency >>>>> >>>>> I don't feel it's a decision so much as a conclusion. >>>>> >>>>> I'd like it not to be the case, because it would surely be simpler, >>>>> but the fact is that there isn't always precisely one delegate - which >>>>> leads me to conclude it can't be a runtime dependency, or at least not if >>>>> you want the model to reflect reality, which is something I always strive >>>>> for. >>>>> >>>> >>>> This is the same reasoning I would use to argue for why the delegate >>>> should be a runtime dependency. There is never precisely one delegate. The >>>> state that is important at the point in time that the middleware is >>>> executed is the request and the delegate. The middleware instance itself >>>> does not depend on the delegate any more than it does on the request. >>>> >>>> >>>> >>>>> > I'm not happy about the idea that every middleware is going to >>>>> effectively require two classes be written >>>>> >>>>> Let's explore that problem. >>>>> >>>>> I think, first of all, you need to not think of this as "middleware >>>>> consisting of two classes" - it's really two different classes, one is a >>>>> handler, the other is middleware: they have different purposes in >>>>> different >>>>> contexts. >>>>> >>>> >>>> Again, this line of thought was directly related to David's proposal. >>>> >>>> I'm confused by what you said here, though, so maybe you can elaborate. >>>> Not sure if this is talking about something else or about David's proposal >>>> or....? >>>> >>>> What I had said was not that "middleware would consist of two classes", >>>> but that "writing middleware would require writing two classes." Since >>>> this >>>> was about David's proposal, this was a factory and a middleware. Where I >>>> previously had one middleware class, it turned into a middleware class and >>>> a factory class. The example I shared showed the BEFORE code with one >>>> MiddlewareInterface implementation and AFTER showed two classes, a >>>> MiddlewareFactoryInterface and a MiddlewareInterface. >>>> >>>> What you said is something different. What do you mean by "one is a >>>> handler, the other is a middleware?" Also, "they have different purposes >>>> in >>>> different contexts." Can you show me what that looks like using the >>>> example >>>> code I shared with BEFORE / AFTER on the User ID metadata enricher >>>> middleware? Because I'm starting to wonder if I've completely missed >>>> something major here. Probably easiest to just start with the simple >>>> BEFORE >>>> middleware and then I'd be able to compare against what I came up with for >>>> my AFTER to see if I can follow this better. >>>> >>>> >>>> >>>>> If the only problem is deferring the loading and creation of handlers, >>>>> and the issue is "not knowing" which constructor-argument is the >>>>> delegate, >>>>> maybe we could solve this by marking that argument somehow... >>>>> >>>> >>>> I think that has been the biggest sticking point for me. We never had a >>>> good solution for this for Stack except for the conventions that allowed >>>> Stack Builder to be successful. It suffered drawbacks as discussed >>>> previously in this thread. >>>> >>>> If this bit of code is doing what I think it is, it might be an >>>> interesting idea: >>>> >>>> >>>> https://bitbucket.org/mindplaydk/middleware-experiment/src/d5c26eba9e445f2f9d2b9f3fd8ee465812c2ab0c/src/Dispatcher.php?at=master&fileviewer=file-view-default#Dispatcher.php-49 >>>> >>>> The only problem is that I'm not sure how many containers would support >>>> this. I *think* this is the first time I've seen this in a container. >>>> >>>> >>>> >>>> I'm still hung up on the runtime dependency vs not. I don't agree with >>>> the conclusion. That doesn't mean I cannot be convinced otherwise. :) >>>> >>>> I think I'm starting to better understand what you're getting at, >>>> though. Is this an accurate summary of your conclusion? >>>> >>>> The only difference between a handler and a middleware is the delegate. >>>> If we can find a way to remove the delegate from the handler method >>>> entirely, then there is no difference between the two as far as >>>> `handle(req) : res`. >>>> >>>> >>>> -- >>> You received this message because you are subscribed to a topic in the >>> Google Groups "PHP Framework Interoperability Group" group. >>> To unsubscribe from this topic, visit >>> https://groups.google.com/d/topic/php-fig/B3jtdJA7-6w/unsubscribe. >>> To unsubscribe from this group and all its topics, send an email to >>> [email protected] <javascript:>. >>> >> >>> To post to this group, send email to [email protected] >>> <javascript:>. >>> >> To view this discussion on the web visit >>> https://groups.google.com/d/msgid/php-fig/a48f9e36-b994-419f-a35e-f721cc9475c1%40googlegroups.com >>> >>> <https://groups.google.com/d/msgid/php-fig/a48f9e36-b994-419f-a35e-f721cc9475c1%40googlegroups.com?utm_medium=email&utm_source=footer> >>> . >>> >>> For more options, visit https://groups.google.com/d/optout. >>> >> -- >> You received this message because you are subscribed to the Google Groups >> "PHP Framework Interoperability Group" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to [email protected] <javascript:>. >> To post to this group, send email to [email protected] >> <javascript:>. >> To view this discussion on the web visit >> https://groups.google.com/d/msgid/php-fig/CADqTB_iisb8BXb4ww1TMNVeiJytAh%2BYeZm5hPm2PDOdrPRn9LQ%40mail.gmail.com >> >> <https://groups.google.com/d/msgid/php-fig/CADqTB_iisb8BXb4ww1TMNVeiJytAh%2BYeZm5hPm2PDOdrPRn9LQ%40mail.gmail.com?utm_medium=email&utm_source=footer> >> . >> For more options, visit https://groups.google.com/d/optout. >> > -- You received this message because you are subscribed to the Google Groups "PHP Framework Interoperability Group" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/php-fig/b76fdb13-d7cb-4952-b573-6084532ac8ec%40googlegroups.com. For more options, visit https://groups.google.com/d/optout.
