On Tue, May 3, 2016 at 2:35 PM, Fleshgrinder <p...@fleshgrinder.com> wrote:

> On 5/3/2016 10:22 PM, Ryan Pallas wrote:
> > I have to disagree, I haven't seen an example of rewriting the original
> > example from the RFC in a more expressive AND readable way. Yes, you can
> > use lots of intermediate variables, but this makes the code HARDER to
> read
> > QUICKLY which is entirely the point of a syntatic sugar addition like
> this.
> > Syntactic sugar makes a language sweeter, and more palatable. Like cane
> > sugar makes your cookies taste good, but doesn't make them more
> nutritious.
> >
>
> Opinions you know but I am still waiting for that example.
>

Waiting for what example? There's been plenty of examples showing how
existing options, rewritten with |> are easier. If you disagree, that's an
opinion, other's agree. If people think its better, why not add it for
them? Like every other feature discussed on this list, nothing is forcing
you to use it.


On Sat, Apr 30, 2016 at 4:00 AM, Thomas Punt <tp...@hotmail.co.uk> wrote:
>
> > From: ocram...@gmail.com
>
> $response = loadConfig()
>  |> buildDic($$)
>  |> getApp($$)
>  |> getRouter($app)
>  |> getDispatcher($$, $request)
>  |> dispatchBusinessLogic($$, $request, new Response())
>  |> renderResponse($$)
>  |> buildPsr7Response($$)
>  |> emit($$);
>
> Without the pipe operator, it could look like the following:
>
> $config = loadConfig();
> $dic = buildDic(config);
> $app = getApp($dic);
> $router getRouter($app);
> $dispatcher = getDispatcher($router, $request);
> $businessResponse = dispatchBusinessLogic($dispatcher, $request, new
> Response());
> $renderedResponse = renderResponse($businessResponse);
> $psr7Response = buildPsr7Response($renderedResponse);
> $response = emit($psr7Response);
>
> That's a lot of unnecessary assignments, however, and the variable names
> don't even provide any additional readability benefits because the function
> names are already self-documenting.
>
>
The first example, with |> is much easier to QUICKLY see what's happening,
because all the function calls are aligned, so I can read quickly top to
bottom knowing what's happening. The second requires much more cognitive
interaction to understand what's going on. Sure you could reformat it to
align all the =, now you have lots of white-space between your variables
and what you're assigning to them... equally as bad in my book.



>
> On 5/3/2016 10:22 PM, Ryan Pallas wrote:
> > This breaks dependency injection, and makes testing harder.  You now
> depend
> > on an array of data which is accessed internally, and can only minimally
> > control it's contents in a testing environment.
> >
>
> Why do you need dependency injection in the most outer point of your
> application? This should be tested with your acceptance/integration
> tests and nothing else. How many unit tests have you written for your
> Symfony app kernel lately?
>

None, I don't write Symfony apps, however they wrote quite a few [1].


> A rather extreme example of such a /most outer/ but you know how it is
> with constructed examples:
>
>
> http://www.yegor256.com/2014/10/03/di-containers-are-evil.html#the-right-way


GROSS. This would not be allowed any where I do code reviews.


>
>
> On 5/3/2016 10:22 PM, Ryan Pallas wrote:
> > Again, how do I dependency inject a config during testing to make sure I
> > build the dic correctly? I'm assuming you're using a bunch of temporary
> > properties? Also you just made adding a step significantly harder, what
> if
> > from building the app, I need to build another layer build for the
> router,
> > for |> I add ONE line of code, for yours I edit the build function in the
> > right location, and change the build router function to load from a
> > different property, and build another boilerplate function to build this
> > new thing, and add another property to hold this new thing... WHOA
> that's a
> > lot more steps, and a MUCH higher risk of a mistake!
> >
>
> Again, this is the most outer place of everything. I mean, all
> frameworks and applications were and are able to solve these issues
> easily, nicely, and testable. Just because my /proposed/ solution to an
> example that is constructed in the first place is not as nice as those
> solutions does not make the examples better. :P
>

You didn't address the fact that your "solution" makes it much harder to
modify the steps in place.

$ret = getConfig()
      |> buildApp($$)
      |> buildRouter($$)
      |> parseResponse($$);

Shoot, I forgot to build Dispatcher; Let me add that

$ret = getConfig()
      |> buildApp($$)
      |> buildRouter($$)
+    |> buildDispatcher($$)
      |> parseResponse($$);

Such a minimal change. Lets try yours:

final class ResponseBuilder {
    private $config;
    private $app;
    private $router;
    private $response;

    private function loadConfig() {}

    private function buildApp() {
        $this->app = new App($this->config);
    }

    private function buildRouter() {
        $this->router = new Router($this->app);
    }

    private function parseResponse() {
        $this->response = new Response($this->router);
    }

    public function build() {
      $this->loadConfig();
      $this->buildApp();
      $this->buildRouter();
      $this->parseResponse();

      return $this->response;
    }
  }

Shoot, I forgot dispatcher; let me add that

final class ResponseBuilder {
    private $config;
    private $app;
    private $router;
+  private $dispatcher;
    private $response;

    private function loadConfig() {}

    private function buildApp() {
        $this->app = new App($this->config);
    }

    private function buildRouter() {
        $this->router = new Router($this->app);
    }

+  private function buildDispatcher() {
+      $this->dispatcher = new Dispatcher($this->router);
+  }
+
    private function parseResponse() {
-       $this->response = new Response($this->router);
+      $this->response = new Response($this->dispatcher);
    }

    public function build() {
      $this->loadConfig();
      $this->buildApp();
      $this->buildRouter();
+    $this->buildDispatcher();
      $this->parseResponse();

      return $this->response;
    }
  }

Whoa that's significantly more changes, and therefore significantly more
chances to make a typo!



> On 5/3/2016 10:22 PM, Ryan Pallas wrote:
> > Again, you're solution is to use OOP, but the pipe operator's purpose is
> to
> > make procedural code cleaner. Not one of your solutions maintained a
> > procedural interface, and therefore is not an argument against the |>
> > operator. The purpose of this operator is syntactic sugar, which "is
> syntax
> > within a programming language that is designed to make things easier to
> > read or to express. It makes the language "sweeter" for human use: things
> > can be expressed more clearly, more concisely, or in an alternative
> style *that
> > some may prefer*."[1] (emphasis mine). Its not designed to solve a
> problem
> > of how can I do this thing, but how can I write this thing such that my
> > team might be able to understand it better.
> >
> > Yes, you can rewrite these examples in an entirely different way, but now
> > you're not comparing apples to even other fruit (procedural vs OO is not
> > the same). The point of this is to take a very common pattern (nesting
> many
> > procedural calls) and make it easier to read and manage later.
> >
>
>   foreach (scandir($arg) as $path) {
>     if ($path !== '.' && $path !== '..') {
>       $ret[] = getFileArg($arg . DIRECTORY_SEPARATOR . $path);
>     }
>   }
>
> What can I say ...
>

Valid, and the only way I've seen this written I like. :)


>
> --
> Richard "Fleshgrinder" Fussenegger
>
>
[1]
https://github.com/symfony/symfony/tree/master/src/Symfony/Component/HttpKernel/Tests

Reply via email to