•  Comment

Formatting Exception Messages

Over the last couple years, I’ve started putting my Exception messages inside static methods on custom exception classes. This is hardly a new trick, Doctrine’s been doing it for the better part of a decade. Still, many folks are surprised by it, so this article explains the how and why.

How does it work?

Let’s say you’re writing a large CSV import and you stumble across an invalid row, perhaps it’s missing a column. Your code might look like this:

if (!$row->hasColumns($expectedColumns)) {
    throw new Exception("Row is missing one or more columns");
}

This works in terms of stopping the program but it’s not very flexible for the developer. We can improve this is creating a custom exception class.

class InvalidRowException extends \Exception
{
}

Now we throw our custom Exception instead:

if (!$row->hasColumns($expectedColumns)) {
    throw new InvalidRowException("Row is missing one or more columns");
}

This might look like boilerplate but it allows higher level code to recognize which error was raised and handle it accordingly. For example, we might stop the entire program on a NoDatabaseConnectionException but only log an InvalidRowException before continuing.

Still, the error message isn’t very helpful from a debugging perspective. Which row failed? It would be better if we always included the row number in our error message.

if (!$row->hasColumns($expectedColumns)) {
    throw new InvalidRowException(
        "Row #" . $row->getIndex() . " is missing one or more columns"
    );
}

That’s better in the log but now the formatting on this one little message is getting a bit noisy and distracting. There’s no upper bound on this complexity: as the log message gets complex, the code will get uglier. Not to mention, there are multiple reasons we might throw an InvalidRowException but we’d need to format them all to include the row number. Booorrrriiing.

Moving the Formatting

We can remove the noise by pushing the formatting into the custom Exception class. The best way to do this is with a static factory:

class InvalidRowException extends \Exception
{
    public static function incorrectColumns(Row $row) {
        return new static("Row #" . $row->getIndex() . " is missing one or more columns");
    }
}

And now we can clean up the importing code without losing readability:

if (!$row->hasColumns($expectedColumns)) {
    throw InvalidRowException::incorrectColumns($row);
}

The only extra code is the function block surrounding our message. That function block isn’t just noise though: it allows us to typehint and document what needs to be passed to generate a nicely formatted message. And if those requirements ever change, we can use static analysis tools to refactor those specific use cases.

This also frees us from the mental constraints of the space available. We’re not bound to writing code that fits into a single if clause, we have a whole method to do whatever makes sense.

Maybe common errors warrant more complex output, like including both the expected and the received list of columns.

public static function incorrectColumns(Row $row, $expectedColumns)
{
    $expectedList = implode(', ', $expectedColumns);
    $receivedList = implode(', ', $row->getColumns());

    return new static(
        "Row #" . $row->getIndex() . " did not contain the expected columns. " .
        " Expected columns: " . $expectedList .
        " Received columns: " . $receivedList
    );
}

The code here got significantly richer but the consuming code only needed to pass one extra parameter.

if (!$row->hasColumns($expectedColumns)) {
    throw InvalidRowException::incorrectColumns($row, $expectedColumns);
}

That’s easy to consume, especially when throwing it in multiple locations. It’s the type of error messages everyone wants to read but rarely take the time to write. If it’s an important enough part of your Developer Experience, you can even unit test that the exception message contains the missing column names. Bonus points if you array_diff/array_intersect to show the actual unexpected columns.

Again, that might seem like overkill and I wouldn’t recommend gold plating every error scenario to this extent. Still, if this is code you really want to own and you can anticipate the common fix for these errors, spending 1 extra minute to write a solid error message will pay big in debugging dividends.

Multiple Use Cases

So far we’ve created a method for one specific use case, an incorrect number of columns.

Maybe we have other issues with our CSV file, like the existence of blank lines. Let’s add a second method to our exception:

class InvalidRowException extends \Exception
{
    // ... incorrectColumns ...

    public static function blankLine($rowNumber)
    {
        return new static("Row #$rowNumber was a blank line.");
    }
}

Again, a bit of boilerplate but we get extra space to write more detailed messages. If the same issue keeps occurring, perhaps it’s worth adding some extra details, links or issue numbers (or you know, fixing it more permanently).

public static function blankLine($rowNumber)
{
    return new static(
        "Row #$rowNumber was a blank line. This can happen if the user " .
        "exported the source file with incorrect line endings."
    );
}

Locking It Down

When you’re creating “named constructors” for domain objects, you use a similar technique but also declare the original constructor as private. I don’t do this with exceptions though.

First off, we can’t in PHP. Exceptions all extend from a parent Exception class and can’t change their parent’s __construct access level from public to private.

More importantly, there’s little benefit for Exceptions. With domain objects, we do this to capture the ubiquitous language and prevent users from instantiating the object in an invalid state. But with an exception, there’s very little state to keep valid. Furthermore, we’re inherently dealing with exceptional circumstances: we can’t foresee every reason a user might throw an exception.

So, the best you can do is create a base factory that you recommend other folks use when creating their exceptions. This can typehint for useful things commonly included in the message:

class InvalidRowException extends \Exception
{
    // One off error messages can use this method...
    public static function create(Row $row, $reason)
    {
        return new static("Row " . $row->getIndex() . " is invalid because: " . $reason);
    }

    // ...and predefined methods can use it internally.
    public static function blankLine(Row $row)
    {
        return static::create($row, "Is a blank line.");
    }
}

Which might be useful but is probably pretty far out there. I haven’t seen a convenient way to enforce it though.

The Big Picture

There’s one final benefit I’d like to touch on.

Normally, when you write your exception messages inline, the various error cases might be split across different files. This makes it harder to see the reasons you’re raising them, which is a shame since exception types are an important part of your API.

When you co-locate the messages inside the exception, however, you gain an overview of the error cases. If these cases multiply too fast or diverge significantly, it’s a strong smell to split the exception class and create a better API.

// One of these isn’t like the others and should probably be a different Exception class
class InvalidRowException extends \Exception
{
    public static function missingColumns(Row $row, $expectedColumns);
    public static function blankLine(Row $row);
    public static function invalidFileHandle($fh);
}

Sometimes we underestimate the little things that shape our code. We’d like to pretend that we’re not motivated by getting our error messages neatly on one line or that we regularly do a “Find Usages” to see our custom exception messages, but the truth is: these little details matter. Creating good environments at a high level starts with encouraging them at the lowest levels. Pay attention to what your habits encourage you to do.

  •  Comment

How I Use Traits

Recently, a few folks asked about a trait in a new project I wrote. Right around the same time, Rafael Dohms showed me his new talk about complex cognitive processes we don’t notice. Because my brain is a big mushy sack, the two blended together. The result was this post, which tries to capture how I use traits but also how I decide to use them in the first place.

Leverage vs Abstraction

The first thing you should do is go read this blog post: “Abstraction or Leverage” from Michael Nygard. It’s an excellent article.

If you’re short on time, the relevant part is that chunks of code (functions, classes, methods, etc) can be split out for either abstraction or leverage. The difference is:

  • Abstraction gathers similar code behind a higher level concept that’s more concise for other code to work with.
  • Leverage gathers similar code together so you only have one place to change it.

A common abstraction would be a Repository: you don’t know how an object is being stored or where but you don’t care. The details are behind the concept of a Repository.

Common leverage would be something like your framework’s Controller base class. It doesn’t hide much, it just adds some nifty shortcuts that are easier to work with.

As the original blogpost points out, both abstraction and leverage are good. Abstraction is slightly better because it always gives you leverage but leverage doesn’t give you abstraction. However, I would add that a good abstraction is more expensive to produce and isn’t possible at every level. So, it’s a trade off.

What’s this have to do with traits?

Some language features are better than others at producing either Leverage or Abstraction. Interfaces, for example, are great at helping us build and enforce abstractions.

Inheritance, on the other hand, is great at providing leverage. It lets us override select parts of the parent code without having to copy it or extract every method to a reusable (but not necessarily abstracted) class. So, to answer the original question, when do I use traits?

I use traits when I want leverage, not abstraction.

Sometimes.

Sometimes?

Benjamin Eberlei makes a good argument that traits have basically the same problems as static access. You can’t exchange or override them and they’re lousy for testing.

Still, static methods are useful. If you’ve got a single function with no state and you wouldn’t want to exchange it for another implementation, there’s nothing wrong with a static method. Think about named constructors (you rarely want to mock your domain models) or array/math operations (well defined input/output, stateless, deterministic). It makes you wonder if static state, rather than methods, are the real evil.

Traits have roughly the same constraints, plus they can only be used when mixed into a class. They’re more macro than object.

This does gives traits an extra feature though: they can read and write the internal state of the class they’re mixed into. This makes them more suitable for some behavior than a static method would be.

An example I often use is generating domain events on an entity:

trait GeneratesDomainEvents
{
    private $events = [];

    protected function raise(DomainEvent $event)
    {
        $this->events[] = $event;
    }

    public function releaseEvents()
    {
        $pendingEvents = $this->events;
        $this->events = [];
        return $pendingEvents;
    }
}

While we can refactor this to an abstraction, it’s still a nice example of how a trait can work with local object state in a way static methods can’t. We don’t want to expose the events array blindly or place it outside the object. We might not want to force another abstraction inside our model but we certainly don’t want to copy and paste this boiler plate everywhere. Plain as they are, traits help us sidestep these issues.

Other practical examples might be custom logging functions that dump several properties at once or common iteration/searching logic. Admittedly, we could solve these with a parent class but we’ll talk about that in a moment.

So traits are a solid fit here but that doesn’t make static methods useless. In fact, I prefer static methods for behavior that doesn’t need the object’s internal state since it’s always safer to not provide it. Static methods are also more sharply defined and don’t require a mock class to be tested.

Assertions are a good example of where I prefer static methods, despite seeing them commonly placed in traits. Still, I find Assertion::positiveNumber($int) gives me the aforementioned benefits and it’s easier to understand what it is (or isn’t) doing to the calling class.

If you do have an assertion you’re tempted to turn into a trait, I’d treat it as a code smell. Perhaps it needs several parameters you’re tired of giving it. Perhaps validating $this->foo relies on the value of $this->bar. In either of these cases, refactoring to a value object can be a better alternative. Remember, it’s best if leverage eventually gives way to abstraction.

So, to restate: I use traits when I want leverage that needs access to an object’s internal state.

Parent Classes

Everything we’ve seen is also possible through inheritance. An EventGeneratingEntity would arguably be even better since the events array would be truly private. However, traits offer the possibility of multiple inheritance instead of a single base class. Aside from their feature set, is there a good heuristic for choosing?

All things being equal, I like to fallback on something akin to the “Is-A vs Has-A” rule. It’s not an exact fit because traits are not composition but it’s a reasonable guideline.

In other words, use parent classes for functionality that’s intrinsic to what the object is. A parent class is good at communicating this to other developers: “Employee is a Person”. Just because we’re going for leverage doesn’t mean the code shouldn’t be communicative.

For other non-core functionality on an object (fancy logging, event generation, boiler-plate code, etc), then a trait is an appropriate tool. It doesn’t define the nature of the class, it’s a supporting feature or better yet, an implementation detail. Whatever you get from a trait is just in service of the main object’s goal: traits can’t even pass a type check, that’s how unimportant they are.

So, in the case of the event generation, I prefer the trait to a base EventGeneratingEntity because Event Generation is a supporting feature.

Interfaces

I rarely (if ever) extend a class or create a trait without also creating an interface.

If you follow this rule closely, you’ll find that traits can complement the Interface Segregation Principle well. It’s easy to define an interface for a secondary concern and then ship a trait with a simple default implementation.

This allows the concrete class to implement its own version of the interface or stick with the trait’s default version for unimportant cases. When your choices are boilerplate or forcing a poor abstraction, traits can be a powerful ally.

Still, if you’ve only got one class implementing the interface in your code and you don’t expect anyone else to use that implementation, don’t bother with a trait. You’re probably not making your code any more maintainable or readable.

When I do not use traits

To be quite honest, I don’t use traits very often, perhaps once every few months. The heuristic I’ve outlined (leverage requiring access to internal state) is extremely niche. If you’re running into it very often, you probably need to step back and reexamine your style of programming. There’s a good chance you’ve got tons of objects waiting to be extracted.

There’s a few places I don’t like to use traits due to style preferences:

  • If the code you’re sharing is just a couple of getters and setters, I wouldn’t bother. IDEs can be your leverage here and adding a trait will only add mental overhead.
  • Don’t use traits for dependency injection. That’s less to do with traits themselves and more to do with setter injection, which I’m rather opposed to.
  • I don’t like traits for mixing in large public APIs or big pieces of functionality. Skip the leverage step and moving directly to finding an abstraction.

Finally, remember that while traits do not offer abstraction and they are not composition, they can still have a place in your toolbox. They’re useful for providing leverage over small default implementations or duplicate code. Always be ready to refactor them to a better abstraction once the code smells pile up.

  •  Comment

Notes From 3 Conferences

I started this month by speaking or hosting at 4 events in 2 countries over 5 days (DrupalCon Amsterdam, DomCode, ZgPHP, WebCamp). While hectic, it was a great way to see a cross section of the community back-to-back. So, I’d like to talk about the events in turn but also some meta-topics about conferences themselves.

DrupalCon

This was one of the biggest conferences I’ve been to, and definitely the slickest, most well produced. Huge stages, a giant conference center, a “pre-note” with zebra pattern suits and super heroes. The conference had a good sense of humor about itself but the ambition was evident. Drupal is Big(tm) and they know it.

From a tech and community perspective, it’s an interesting position. On the one hand, Drupal began life as a open-source project but now has a massive commercial side (check out the sponsors hall). The keynote discussed Drupal as becoming a Public Good, citing Paul Samuelson’s work and outlining a 3 step lifecycle in this process: Volunteers → Business → Government. The fact the keynote began with a sponsored doppelganger act was a tacit admission of where Drupal currently stands in this process.

This isn’t necessarily bad. I have little knowledge of Drupal but my impression is the commercial interest helps drive an increasing “professionalization” of the developers and tooling. Rolling out best practices and applying general engineering principles to Drupal is a great step forward. Make no mistake, they are tackling genuinely hard problems.

Perhaps for this reason, Drupal is also trying to reconnect to the PHP community at large. This is also a hugely positive (and arguably necessary) move to bring in some of those professional dev practices. At the same time, the feedback I received for my talk on the general PHP track was different enough from other conferences to remind that it is a separate audience, at least for now.

Still, the question on everyone’s mind was “How do we keep hobbyist developers?” I interpreted this as: “Has the re-engineering of Drupal made it so complex that only experienced pro developers can reasonably work with it and was it worth the additional complexity?” To that: I don’t know. I don’t know the code. A well engineered codebase should be less complex but using it may require you to sideload a lot of knowledge (i.e. indirect complexity). That’s possibly a culture or documentation issue, not a technical one.

Some of the articles in the Drupal magazine I found in my swag bag questioned if this was even an issue. Perhaps the natural evolution of Drupal is a focus on high-end, high-traffic CMS sites. Perhaps not.

Either way, it was a great conference. Drupal is juggernaut and here to stay. I don’t know where the road will take them but they’re trying to head in the right direction, even when it’s uphill. Much respect.

ZgPHP

Two days later, and I was presenting at ZgPHP in Zagreb, Croatia (my first trip to the region). The difference was intense.

ZgPHP is a local user group in Zagreb and this was their second annual conference but their first in English. As such, it’s a much smaller event: Total attendees were around 80, though the number waxed and waned throughout the day.

One of the great things about this conference though is the price: it’s completely free to attend. Like DrupalCon, ZgPHP is also worried about the hobbyists and the lone cowboy coders and the tiny dev shops. So, their response is to lower the barrier to obtaining pro-level knowledge, at least as much as possible and free tickets are a great step to do that in a country where the unemployment rate is a crushing 20%. They can’t reach everyone with this tactic but it’s certainly not for lack of trying.

To be fair, that comes with certain tradeoffs: The venue was donated by the local Chamber of Commerce. There was no catering staff and lunch was local pastries with 2 liter bottles of Coke. My badge was an oversized sticker with my name and twitter handle written on it in marker. (When I returned to the hotel, I peeled the sticker off carefully and cut up toilet paper with shaving scissors then stuck to the back so I could bring it home for my badge collection).

So, yes, it’s a small conference but by design. It was well run, well organized and a really nice community.

Croatia isn’t a huge country (4.23 million people, slightly less than Kentucky). Nonetheless, there’s multiple user groups and even another annual conference. That’s some great hustle. By and large, the conversations I had were the same as anywhere else: HHVM and REST APIs, unit testing and decoupling. I was the only speaker not from the region, which made me nervous but folks laughed at my jokes and left nice joind.in reviews. It was a good crowd and I had fun.

WebCamp

Two days later and I was at another conference in Zagreb: WebCamp. Rather than focus on any specific language or tool, WebCamp is about, well, the web.

It’s also massive. And free. Like ZgPHP, WebCamp is totally free to attend. All you had to do is register for one of the 1100+ free tickets on their website, which lasted less than a day. Of course, as with any free ticket, there were a lot of no-shows but around 800 people attended on the first day. True, that’s smaller than DrupalCon but 800 people is significantly larger than almost any PHP conference out there.

Still, a conference of this scale has bills, so attendees could buy a supporter pack (~40 euros?), which came with a t-shirt and some other goodies. Lots of sponsors chipped in and they received perks like evening stands and an hour-long recruitment session on the first day.

WebCamp was a joint effort by several local user groups: PHP, Ruby, Python, JS, you name it. In fact, WebCamp and ZgPHP were part of a whole initiative called “Week of WebCamp” where there were several smaller conferences and workshops throughout the city of Zagreb.

It’s an ambitious undertaking which culminated in WebCamp itself. I’m don’t know if any of the individual groups could’ve pulled this together individually but together, they made it work really well. I saw talks on everything from Elixir to Gearman to data aggregation.

For my part, I was asked to do the opening keynote, which was an enormous honor but the size made it intimidating. Still, the crowd laughed and had fun and even I was reasonably pleased with the result. They also asked me to host one of the tracks which meant a crash course in pronouncing Crotian names (final score: D+).

I’m a huge fan of multi-technology events and also the free-to-attend model but they’re hard to get right. Watching someone pull off a 2-day, dual-track, 800 person conference in those formats plus the additional events throughout the week was amazing. Yes, nothing is perfect but it was absolutely a success.

I’m not an “Everything is awesome”, “Community Works” cheerleader sort of fellow. Still, WebCamp in action was inspiring and leaves me wondering if it’s a taste of things to come: a free-to-attend, multi-community event supported by donations and sponsors.

Conclusion

I had a great time at all of the events and would highly recommend any of them (I skipped over DomCode as I’m one of the founders but would highly recommend it as well)!

Still, I left with a lot of questions. Everywhere I went, people mentioned hobbyist or junior developers. How do we reach them? How do we attract them? What do we teach them? This is especially true in the PHP community where there’s a huge variation in knowledge level.

It also left me wondering about the role of those teaching. Are free-to-attend events more open? Doesn’t that leave us more dependent on our sponsors? Should our conferences be more cost-effective affairs or can we teach more effectively when we go all out? Is commercial backing driving knowledge or impeding it? How can we encourage the right attitude in our partners? Who are we really targeting with technical conferences? Is turning teaching into a commercial interest an acceptable path for an open source community? What are the role of speakers in this?

Each of these events brings a different model to the table. Is there a right one? Well, the fact that all of them are successful in different ways says probably not. I loved the variety of speakers plus the pomp and circumstance of DrupalCon but you probably couldn’t pull that off on a ZgPHP budget. At the same time, I felt like I could take more specific questions and help people more deeply at ZgPHP precisely because it so direct. There are things you can do with one model that you can’t necessarily do with another. I suppose we need different events pushing different models to catch the widest possible subset of the community, though I wish we could do better.

One amazing thing was that all of these conferences were recording their talks to publish them on the web for free. My DrupalCon talk was online less than 2 hours after I gave it, which is bonkers. Perhaps the web-based model is the real future here, though as long as there’s a hallway track and a social to network at, there will be value in attending conferences. Which just leaves one question an event to consider: who are we trying to bring in and how do we get them there?

Many thanks to Igor Wiedler for proofreading an earlier version of this article

  •  Comment

Tips on Speaking

Earlier this evening, I was a guest on NoCapes, a new web series about sharing advice and encouraging folks to engage in the PHP community. It’s a great initiative, you should check it out. There’s also a video of my interview up as well.

But as we begin The Autumn of a Thousand Conferences, I thought I’d follow up by taking a moment and write up some tips on speaking. Bear in mind, I only began a couple years ago so this is just what works for me. I try to focus on the more practical and less glamorous bits of the speaking experience so you know what to expect.

Ultimately, the #1 rule is this: speakers are the same as any other type of performer. It isn’t about talent, it isn’t about luck, it’s about work and practice. So, don’t beat yourself up if you’re not amazing at first and don’t expect to be well respected until you pay your dues.

I would also ask yourself what is more important. Personally, I’d rather be known for being a good engineer than a great speaker. That said, speaking has helped me make some amazing friends and grown my career considerably. You can (and probably should) try it as well.

Getting Accepted

  • It’s cliché but start off small: user groups, local meetups, etc. When submitting to a bigger conference, mention your experience. Include links to joind.in, reviews, etc.
  • Just like any type of writing, you’re going to get rejected. A lot. Even when you’ve got some talks under your belt, you’re still going to get rejected on a regular basis.
  • If you have no recorded experience, a 2 minute demo of you covering a small topic can make a huge difference. Many conferences are trying to add new speakers but they’re also risk adverse, so show that you know y