Sunday, December 31, 2017

Series: Serious PHP

I've been a PHP developer professionally for many years and one of the great
joys of my life as a dev has been to see the recent PHP Renaissance.
PHP seemed moribund, but a couple of things happened that completely revitalized the ecosystem. Here are, in my estimation, the most important factors:

  1. Composer for package management revolutionized and drastically simplified dealing with dependencies.
  2. The emergence of the PHP FIG and the PSR standards have gone a very long way to standardizing and professionalizing the ecosystem.
  3. PHP 7 was released, and it was fast, making PHP a serious contender for enterprise development (again?)
  4. Laravel exploded in popularity and it showed an entire generation of coders that PHP can actually be a joy to work in. 

Given that PHP, far from dying a slow painful death, seems to have hit something of a second wind, I've been wondering if the increasing professionalism and seriousness of the ecosystem means that similarly "serious" training material has been, or is being, produced for PHP.
For the longest time there were only a handful of serious books about developing in PHP and some of them were of questionable quality.

So one of the things I'd like to do in 2018 is take a look at the training landscape for PHP and see what's out there.
Do we, for instance, have anything like Sandi Metz' "Practical Object Oriented Design in Ruby"? Books that are so good they transcend their language?
Which books would I suggest a junior read to get really deep into the language, but which will stand them in good stead long after they leave PHP behind?

I'm not suggesting that PHP devs should be parochial in their reading, but I would like -- rather than assuming the "good stuff" comes from other communities -- to identify our own "good stuff".

Friday, December 22, 2017

36 in review.

So I can't actually believe that I'm writing one of these posts again - it feels like just a moment ago that I wrote my first two entries (34, 35) in this review series.

Review

So last year I said that I was aiming for just two things.

1 - Writing and submitting a story a month
2 - Push myself professionally.

So I didn't track point 1 very closely, but I probably made it close to that. I submitted 25 times this year only, with 4 acceptances (one of which was a reprint of an old story). Still, I'm surprised that it was that many, given the big changes in my little family's life this year. So let's call that a success, especially under the circumstances.

On point 2, I think I've made some nice progress. I joined Amazee Labs as a senior developer where I work with some mighty talented people, and I've also made a number of contributions to Open Source (mostly p5.js - at the time of writing, I'm number #22 on the contributors list)

So yeah. Win.

Favorite Fiction discovered

I read some great novels and comics this year. My favorite were probably Michael Cunningham's The Hours, which speaks really deeply to anyone who spends their time trying and failing to make great art.

The other major love from this year's reading was Charles Burns' "Black Hole", a graphic novel unlike anything I have ever read. Unsettling and brilliant, read it.

 

Favorite Technical Book discovered

I'm ashamed to say it, but last December was the first time I ever read Uncle Bob's "Clean Code". In my defense, it was the first year I could actually afford a copy (for some reason, until the end of 2016, all online stores in South Africa that sold the book were ridiculously priced). In some respects I'd expected more from the book, given its status, but even so, I believe it was one of the better books about code that I've ever read, and unreservedly recommend it to anyone who wants to write better code.

Writing

2017 was a great writing year.

First, my short story Ndakusuwa was nominated for a Nommo award - a massive honor, even though I didn't win.

Second, my short story "Remains of an Old World" won the 2016 Bloody Parchment short story competition. A serious honor. It'll appear in an anthology next year (I think).

My short story "Sulky" came out in the Parsec Ink "Appetites" anthology, and -- so cool -- was discussed on an SFF podcast (side note: Alan and Jeremy Vs SF is an excellent resource - listen to it).

I also had a short story ("Practical applications of machine learning") published in the South African literary journal Type/Cast.

General

As I said in an earlier post, my family packed up and moved country this year. So things from around May have been difficult. Moving countries, leaving family, getting resettled all takes up a bunch of head space, so my output -- especially on the fiction side -- has taken a dramatic plunge (hence my not even mentioning philosophy).


Plans for 2018


I think that I've managed to get myself settled I can get back to the good work.

I have three things I want to do next year.

  1. I need to focus on my health and fitness. Its something that always comes third or fourth on my list of things to do, and so it simply falls off. I'm not sure what making this a priority looks like just yet, but I'll update during the year.
  2. Writing. I want to write more longer fiction this year than I've ever written before. I also need to get rid of parallelism in my writing, since it just means I don't actually get things done.
  3. Code: I want to focus on doing more projects this year than previous years.

Wednesday, November 15, 2017

Generative poem: /usr/bin/diff

Source, Edit, diff

2,3c2,3
< or if time even makes sense
< anymore.
---
> before my next shift, but I
> had to say hi.
5c5
< investigate some signal found
---
> investigate tidal forces in binary systems
7c7
< Some regular beeping out of
---
> So we set up in orbit around
13,20c13,17
< that we clicked
< we were facing something indescribable, something terrible
<
< something like God.
<
< Something like Death.
<
< We're not coming home,
---
> that we clicked that
> we were faced with something entirely new
> something like waves.
> Something like sound.
> We're not coming home just yet,
22,24c19,21
< it hates us,
< and now
< it knows
---
> I miss you,
> and soon
> we'll be
26,27d22
<
< I'm sorry.

Wednesday, September 20, 2017

Lethaba DI Container

In my last post I wrote up some notes about reading the Pimple 1.x source.
At the end of it I mentioned I wanted to write a DI container myself.

Behold, Lethaba DI - a stupidly simple clone of Pimple.

A couple things - I decided against implementing the ArrayAccess interface and followed Laravel in making the container callable, so in order to grab something out of the container instead of this

$container['service'];

we go

$container('service');

But beyond that ... it's pretty much a clone.

Tuesday, September 19, 2017

Reading Source code for Pimple 1.x

I have huge respect for Fabian Potencier, the man is a code machine, and in addition to his work in open source, you have to admire his commitment to educating other devs (check out his "create your own framework" series).

Recently I was researching Dependency Injection and came across Pimple, Silex's (the microframework) DI container. There's a helpful note on the frontpage that tells us that reading the source for Pimple 1.x is a great way of learning how to write a simple DI container.
So I read it. Here are my notes.

Preamble - Dependency Injection


So why worry about DI generally? Well, good question, and one covered quite well in the Wikipedia article I've linked to above. For completeness, though (and for my own peace of mind) I'll give a quick take on it here.
Dependency Injection describes a pattern or technique that, if implemented, frees up your objects from having to worry about how their dependencies are created, and indeed, from creating them themselves.

Compare

Class A
{
    private $databaseConnection;
    public function __construct()
    {
         $this->databaseConnection = new \DatabaseConnection("server", "username", "password", "catalogue");
     }
    /** snip **/
}


In this first example (whatever other issues it has) our class A is tightly coupled to the \DatabaseConnection class. Our class can only ever use this kind of db connection (rather than say some specialized sub-class, or a mock while testing).
If the \DatabaseConnection class ever changes, say it needs a new parameter when it's instantiated, we'll need to change our class's own constructor as well (SRP, hi!).

The usual way of sorting this out is to pass through any objects that our own class might rely on ...

Class B
{
    private $databaseConnection;
    public function __construct(\DBConnectionInterface $databaseConnection)
    {
        $this->databaseConnection = $databaseConnection;
    }
    /** snip **/
}
Notice now we've loosened up our class's relationship to the DatabaseConnection class - when newing up our own class, we now simply pass through a DatabaseConnection object, and because we're coding to an interface, we can merrily use our $this->databaseConnection regardless of what actual class is passed through to us.

This seems to just push back our problem though, right? Isn't the code that goes ahead and creates the instance of our class B now responsible for creating the objects it's dependent on. And What if we create instances of B in more than one place? Surely the virtue of having a constructor is that we only really need to describe its set up in a single place? This is true, which is why the DI pattern exists.

Central to it is the idea of an injector, or--more commonly--a container (see the wikipedia article for the rest of the synonyms). The container represents a place where the creation of objects can be centralized. Rather than have our code, say, create new database connections in several places, we centralize the logic for creating databases in our container. If how we create a database connection changes, we only need to change that in a single place.
Not only that, if any of the objects in the container have dependencies themselves, the container will be able to manage them too - long chains of dependencies are resolved inside the container.

And this is what Pimple does - it's a DI container. We tell it how to create things like our Database connection, and then when we need one in our code, we just ask the container to give us one.

In our example, we could create a new instance of class B with our container doing something like ...

$b = new B($container['databaseConnection']);

or, in some cases it might be appropriate to have the container create our instances of our B class itself ...

$b = $container['B'];


The Code


There isn't much to Pimple 1.1. Just over 200 lines of code with comments and whitespace. It does a lot with a little though.
I'll be giving line numbers from here - so feel free to follow along.

ArrayAccess

First things, it implements (line 33) the ArrayAccess interface. If the name doesn't give it away, this interface lets our objects act as arrays, i.e. calling code is able to interact with the object using the square bracket syntax.

This let's us both put stuff in the container like this

$c['key'] = $value; //C1

and read stuff from the container like this

$value = $['key']; //C2

I'd be interested to know why Fabpot went this way. My guess is that the assignment side is made nice and clean.
Consider an alternative - putting something into the container with some kind of setter

$c->setValue('valueName', $value); //C3

I don't see this being a showstopper, but it's certainly not as concise as C1 above.
That's just a guess, though.

A lot of the functionality of the class is simply implementing the ArrayAccess interface (i.e. providing implementations of offsetExists, offsetGet, offsetSet, offsetUnset).

Defining parameters

I'm following the sections in the documentation here, looking at what kinds of things the service container can store, and seeing how this is achieved.
First off are parameters, these are just straightforward values. There's not much to be said about these - most of the work in the code is done to figure out when we're not working with parameters.

With parameters, the container is simply acting as an abstraction over the internal store (line 35).
It's important that the container be able to work with simple values without too much overhead because simple values are also part of the dependencies needed to create objects (in our DB connection example, things like the username and password may be considered parameters).

Having all our dependencies accessible through a common interface seems like good design.
This point about common interfaces will become clearer when we see the recursive nature of service definition next.

Defining services

Services are the heart of the DI pattern. Insofar as Pimple defines them, they're "Object[s] that [do] something as part of a larger system." Consider the case I described in the preamble - we want to create a DatabaseConnection service. This is achieved by passing an anonymous function to the container that knows how to create, and will return, the object type.

Our example might be something like

$containerInstance['DBConnection'] = function ($c) {
   return new \DatabaseConnection($c['server'], $c['username'], $c['password'], $c['catalogue']);
};

Pretty straightforward -- note, though, the argument $c that's passed to the function, that's an instance of the container itself! This is what enables the container to resolve any dependencies that a service might require (assuming that the dependencies are actually defined in the container - if not, expect errors).

The magic here comes in line 81, in the offsetGet() method, where we try pull the service out. We check whether the thing we're trying to pull out is an Object, and if it is, whether it's invokable. Recall that a php anonymous function just is an instance of a particular class (http://php.net/manual/en/class.closure.php), which is why that check works as it does.

If an invokable class is found, Pimple will call it and pass itself as as argument (for further dependency resolution, if required).

Shared services

Shared services act like a singleton (the Laravel container uses this terminology explicitly) - instead of returning a brand new object every time the service is requested, it'll create the object once, and return the same instance on subsequent calls.

You do this by adding running your function through the container's share() method before adding it, like so:

$containerInstance['DBConnection'] = $containerInstance->share(function ($c) {
   return new \DatabaseConnection($c['server'], $c['username'], $c['password'], $c['catalogue']);
});

This is where things start getting slightly more interesting - the share() function (lines 116-131) does the following:
First checks that what we've passed through is actually invokable (line 118, same logic as described above), throwing an exception if it isn't.

If it is, then it wraps it in a new anonymous function which makes use of a static variable to store the shared service object (i.e. whatever the anonymous function we pass in returns). When you use the static keyword inside a function, the variable declared as static does not lose its value after it's finished executing. This is dangerous, but really powerful (read more here).

Essentially, what the share() method does is check whether it has ever been run before (i.e. is the static variable null) and if it hasn't, it runs the function we've passed it and stores the result.
This is a fairly standard memoization pattern, less often seen in PHP than in the JS world, in my experience.

Protecting Parameters

You might've noticed a problem here. What if we want to store an anonymous function as a parameter? That is, what if we want to be able to retrieve a function from our container without the container running it? As it stands, whenever we drop an invokable into the container, it's going to be run with the container itself as an argument.
To avoid that, Pimple provides the protect() method (lines 142-151) - it's used the same way as the share() method and does the same kind of thing - wraps our function in another function, except, in this case, all the wrapping function does is return the wrapped function, rather than execute it.

Note that we can pull out functions from the container without them being executed by using the raw() method (lines 162-169).

Extending Services

The last little piece of functionality I want to cover is the mechanism used for extending services after creation. The idea here is that we might want to take the results / output of a service and modify it in some way before it's resolved/returned. This is achieved by, once again, wrapping functions within functions. In this case, we're taking both the original callable function and our extension and wrapping them up in a third.

Let's take the documentation's example of modifying a mail service:

$container['mail'] = function ($c) {
    return new \Zend_Mail();
};

$container['mail'] = $container->extend('mail', function($mail, $c) {
    $mail->setFrom($c['mail.default_from']);
    return $mail;
});

See that the function doing the extension takes two parameters, the first ($mail) being the original value of mail in the container, and $c which, as always, is the container instance itself.

Most importantly, how is this accomplished in the extend() method (lines 184-203)?
The meat of it all, after a few tests, lives on lines 200-202. Here, what's happening is that Pimple is taking the existing service and passing it and the extension function that we've defined to a new anonymous function via the "use" keyword (i.e. the new anonymous function inherits them from its parent's scope).
The cool thing about this is that extensions can be extended in this way indefinitely through a series of nested calls.

Next Steps


I was planning on writing my own DI container based on Pimple (as part of a larger project), if I do, I'll post the code up here too.

Sunday, September 17, 2017

Hello New Zealand

So the last few months have been hectic, to say the least.
Wanna know how to derail all your plans?
Move country.

But, here we are now living in the Shaky Isles down in Windy Wellington.

The move has meant that I've had to shuffle a few things around - but in terms of yearly progress, I haven't been doing too badly considering the massive upheaval.

I've managed to make a few contributions to FOSS (p5.js mostly).

I've also managed to get some, but not much, writing done - including a forthcoming story in Grievous Angel (which marks my 3rd pro-sale).

I'd like to resurrect this blog to some extent as well. I've been reading some really great stuff lately, both code and prose, and have been thinking that this is the perfect place to document what I've learned.

For instance, a couple months ago I read most of the source for the Slim Framework, something I heartily recommend, but I've misplaced my notes (in the move, no doubt) - so if I pop them all in my blog, I'll not only not lose them going forward, but perhaps, just perhaps, they'll be useful for others too.

Don't expect any unifying theme here, I'll just be capturing in blog posts what I've been reading, whether that be source code or short stories or philosophy papers.

Anyways - hi from New Zealand. Let's see if we can get some writing and coding done.