Archive for the 'Programming' category

I think I understand bounded contexts

published on October 24, 2017.

Earlier this year I started reading the DDD book by Eric Evans. Together with the Eventsourcery videos from Shawn McCool, the first three chapters of the book were… easy to understand, even. Lots of “A-ha!” and “Oh!” moments, followed by “That makes perfect sense.” statements, and a couple of excited “I knew that!”-ones. Then I got to the chapter with the bounded contexts. I read the first few pages, thought about them… Then read them again, and thought some more. Then I put the book back on the shelf for a few months.

Last night I read it again, and then…

Click!

A bounded context is a point of view.

A bounded context defines how a section of a business sees, thinks, talks about a subject that is important to that section of the business. And we represent that business subject with a model. That same business subject can be present in different sections of a business, but every section views it differently. To some extent, at least. That is the reason why the context of a model is important — we need to know how to model a subject for that specific business section.

And we need to put boundaries on those models — we must prevent the mixing of, what might seem same, models between these contexts.

A book is a book, right?

Depends on who you ask.

If you ask a publisher, a book has a title, a writer, a cost, a price, and a category. If you ask a seller, a book has a title, a writer, a cost, a price, and a category. They talk about the same things, right?

For a publisher a book has a working title, and a published title. For a seller a book has a title. For a publisher a book has a writer, who needs to be payed. For a seller a book has a writer, which is just a name on the front cover of the book. For a publisher the cost of a book includes the cost of the writer, the editor, the designer, the printing, the binding. For a seller the cost of a book includes the buying price, maybe some discounts from the publisher on the quantity purchased, the paychecks of the store clerks, bills for running the store, taxes… For a publisher the price includes the producing cost plus the profit they want to make. For a seller the price includes the buying cost plus the profit they want to make, and maybe some discounts they want to give to buyers. For a publisher the category can be fiction and non-fiction books. For a seller the category can be epic fantasy, sci-fi, horror, thriller, programming, design, recipe books…

See where am I going with this?

Depending on the point of view, depending on the context, the same book can mean two different things for two different business sections in the business of selling books. Even if at first we might think there is no difference, once we start talking to the business people, these differences will pop-up.

We should also respect the boundaries between these two contexts, so that we always know about what cost or what price we are talking about. Otherwise, the seller would quickly run out of business if they’d sell books at the publisher’s price.

This is just a model

Of course, there is more to bounded contexts, models, DDD, etc., than what I wrote here. More to read, more to learn, more to think, more to write.

Happy hackin’!

Creating datetimes from a format with a timezone

published on October 16, 2017.

I wouldn’t be writing this blog post, if I’d read all the “fineprints” in the PHP manual. Alas, here we are.

The DateTime and DateTimeImmutable classes have a createFromFormat method. As you can probably guess from it’s name, it creates a datetime object from a datetime string formatted in the specified format. Something like this:

<?php

$dtString = '2017-10-16 07:50:00';
$format = 'Y-m-d H:i:s';

$dt = \DateTimeImmutable::createFromFormat($format, $dtString);

print_r($dt);

gives an immutable datetime object:

DateTimeImmutable Object (
    [date] => 2017-10-16 07:50:00.000000
    [timezone_type] => 3
    [timezone] => Europe/Belgrade
)

Nothing wrong with that. The timezone is Europe/Belgrade, as we didn’t provide the third parameter to the createFromFormat method, which is the optional timezone, and in this case PHP defaulted to the server’s timezone. Business as usual.

If we tell it to use a specific timezone, it’ll use that one instead of the server’s timezone:

<?php

$dtString = '2017-10-16 07:50:00';
$format = 'Y-m-d H:i:s';
$timezone = new \DateTimeZone('America/New_York');

$dt = \DateTimeImmutable::createFromFormat($format, $dtString, $timezone);

print_r($dt);

and an expected result of:

DateTimeImmutable Object (
    [date] => 2017-10-16 07:50:00.000000
    [timezone_type] => 3
    [timezone] => America/New_York
)

Again, business as usual, because we told PHP in what timezone the datetime string is, America/New_York.

A format with a timezone offset

When the format has a timezone offset though, that’s… the part I skipped in the manual:

<?php

$dtString = '2017-10-16T07:50:00+00:00';
$format = 'Y-m-d\TH:i:sP';
$timezone = new \DateTimeZone('America/New_York');

$dt = \DateTimeImmutable::createFromFormat($format, $dtString, $timezone);

print_r($dt);

and a result of:

DateTimeImmutable Object (
    [date] => 2017-10-16 07:50:00.000000
    [timezone_type] => 1
    [timezone] => +00:00
)

Errr… Not really what I wanted, but okay. I guess.

The createFromFormat method ignores the provided timezone (or the server’s timezone if there’s none provided), if the datetime string and it’s format have a timezone offset.

It’s noted in the manual, my bad for not reading carefully, but this still caught me by surprise.

Not being aware of this can cause some hard to track down bugs in applications. While the DateTime objects are being created without an error, they are being created with a different timezone_type from what I originally expected and can potentially lead to a loss of information as the timezone identifier can’t be retrieved from the timezone offset.

Happy hackin’!

Complex argument matching in Mockery

published on May 08, 2017.
Heads-up! You're reading an old post and the information in it is quite probably outdated.

This past weekend I did some issue maintenance and bug triage on Mockery. One thing I noticed going through all these issues, is that people were surprised when learning about the \Mockery::on() argument matcher. I know Mockery’s documentation isn’t the best documentation out there, but this still is a documented feature.

First of all, Mockery supports validating arguments we pass when calling methods on a mock object. This helps us expect a method call with one (set of) argument, but not with an other. For example:

<?php
$mock = \Mockery::mock('AClass');

$mock->shouldReceive('doSomething')
    ->with('A string')
    ->once();

$mock->shouldReceive('doSomething')
    ->with(42)
    ->never();

This will tell Mockery that the doSomething method should receive a call with A string as an argument, once, but never with the number 42 as an argument.

Nice and simple.

But things are not always so simple. Sometimes they are more complicated and complex.

When we need to do a more complex argument matching for an expected method call, the \Mockery::on() matcher comes in really handy. It accepts a closure as an argument and that closure in turn receives the argument passed in to the method, when called. If the closure returns true, Mockery will consider that the argument has passed the expectation. If the closure returns false, or a “falsey” value, the expectation will not pass.

I have used the \Mockery::on() matcher in various scenarios — validating an array argument based on multiple keys and values, complex string matching… and every time it was invaluable. Though, now that I think back, the older the codebase, the higher the usage frequency was. Oh, well.

Say, for example, we have the following code. It doesn’t do much; publishes a post by setting the published flag in the database to 1 and sets the published_at to the current date and time:

<?php
namespace Service;
class Post
{
    public function __construct($model)
    {
        $this->model = $model;
    }

    public function publishPost($id)
    {
        $saveData = [
            'post_id' => $id,
            'published' => 1,
            'published_at' => gmdate('Y-m-d H:i:s'),
        ];
        $this->model->save($saveData);
    }
}

In a test we would mock the model and set some expectations on the call of the save() method:

<?php
$postId = 42;

$modelMock = \Mockery::mock('Model');
$modelMock->shouldReceive('save')
    ->once()
    ->with(\Mockery::on(function ($argument) use ($postId) {
        $postIdIsSet = isset($argument['post_id']) && $argument['post_id'] === $postId;
        $publishedFlagIsSet = isset($argument['published']) && $argument['published'] === 1;
        $publishedAtIsSet = isset($argument['published_at']);

        return $postIdIsSet && $publishedFlagIsSet && $publishedAtIsSet;
    }));

$service = new \Service\Post($modelMock);
$service->publishPost($postId);

\Mockery::close();

The important part of the example is inside the closure we pass to the \Mockery::on() matcher. The $argument is actually the $saveData argument the save() method gets when it is called. We check for a couple of things in this argument:

  • the post ID is set, and is same as the post ID we passed in to the publishPost() method,
  • the published flag is set, and is 1, and
  • the published_at key is present.

If any of these requirements is not satisfied, the closure will return false, the method call expectation will not be met, and Mockery will throw a NoMatchingExpectationException.

Happy hackin’!

Open source taught me how to work with legacy code

published on April 28, 2017.
Heads-up! You're reading an old post and the information in it is quite probably outdated.

Contributing to open source projects has many benefits — you learn and you teach, you can make friends or find business partners, you might get a chance to travel. Even have a keynote at a conference, like Gary did.

Contributing to open source projects was the best decision I made in my professional career. Just because I contributed to, and blogged about Zend Framework, I ended up working and consulting for a company for four and a half years. I learned a lot during that time.

What I realized just recently is that open source also taught me how to work with legacy code. It taught me how to find my way around an unknown codebase faster, where to look and what to look for when investigating an issue. Most importantly, it taught me how to react to legacy code.

Usually when people hear “legacy code”, they think code that was written by a bunch of code monkeys who know nothing about writing good software. The past was stupid, the present is smart and wise, and will make everything better for the future. A long time ago, I was the same.

Today, my thinking and my approach is completely different.

I have the utmost respect for the programmer and their code that is before me. Rarely do I have the privilege knowing the circumstances under which a piece of legacy code was written.

In many cases the original author of the code is not on the team any more, or they just don’t remember why was some decision made and a piece of code written in a certain way. It might be a hack workaround for a code that was written by someone even before their time on the project. Maybe they didn’t know better at the time, or maybe they indeed made an error and now it’s my bug to fix.

Whatever the reason is, the code is written, used, and it delivers business value. It requires maintenance, fixes, and improvements and I welcome the challenges it brings.

Happy hackin’!

Recording screencasts of OSS contributions

published on April 19, 2017.
Heads-up! You're reading an old post and the information in it is quite probably outdated.

I enjoy contributing to open source projects, and I learn a lot while doing it. When someone asks me for advice on how to improve as a programmer, I usually tell them to find an open source project that interests them, and start contributing.

Easier said than done.

I’ve been contributing since… early 2009 I think, when I joined the Zend Framework mailing list.

To try and bring closer contributing to beginners, I decided to start recording screencasts of me doing open source contributions. To give a glimpse of how I do it.

So far I have created 4 of them and uploaded on YouTube. The quality is not perfect, but I think it’s good enough. There’s no video editing, I want to show how I really do it, no fixing of mistakes, no retakes. I use zoom to start a “meeting” and then share and record the screen. It’s actually the best screencasting software for Fedora I’ve found, and it’s not even a screencasting software ¯\(ツ)/¯

While doing these screencasts I also realised that I quite enjoy doing this and the whole process has the added bonus of me actual doing rubber ducking, because, well, I talk all the time as I do things.

Also, potential clients and employers can get a peak at how I work.

Happy hackin’!

Robert Basic

Robert Basic

Software engineer, consultant, open source contributor.

Let's work together!

If you require outsourcing or consulting help on your projects, I'm available!

Robert Basic © 2008 — 2019
Get the feed