Hi Midori,

On 31 July 2016 at 10:00, Midori Koçak <mtko...@gmail.com> wrote:
> even though we have classes included in our program, the
> only way to create an object from a class, is to instantiate it in
> unstructured code.

That is the true nature of reality.

All PHP programs start in procedural code, and then require some
bootstrapping before we can enter the lovely world of OO code.

> Most of the programs we write, end up to have some piece of
> spaghetti code somewhere. To prevent this, one should write a god object
and run once but classes are not and should not be code blocks wrapped
around “class” keyword.

All applications start in 'procedural' land. And all applications
require some procedural code to setup the OO environment. You don't
need to create a god object. What you need to do is be able to
bootstrap the OO environment nicely from procedural code.

There is no possible way to escape this. If you try to, what you find
is that you're hiding the 'yucky' procedural stuff away somewhere. It
will still be present, just not in as obvious a location.


> Instead of instantiating objects on the fly, here I propose a structured
> definition of an object using this syntax:

I think what you've done is moved the procedural code into the object
instantiation block. It is still there as procedural code, it just
isn't as obvious. So it doesn't really solve the "problem" of PHP
programs starting of in procedural code, it just makes it harder to
see, which bits are procedural and which bits are OO.


> Consider this piece of code:

> $app->get('/hello/{name}', function (Request $request, Response $response) {
>    $name = $request->getAttribute('name');
>    $response->getBody()->write("Hello, $name");
>
>    return $response;
> });


I think quite a few frameworks show examples that look cool, but
aren't necessarily the best practice. I've been using the Auryn DIC
(https://github.com/rdlowrey/auryn) to do this bootstrapping required
before we can use OO code.

For the example code you showed, I would refactor it to use Auryn with
something like this:

// In an appropriate functions file
function helloName(Request $request, Response $response) {
    $name = $request->getAttribute('name');
    $response->getBody()->write("Hello, $name");

    return $response;
}

//This is a procedural function that returns an object. i.e. it forms
the boundary between the OO code in our application, and the
procedural code.
function createRoutes() {
    // We could read the routes from a data file, or even from annotations
    // Both of those would be just as procedural as this is.
    $getRoutes = [
        '/hello/{name}' => 'helloName'
    ];

    return new Routes($getRoutes)
}

class Application extends App {

    public function __construct(Routes $routes) {
        foreach ($routes->listGetRoutes() as $pattern => $callable) {
            $this->get($pattern, $callable);
        }
    }

    public function dispatch(Request $request) {
        // Do the dispatching of the request against the routes.
    }
}

// In bootstrap.php
$injector->delegate('Routes', 'createRoutes');

// Another function to create a request object, from the $_REQUEST and
other global vars.
$injector->delegate('Request', 'createRequest');
$app = $injector->execute(['Application', 'dispatch']);

The 'delegate' method is the bit where we creating the link between
the lovely OO code, and the 'yucky' procedural code. The delegate
method tells the injector, "whenever an some code we're running
requires an object of types 'Route' call this function to create it".

When the injector creates the Application object, it will see that the
constructor needs a Routes object, and will call the delegate function
to create it.

Although we still have some lines of procedural code, it is reduced to
the bare minimum, and none of the procedural code in the
'createRoutes' function needs to be cluttering up the bootstrap file.

cheers
Dan

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to