Jekyll2021-09-06T21:38:28+02:00https://rosstuck.com/feed.xmlRoss TuckWeb developer, speaker, author, expat, book nerd, friend to cats.Ross TuckDialects in Code: Part 22020-09-17T15:00:00+02:002020-09-17T15:00:00+02:00https://rosstuck.com/dialects-in-code-part-2<p>We previously looked at dialects, collections of programming practices that change how you can use the same programming language to express your program differently. In this article, we’ll look at how the different practices within a dialect can interact with each other.</p>
<h2 id="everything-flows">Everything Flows</h2>
<p>Short of a major innovation in tooling or methodology, dialects rarely change all at once. Instead, changes manifest as a shift in which practices we use. We introduce a new practice (make more objects immutable) or we stop using one (functions may only have a single return point) or we refine something we’re already doing (let’s migrate our property docblocks to property typehints).</p>
<p>These types of changes are inevitable and they help keep a codebase healthy. Even if you don’t deliberately change your practices, you’ll see changes over time by staying up to date with your dependencies or through the natural churn of contributors to the codebase.</p>
<p>Sometimes, though, a change proves more difficult than expected. You introduce something that looks great but maybe it requires more boilerplate code or you can’t get it working with your serialization library or any of those wonderful things that can make programming feel like death by papercuts.</p>
<p>In these cases, it might feel like the practice is deficient or not suited for your use case. And that might be true. But it might also be the practice works best in combination with other practices.</p>
<h2 id="supporting-practices">Supporting Practices</h2>
<p>Let’s look at adding unit tests to a legacy application. It’s common to see code like this:</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">SomeService</span>
<span class="p">{</span>
<span class="k">public</span> <span class="k">function</span> <span class="n">isPumpkinSpiceLatteSeason</span><span class="p">():</span> <span class="kt">bool</span>
<span class="p">{</span>
<span class="nv">$now</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">DateTime</span><span class="p">();</span> <span class="c1">// automatically set to system time</span>
<span class="nv">$startOfSeason</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">DateTime</span><span class="p">(</span><span class="s1">'August 25, 2020'</span><span class="p">);</span>
<span class="nv">$endOfSeason</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">DateTime</span><span class="p">(</span><span class="s1">'December 1, 2020'</span><span class="p">);</span>
<span class="k">return</span> <span class="nv">$now</span> <span class="o">>=</span> <span class="nv">$startOfSeason</span> <span class="o">&&</span> <span class="nv">$now</span> <span class="o"><</span> <span class="nv">$endOfSeason</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>This method looks very testable: it has a clear scope and a finite number of outcomes. The method would also benefit from tests: boundary checks are so easy to make a mistake on.</p>
<p>Unfortunately, writing tests won’t be easy because the value of <code class="language-plaintext highlighter-rouge">$now</code> is derived from the current system time. This is a classic case for Dependency Injection: if we pass a Clock into the constructor of <code class="language-plaintext highlighter-rouge">SomeService</code>, we can mock it in the tests but use a real one in the running application.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">SomeService</span>
<span class="p">{</span>
<span class="k">private</span> <span class="kt">Clock</span> <span class="nv">$clock</span><span class="p">;</span>
<span class="k">public</span> <span class="k">function</span> <span class="n">__construct</span><span class="p">(</span><span class="kt">Clock</span> <span class="nv">$clock</span><span class="p">)</span>
<span class="p">{</span>
<span class="nv">$this</span><span class="o">-></span><span class="n">clock</span> <span class="o">=</span> <span class="nv">$clock</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">function</span> <span class="n">isPumpkinSpiceLatteSeason</span><span class="p">():</span> <span class="kt">bool</span>
<span class="p">{</span>
<span class="nv">$now</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-></span><span class="n">clock</span><span class="o">-></span><span class="nf">now</span><span class="p">();</span>
<span class="nv">$startOfSeason</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">DateTime</span><span class="p">(</span><span class="s1">'August 25, 2020'</span><span class="p">);</span>
<span class="nv">$endOfSeason</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">DateTime</span><span class="p">(</span><span class="s1">'December 1, 2020'</span><span class="p">);</span>
<span class="k">return</span> <span class="nv">$now</span> <span class="o">>=</span> <span class="nv">$startOfSeason</span> <span class="o">&&</span> <span class="nv">$now</span> <span class="o"><</span> <span class="nv">$endOfSeason</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>It’s a few more lines of code but well worth it. <code class="language-plaintext highlighter-rouge">SomeService</code> has gone from “this is going to be really complicated to test” to “this can be covered with common testing practices.”</p>
<p>Now, it would’ve been painful but we could’ve theoretically tested this without using dependency injection (probably by messing with the system clock, yikes!). Conversely, Dependency Injection can still benefit us when we’re not writing tests (e.g., using it to implement a strategy pattern). Since these two practices can exist separately, we can see they’re two separate practices and not two aspects of one practice, but there is a clear relationship between the two: Code with Dependency Injection is easier to test.</p>
<p>When one practice enables another to be easier or more feasible, I call it a <strong>Supporting Practice</strong>.</p>
<p>Any practice can be a supporting practice for another practice. Further, any practice can have lots of supporting practices. Unit Testing, for example, benefits from Dependency Injection but also not using global state, reducing mutability, etc. Not all of these are required, but they all contribute to making unit testing easier.</p>
<p>In turn, Unit Testing can be a supporting practice itself, improving your experiences with Continuous Integration, Continuous Deployment, and Just Keeping Stuff Actually Working.</p>
<h2 id="why-do-supporting-practices-matter">Why Do Supporting Practices Matter?</h2>
<p>Plenty of ink (and blood) has been spilled on the benefits of Dependency Injection and Unit Testing, why try to name this relationship?</p>
<p>First, just acknowledging the existence of supporting practices can reframe how we approach new practices. When a change to our dialect isn’t working, this gives us an extra dimension to step back and debug. Maybe we ARE doing it right, but there’s something we’re missing? Is there something different between our environment and the person we learned it from? Working through these questions can be enlightening.</p>
<p>Second, when we try to teach new practices, it helps us remember we need to include which supporting practices we’re counting on. This can be difficult considering how many practices we work with and that the connection isn’t always clear. Modern software engineering is often just chains and chains of supporting practices.</p>
<p>Domain events, for example, are immutable events that your entities generate. Sounds straightforward, until you try to implement this and realize it’s almost impossible without dropping auto-increment ids and switching over to app-generated IDs, e.g. UUIDs.</p>
<p>Domain events and UUIDs might not seem connected at first. If you were already using UUIDs, you might have never even considered the issue, but recognizing your supporting practices early on will make it much easier for folks to add them to their dialect.</p>
<h2 id="the-flip-side">The Flip Side</h2>
<p>If we’re going to highlight practices that help other practices, is it possible that some practices hurt other practices?</p>
<p>Short answer: yes, though hurt is relative. Based on our previous example, we could say that auto-increment ids are a practice that might require more work to integrate with your domain events. It’s not that auto-increment ids are inherently evil, it just happens to negatively impact another practice you’re currently using.</p>
<p>For this reason, I prefer to call them <strong>Complicating Practices</strong>, because they’re not “bad”, they just raise complications for other practices.</p>
<p>Depending on your dialect, the complications may not even be an issue. The procedural dialect I write my one-off shell scripts is very concrete and easy to scan but that makes dependency injection difficult. However, I don’t do much abstraction or unit testing in my shell scripts, so it’s a tradeoff I’m okay with. However, the enterprise-y dialect I write larger applications in cares very much about testing and Dependency Injection so it’s not a good tradeoff there.</p>
<p>Still, aren’t there inherently evil practices? Well, some practices complicate so many other practices that they’re rarely worth using. In our unit testing example, we could use a Singleton for a database complication. This is a Complicating Practice for unit tests but also complicates transactions, multiple databases, locking, and, well, lots of other things.</p>
<p>It’s not impossible to find a place where Singletons make sense. Maybe they’re a decent transitional step in an ancient legacy app. It’s just unlikely they have good ROI in the trade-off economy when you have any other choice.</p>
<h2 id="the-ergonomics-of-practices">The Ergonomics of Practices</h2>
<p>When we start considering the push and pull dynamic of Supporting and Complex Practices, we begin to see a dialect isn’t random habits cobbled together. It’s a constantly evolving balance of trade-offs as new practices are introduced, merge with others, get borrowed and mutated in other dialects, and even return to their source as something different.</p>
<p>Programmers will optimize for a set of practices that can co-exist with minimal complications. For a new practice to be successfully adopted, it doesn’t just need to stand well on its own, it needs to do at least one of the following:</p>
<ul>
<li>Mesh well with existing practices</li>
<li>Offer replacements for the practices it complicates</li>
<li>Contain such an overwhelming advantage that it’s worth complicating other practices</li>
<li>Be shoved down the dialect’s throat through political or social clout</li>
</ul>
<p>After enough iterations, dialects can begin to form semi-stable bundles of practices. Practices can entangle with each other and mutation may slow down. Some practices will be added or removed purely to support other practices or avoid complications.</p>
<h2 id="old-school">Old School</h2>
<p>Occasionally, you’ll have vestigial practices remain that no longer influence anything. As an example, it was once common to enforce that every function only had a single return statement. Apocryphally, this was to help clarify flow control in an era of gotos or helped ensure you deallocated your memory giving you only one spot to do it.</p>
<p>As supporting practices, the “Single Return Law” might’ve been useful when more programs were written in FORTRAN or C but that isn’t the case anymore. Thus, dialects have shifted away from this practice, to avoid complicating the use of Guard Clauses where there’s a number of early if/return statements at the beginning of functions.</p>
<p>Leftover practices like these can haunt us for a long, long time. Looking at what these practices support or complicate can help us recognize them earlier.</p>
<h2 id="true-neutral">True Neutral</h2>
<p>Finally, remember that sometimes a practice is just a practice and doesn’t support or complicate anything. Many stylistic practices are like this. Do you like a space after your negation operator like this?</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="p">(</span><span class="o">!</span> <span class="nv">$pumpkinSpiceLatteSeason</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">//...</span>
<span class="p">}</span>
</code></pre></div></div>
<p>If so, cool. If not, also cool. It may function as an identification signal in your dialect but I don’t think it impacts anything else.</p>
<h2 id="summary">Summary</h2>
<p>In this article, we covered the ideas of Supporting and Complicating practices. By trying to recognize them and taking care to communicate them along with a change in practices, we can help improve the likelihood of our change being adopted in a dialect.</p>
<p>We also discussed how the push and pull between practices helps shape dialects over time, and how it can leave some leftover practices that don’t offer much.</p>
<p>In the next installment of this series, we’ll start looking at how dialects impact the expressiveness of our code.</p>Ross TuckWe previously looked at dialects, collections of programming practices that change how you can use the same programming language to express your program differently. In this article, we’ll look at how the different practices within a dialect can interact with each other.Dialects in Code: Part 12020-08-26T15:00:00+02:002020-08-26T15:00:00+02:00https://rosstuck.com/dialects-in-code-part-1<p>For a long time, I’ve been interested in how different folks can use the same programming language in radically different ways. I’ve privately used the term “dialects” to describe these different approaches. In this series, I want to talk about recognizing dialects in code and how we can make them work for us.</p>
<p>Before we get into concrete benefits though, let’s focus on dialects, where they come from and how they find their way into our code.</p>
<h2 id="the-big-bad-theory">The Big Bad Theory</h2>
<p>Telepathy doesn’t exist.</p>
<p>To communicate our thoughts, we need to encode them into language. The process of encoding thoughts into a language produces an artifact, like written text, spoken words, sign language, subtle facial expressions or even a combination of these.</p>
<p>This artifact is always an imperfect copy of the author’s original thoughts. You can say “X is like Y” or “I am sad today” but this is always a simplification that doesn’t have the exact connotations, knowledge or context that remain in your brain. Those thoughts remain hidden to us. Sharing the full state of your brain would take too long, be too complex and might not be possible since the other person still has their own thoughts. Like saving a JPEG, encoding a thought into a language is always a lossy process. The artifact that comes out of the encoding process is different than the thought that went into it.</p>
<p>The advantage of artifacts is they <em>can</em> be shared. By simplifying our thoughts, we reduce the information we’re transmitting to a managable amount. Sometimes the thought even becomes clearer because we’ve simplified it. Artifacts can also be communicated or stored for further use. That’s a huge advantage.</p>
<p>On the other side, the person consuming the artifact will understand it differently depending on their own thoughts, experiences and knowledge. I could say something like “Monads are monoids in the category of endofunctors.” This might be a concise, correct statement but how you perceive it depends on your knowledge of functional programming knowledge, or recognizing it as a meme/joke, or just how you feel about me in general.</p>
<p>Language has rules but they’re very fuzzy rules on both the creating and receiving side.</p>
<h2 id="now-in-code">Now in Code</h2>
<p>The same is true for programming. When we begin writing code, we have an idea we want to express, like a rough sketch of an API, or a fix for a bug, or a full fledged model. If we want to automate the execution of that idea, we need to express it in a programming language.</p>
<p>Programming languages tend to offer less expressiveness than natural languages. That means it takes extra effort to encode information in them and it takes a lot of contextual knowledge to understand the authorial intent. On the flip side, programming languages are significantly less ambiguous than natural languages. If expressing an idea in English is like saving a photo as a JPEG, expressing an idea in code is like saving a photo as a GIF with max 256 colors: you lose detail but gain conciseness.</p>
<p>That tradeoff allows a computer to execute our idea with incredible speed and accuracy, which is a heck of a thing.</p>
<h2 id="information-through-convention">Information Through Convention</h2>
<p>The loss of information about business requirements or programmer intent still presents a major challenge for maintenance and future development. We can work around this by supplementing the code with discussion and documentation, and teams frequently do. However, the code itself remains one of our most vital and useful artifacts. Even very human centric methodologies like Domain-Driven Design acknowledge code as the primary artifact your team uses.</p>
<p>So to help preserve our mental well-being, programmers created practices, tricks, and conventions to help impart more meaning into code.</p>
<p>For example, long-term PHP’ers may remember that classes didn’t always have visibility modifiers for properties or methods. This was frustrating when writing a class because things could change or be called in unexpected ways and it was frustrating when using a class because it wasn’t always clear which things you should or shouldn’t touch.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// If a user changes the name property directly here, the changed name may get saved</span>
<span class="c1">// in the database but it will fail to change the lastUpdated time. Oops!</span>
<span class="kd">class</span> <span class="nc">User</span>
<span class="p">{</span>
<span class="k">var</span> <span class="nv">$name</span><span class="p">;</span>
<span class="k">function</span> <span class="n">name</span><span class="p">(</span><span class="nv">$name</span><span class="p">)</span>
<span class="p">{</span>
<span class="nv">$this</span><span class="o">-></span><span class="n">name</span> <span class="o">=</span> <span class="nv">$name</span><span class="p">;</span>
<span class="nv">$this</span><span class="o">-></span><span class="n">lastUpdated</span> <span class="o">=</span> <span class="nb">time</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div></div>
<p>To work around this, PHP borrowed an existing convention that private or protected class features should be prefixed with an underscore. By adding and understanding this convention, we can convey extra information that prevents bugs:</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Here the _ tells the user “don’t change this property directly” so </span>
<span class="c1">// hopefully they’ll scroll farther down and find the name() method</span>
<span class="kd">class</span> <span class="nc">User</span>
<span class="p">{</span>
<span class="k">var</span> <span class="nv">$_name</span><span class="p">;</span>
<span class="k">function</span> <span class="n">name</span><span class="p">(</span><span class="nv">$name</span><span class="p">)</span>
<span class="p">{</span>
<span class="nv">$this</span><span class="o">-></span><span class="n">_name</span> <span class="o">=</span> <span class="nv">$name</span><span class="p">;</span>
<span class="nv">$this</span><span class="o">-></span><span class="n">lastUpdated</span> <span class="o">=</span> <span class="nb">time</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div></div>
<p>It may seem crude today but for developers at the time, this convention added a lot of safety and intent to the code. You could rely more readily on autocomplete without having to read the entire class and that was a big productivity gain.</p>
<p>Still, it wasn’t perfect: you couldn’t differentiate between protected and private. Some folks tried a double underscore, others did it the other way around and most didn’t differentiate between the two at all. Eventually, this was formalized into the PHP language itself as public/protected/private visibility modifiers which is now the most widely used way of expressing this.</p>
<p>Most practices will never end up as part of the core language itself. They’ll remain userland conventions like a variable naming scheme, a specific directory structure, a preference for one design pattern over another, etc. And that’s good, userland conventions are typically cheaper to produce and iterate on. Even features that make their way into the language itself (our visibility modifiers) may change or even be removed. Languages are always in motion, evolving towards the future.</p>
<h2 id="enter-the-dialect">Enter the Dialect</h2>
<p>Over time, these practices group, combine, split and merge into semi-stable clusters which are used and recognized by a group of people. Keeping with our “Programming languages as a language” metaphor, I refer to these groups as “dialects” of the programming language.</p>
<p>In human language, a dialect is a version of a language (say, English) with its own grammar, vocabulary, idioms and other other features. For example, I’m originally from the Southern part of the US where we say “y’all” and “over yonder”, which is unique to our region.</p>
<p>Dialects within the same base language are usually still intelligible to each other. I can communicate with folks from the US Midwest who have their own dialect. I may have more trouble with someone from the UK who speaks Cockney but given time, we can probably work it out.</p>
<p>All of this is true for programming communities as well. Different communities will have unique practices, unique ways of combining them and occasionally different difficulty levels in understanding each other, even if they’re using the same programming language.</p>
<p>Because of its wide variety of uses, PHP has a host of dialects and like human languages, most are associated with and propagated by a community of some kind. The boundaries between dialects can be blurry, as they’re essentially artificial, but it can be useful to talk about. We can identify them by a particular framework (Laravel vs Symfony dialects), a product (Drupal vs Wordpress dialects). It can be generational (PHP devs from before 2010), geographic (PHP’ers from The London School of TDD), or even comparative (“Java-style” PHP). A dialect can be as small as one person (a personal style) or as large as several million.</p>
<p>It’s important to realize that just as with natural languages, there is no “true” dialect of a programming language. Even a standardized dialect is still just a dialect. Therefore, when we talk about encoding our thoughts into an artifact, we’re doing this by applying not just a language but a specific dialect of that language and that will impact the resulting artifact, i.e. code.</p>
<h2 id="how-do-dialects-impact-my-code">How do dialects impact my code?</h2>
<p>Even something as simple as naming a class is impacted by our choice of dialect. Let’s say you had a class that receives an event and dispatches it to 0 or more listeners. Would you go with:</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">EventDispatcher</span>
<span class="kd">class</span> <span class="nc">DispatchesEvents</span>
</code></pre></div></div>
<p><code class="language-plaintext highlighter-rouge">EventDispatcher</code> is probably the most common choice, as the bulk of dialects I’ve seen name classes after nouns. That said, there are communities in PHP that prefer to name classes after the responsibilities that class has, using a form that focuses on verbs. It’s a very distinctive choice and like my use of “y’all”, it’s often a good clue as to the origin of the code I’m looking at.</p>
<p>As we said before, both dialects are equally valid, there is no right or wrong choice here! However, confusion arises when consumers of the artifact are unaware of the implicit rules of the dialect used or, worse, apply conventions from the wrong dialect.</p>
<p>For example, in some communities, the verb-first form is never used for classes but is used for traits. If I’m looking at a file tree of a library and assume that <code class="language-plaintext highlighter-rouge">DispatchesEvents.php</code> is a trait, that can confuse my understanding of the overall library.</p>
<p>So, should we value mutual intelligibility of dialects above all else and always use the most common convention? There’s certainly value in that but allowing changes like this is a key element in innovation. It’s a balancing act and heavily dependent on the intended audience for our code. Is this only used in a specific team? Will it be a widely consumed library? Is it mainly consumed as a binary without ever looking at the code?</p>
<p>Let’s look at another example. You need to iterate over a list of numbers and perform some operation to each of them. How do you prefer to iterate over them?</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">for</span> <span class="p">(</span><span class="nv">$i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nv">$i</span> <span class="o"><</span> <span class="nb">count</span><span class="p">(</span><span class="nv">$list</span><span class="p">);</span> <span class="nv">$i</span><span class="o">++</span><span class="p">)</span>
<span class="k">foreach</span> <span class="p">(</span><span class="nv">$numbers</span> <span class="k">as</span> <span class="nv">$list</span><span class="p">)</span>
<span class="nf">map</span><span class="p">(</span><span class="nv">$list</span><span class="p">,</span> <span class="cm">/*...*/</span><span class="p">)</span>
</code></pre></div></div>
<p>While we may each have a personal preference, the choice here will depend on the dialect you’re writing in. In a C-ish style, the for loop will be the most idiomatic but has mostly died out in modern PHP. foreach is by far the most common construct used, while map is the most concise but also requires some FP knowledge.</p>
<p>You can also see how some dialects trade general applicability for increased precision of language:</p>
<ul>
<li>for repeats any code any number of times based on an arbitrary condition</li>
<li>foreach repeats any code once for each item in a list</li>
<li>map applies any function once to each element of a list and returns a new list.</li>
</ul>
<p>By using more and more specific jargon in our dialect, we can create shorter, easier-to-read code, at the expense of a higher barrier to entry.</p>
<h2 id="summary">Summary</h2>
<p>When we write code, we filter our thoughts through a dialect, a collection of practices that help shape the code we produce.</p>
<p>We’ve focused on theory but in the next few articles, we’ll look at concrete benefits of using dialects, such as:</p>
<ul>
<li>Understanding when practices work together and when they don’t</li>
<li>Easier communication and onboarding</li>
<li>Using dialects to indicate levels of quality</li>
<li>Improving expressiveness in code</li>
</ul>
<p><em>Many thanks to Shauna Gordon and Frank de Jonge for reviewing this post.</em></p>Ross TuckFor a long time, I’ve been interested in how different folks can use the same programming language in radically different ways. I’ve privately used the term “dialects” to describe these different approaches. In this series, I want to talk about recognizing dialects in code and how we can make them work for us.The Everybody Poops Rule2018-08-26T17:00:00+02:002018-08-26T17:00:00+02:00https://rosstuck.com/the-everybody-poops-rule<p>One of the hardest things to teach growing devs is when not to use their newfound skills. After putting huge effort into learning with a mentor, having that same mentor pick up a feature and say “No, just crap this one out, it’s not important” seems inconsistent and bewildering.</p>
<p>To help explain, I use what I call “The Everybody Poops Rule.” It goes like this:</p>
<blockquote>
<p>Everybody poops. But you don’t poop in every room in the house. You have a special room where you poop, you put a door on it and you only poop there.</p>
</blockquote>
<p>Okay, it’s crass but that makes it memorable. There’s two key points here:</p>
<p>First, in the same way DDD is about admitting there is no single consistent model of the world or that TDD is about admitting failures are unavoidable, the Everybody Poops rule is about admitting some parts of a system will be…well, crap. Not every part of the system could or should be top tier quality. Eventually, everybody poops. It’s a natural process.</p>
<p>But, and this is the second point, that doesn’t mean it’s unmanageable. DDD copes with the lack of a consistent model by embracing and integrating multiple models. TDD puts verification upfront, admitting all code is untrustworthy until proven otherwise.</p>
<p>The Everybody Poops rule responds to the existence of crap by embracing encapsulation. That company blog? It’s not a core system, throw it together. A shell script? Pffft, crap it out. That little framework glue code? Psha, it’ll be removed in the next framework release.</p>
<p>When in doubt, default to quality. But if the code is isolated, unimportant and behind an interface: who cares if it smells? We can still build a reasonable codebase, we can live in a reasonable house, as long as we only poop in specific areas and you keep the door closed.</p>
<p>Let’s talk about some of the implications.</p>
<h2 id="let-it-go">Let It Go</h2>
<p>First and foremost, you can’t stop people from pooping. When dealing with a sufficiently complex system, there will always be waste. Holding it in is unhealthy and impossible.</p>
<p>Most teams follow the Broken Window Theory, fearing even a single tradeoff starts the slide down a slippery slope. This can reduce discussion (read: dissension) in the short term but leads to arbitrary compliance or worse.</p>
<p>Deciding on a level of quality isn’t like deciding on a coding standard, you can’t have an off-the-shelf-always-okay answer. Quality is the place to have nuanced discussions.</p>
<h2 id="not-on-the-walls">Not On The Walls</h2>
<p>Even when you are producing crap, there are still standards of decency. Maybe the team is fine with a God Class, or a really long method, maybe it doesn’t have all the unit tests, that’s okay but it still better have docs and pass your static analyzers.</p>
<p>Finding the right balance can be difficult since you’re already lowering your standards. Focus on the tradeoffs here, including the time and energy spent discussing.</p>
<h2 id="encrapsulation">Encrapsulation</h2>
<p>How does one isolate crap? In practical terms, any way you normally split code. Put it behind an interface. Drop in a service layer. Pull it out to another namespace. Split it into a separate codebase. Delegate to a third party package. Build a bridge interface. Push it behind an API.</p>
<p>Remember, none of this erases the existence of the poop. Putting it behind a door doesn’t somehow make it clean or better. It’s just hopefully somewhere you don’t have to touch it all the time.</p>
<p>This isn’t easy work. Perversely, it often takes more skill to handle poop safely than it would to make to not make crap in the first place. Poop juggling is a senior ability.</p>
<h2 id="waste-management-systems">Waste Management Systems</h2>
<p>Never put poop behind a door unless you have a plan to get rid of it later.</p>
<p>That might seem silly since the poop is, by definition, unimportant. But ask yourself: if you can’t flush it, is it really isolated? Without good waste management, poop has a nasty habit of backing up and flooding you at the worst moment. And poop rarely ages well.</p>
<p>Besides, it might be an unimportant detail now but times change. Make sure you’re in a good position to replace or redirect that code if the business pivots. Today’s manure is tomorrow’s fertilizer.</p>
<h2 id="iterable-bowel-syndrome">Iterable Bowel Syndrome</h2>
<p>Other times, you might want to go in and make a deliberately crappy pass at building an important system. Even worse than a spike or proof-of-concept, these barebone first drafts may stink but they’re a great way of gaining knowledge or scaffolding other systems.</p>
<p>Just make a firm commitment to flush it at the end. If you name it, you (or your manager) is going to get attached to it.</p>
<h2 id="dont-force-it">Don’t Force It</h2>
<p>Just because you can manage poop successfully doesn’t mean you should do it everywhere. No amount of engineering will ever make a kitchen toilet a good idea. Similarly, don’t crap in the domain layer.</p>
<p>Before you make the decision to crap something out, ask yourself:</p>
<ul>
<li>How often do you have to touch it?</li>
<li>Is it it going to hang around for a long time?</li>
<li>Is it a core domain for your company, e.g. do you draw competitive advantage from it?</li>
<li>What are the consequences if the project fails in development? At each quarter of its projected life cycle?</li>
<li>What are the consequences if it exceeds its lifecycle?</li>
<li>Do you know the maximum and minimum amount of complexity possible?</li>
<li>Can you find a solution to keep the complexity “bounded”, i.e. within a certain range?</li>
</ul>
<h2 id="raising-a-stink">Raising a Stink</h2>
<p>If you do make the decision to underengineer something, bring your stakeholders into the decision. They’ll know if it’s worth it and it avoids surprise. Nothing undermines confidence in an engineering team faster than someone else coming along and saying “What is this crap?!” without knowing it’s supposed to be crap.</p>
<p>Make sure you document it. Not only will this help cover your butt, this is the stuff you want to touch the least so it’s the most likely to be forgotten. Finally, this documentation signals to new hires that quality is the standard and YOLO is a rare deviation.</p>
<p>Teach the standard. Document the deviation.</p>
<h2 id="in-the-end">In The End</h2>
<p>Many have commented that the best devs often write code indistinguishable from the newest juniors. On a line by line basis, that might be true. But that’s okay. When the work is done, you’ll realize their focus was somewhere else the whole time.</p>
<p>They weren’t worrying about the plumbing.</p>
<p>They were building the house.</p>
<p><em>Thanks to Cees-Jan Kiewiet, Igor Wiedler, Frank de Jonge, Anthony Ferrera and Matthias Noback for proofreading.</em></p>Ross TuckOne of the hardest things to teach growing devs is when not to use their newfound skills. After putting huge effort into learning with a mentor, having that same mentor pick up a feature and say “No, just crap this one out, it’s not important” seems inconsistent and bewildering.Returning From Command Buses2018-01-22T13:30:00+01:002018-01-22T13:30:00+01:00https://rosstuck.com/returning-from-command-buses<p>The most common question I get about my command bus library is: “can commands really return nothing?” The second most common question is “Why do you let commands return something, don’t you know that’s Wrong(tm)?”</p>
<p>It’s easy to get hung up on form, not function. That’s a shame because command buses aren’t important. In the grand scheme of things, they’re completely, utterly, totally unimportant. It’s all about where the messages are going, not how they get there.</p>
<p>Still, let’s take a look at some myths about command buses.</p>
<h2 id="command-buses-are-a-part-of-cqrs-and-they-always-go-together">“Command Buses are a part of CQRS and they always go together.”</h2>
<p>CQRS is about the separation of a (write) model that solves a problem and a (read) model that informs you about problems. This is a useful lens for viewing some domains.</p>
<p>While I wasn’t there when the term was coined (and haven’t asked), it’s pretty logical to assume the “Command” in “Command Bus” had the same etymology. It was a piece of plumbing used to address the write model, which is the important part of our app.</p>
<p>But that’s a one way relationship. Write model doesn’t care how you send it information. A “old school” service layer like this:</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$this</span><span class="o">-></span><span class="n">serviceLayer</span><span class="o">-></span><span class="nf">openAccount</span><span class="p">(</span><span class="nv">$email</span><span class="p">,</span> <span class="nv">$password</span><span class="p">);</span>
</code></pre></div></div>
<p>is just as CQRS-y as a command bus like this:</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$this</span><span class="o">-></span><span class="n">serviceLayer</span><span class="o">-></span><span class="nf">handle</span><span class="p">(</span><span class="k">new</span> <span class="nc">OpenAccount</span><span class="p">(</span><span class="nv">$email</span><span class="p">,</span> <span class="nv">$password</span><span class="p">));</span>
</code></pre></div></div>
<p>It has the same guarantees, the same ability to encapsulate. It’s just a minor difference in implementation. And no, it doesn’t return anything.</p>
<p>Conversely, if we’re using either version in a non-CQRS app, it doesn’t matter if we return something or not. The non-returning is a property of CQRS, not the Command Bus.</p>
<h2 id="you-can-only-use-a-command-bus-if-youre-doing-cqrs">“You can only use a Command Bus if you’re doing CQRS.”</h2>
<p>Nowadays I would argue the term “Command” in Command Bus has less to do with the CQRS write model and more to do with the classic Gang of Four definition of “Command”, i.e. breaking down operations into discrete units and passing them around. Command Bus has found a broader audience as a modern take on implementing a service layer. And that’s okay.</p>
<p>The advantages for a command bus hold true whether you’re using CQRS or not:</p>
<ul>
<li>It’s easy to decorate the uniform interface</li>
<li>It’s different enough to form a clear barrier between UI and domain model</li>
<li>The command class is a nice way to capture ubiquitous language</li>
<li>The command DTOs can pair well with form libraries and serializers.</li>
</ul>
<p>We use a command bus because it’s a useful implementation idiom, not because it’s a fixed part of CQRS. It’s not key architecture, it’s just a handy little twist.</p>
<h2 id="i-should-be-using-cqrs-and-command-buses-because-thats-good-practice">“I should be using CQRS and Command Buses because that’s good practice”</h2>
<p>No, they’re useful practices for some types of problems. CQRS is rarely a primary goal anyways. Most of the folks I see using it are actually oriented at doing Event Sourcing, which is another orthogonal concept altogether.</p>
<h2 id="i-shouldnt-be-returning-anything-because-cqrs-is-cqs-which-says-dont-return-anything">“I shouldn’t be returning anything because CQRS is CQS which says don’t return anything”</h2>
<p>CQS (like CQRS) can be a useful lens for some problems but not all situations or practices. It is a good guideline for warning you against side-effect prone code. That said, CQS is aimed at method level whereas CQRS is targeting higher-level architecture. I’d argue they’re spiritually similar but CQRS isn’t direct a superset of CQS.</p>
<h2 id="we-dont-return-things-because-commands-are-asynchronous">“We don’t return things because commands are asynchronous”</h2>
<p>At a technical level, this seems legit. We could be sending the command into a background queue so we don’t know when it’s actually going to be executed. Therefore, we can’t count on a return value for any command.</p>
<p>In earlier times, this was touted as a feature. Commands are so easy to serialize, why wouldn’t we put them in queues and message buses like we do for events? At least, this is how I first understood it.</p>
<p>As time passed though, there’s been a general realization this doesn’t hold up. If I can’t execute the bulk of a user’s request directly because of some resource constraint, then I should still record and acknowledge they started it.</p>
<p>If you’re doing Event Sourcing, using a Saga or Process Manager is a very natural fit here; the initial command doesn’t do anything beyond raising an event that a user requested we do something but at least we have a firm record of it. Then using the same systems we use to distribute events to projectors, we can trigger a background worker when resources are available. If there are any problems, the Saga/Process Manager can retry using the recorded event.</p>
<p>In other words: let events be asynchronous, make commands be synchronous.</p>
<h2 id="we-dont-return-things-because-its-our-write-model">“We don’t return things because it’s our write model.”</h2>
<p>Yes, now we’re getting somewhere.</p>
<p>The CQRS aversion to return values has nothing to do with return values specifically. It’s about making certain the write model isn’t reporting about the current state of the system, that’s the read model’s job. That’s the main supposition of CQRS, after all, that treating problem solving and reporting separately lead to less friction and more flexible models.</p>
<p>Whether the write model gives back state by return value, reference, pointer or passing indirectly via another object doesn’t matter. The goal is to keep the write model from taking on reporting duties.</p>
<p>The lack of return values is a consequence, not a first order rule. We’re not silencing the write model, it just has nothing to say.</p>
<h2 id="right-we-never-return-anything-ever-ever">“Right, we never return anything ever. EVER.”</h2>
<p>We’re not having the write model generate and pass back the changed state of the app.</p>
<p>That said, there are instances the write model responds. In PHP or similar languages, the write model typically raises exceptions to signal error states. While exceptions are semantically and idiomatically different than return values, they can be used in a similar fashion. If we were working in a language without exceptions (like Golang), then it would be very reasonable to return errors from the command bus.</p>
<p>None of this violates CQRS principles. Even orthodox folks will concede that returning an acknowledgement or some other “small” value is reasonable (albeit in rare, always unspecified edge cases). In practice, the most common use case like this is returning a complex id from the command handler. While I (personally) don’t think that’s a huge problem, it’s pretty easy to work around this by introducing a domain service that can be used to pre-generate the id in the controller.</p>
<p>Finally, it’s important to remember that write models often produce state and make it available through other means. The most common reason for CQRS right now is Event Sourcing, which produces state as events. While events are recorded mainly for the purpose of future write model decisions, they are distributed through the system, so in the sense of availability, they’re as good as returned.</p>
<h2 id="wait-so-i-can-return-events-from-my-command-handlers-and-still-be-doing-cqrs">“Wait, so I can return events from my command handlers and still be doing CQRS?”</h2>
<p>I don’t know. Maybe? But even if that was internally consistent, I wouldn’t recommend returning events all the way up to the controller dispatching the command.</p>
<p>Examining the event stream and deciding what to show the user can be a complex task. After all, it’s complex enough that we have the concept of a read model.</p>
<p>The last thing most apps need is more logic in controllers, so don’t burden controllers with the task of interpreting a partial event stream. There might not be enough information to make a good projection but there is enough complexity to make a bad one.</p>
<p>So, while we could get that data at the controller level, that doesn’t make it the best place to handle it. Nor does having the events there overcome the UX frustrations of eventually consistency. If that’s a problem, you don’t have scaling issues and you have a taste for the unorthodox, then flout eventual consistency of your read models however you like but just returning events isn’t the fix for that.</p>
<p>In the end, my advice is let the write model communicate to the read model horizontally and query the read model from your user interface vertically.</p>
<h2 id="cool-story-bro-but-im-using-a-command-bus-that-doesnt-return-anything-so-i-know-im-doing-cqrs-right">“Cool story bro but I’m using a Command Bus that doesn’t return anything so I know I’m doing CQRS right.”</h2>
<p>Not necessarily. What if your read and your write model are still tightly coupled? That can happen regardless of any bus.</p>
<p>In the same way it’s possible to use a data mapper ORM and still produce tight coupling on a database, it’s perfectly possible to use a command bus that doesn’t return anything and not be doing CQRS.</p>
<p>Tooling never guarantees an outcome.</p>
<h2 id="soshould-i-be-returning-stuff-or-not">“So…should I be returning stuff or not?”</h2>
<p>In a non-CQRS app? Do whatever the heck you want.</p>
<p>In a CQRS app? Probably not, depending on how you’ve wired it up. But remember, the point isn’t to cargo-cult about return values, it’s to understand the constraints and decisions that lead to that tactical choice.</p>
<p>Architectures have evolved certain conventions in the way they’re built, it’s the tradeoffs we’re trying to respect, not the specific form. At the same time, these conventions evolved because of the experience of previous developers and we can learn from them to avoid bumping into the same issues.</p>
<p><em>Thanks to Frank de Jonge, Jeroen vd Gulik and Shawn McCool for proofreading and feedback.</em></p>Ross TuckThe most common question I get about my command bus library is: “can commands really return nothing?” The second most common question is “Why do you let commands return something, don’t you know that’s Wrong(tm)?”Precision Through Imprecision: Improving Time Objects2017-08-10T14:30:00+02:002017-08-10T14:30:00+02:00https://rosstuck.com/precision-through-imprecision-improving-time-objects<p>tl;dr When creating value objects representing time, I recommend choosing how finegrained the time should be with your domain experts and round it off to that precision in the value object.</p>
<p>When modeling important numbers, it’s considered good form to specify the precision. Whether it’s money, size or weight; you’ll typically round off to a given decimal point. Even if it’s only for user display, rounding off makes the data more predictable for manipulation and storage.</p>
<p>Unfortunately, we don’t often do this when handling time and it bites us in the rear. Consider the following code:</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$estimatedDeliveryDate</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">DateTimeImmutable</span><span class="p">(</span><span class="s1">'2017-06-21'</span><span class="p">);</span>
<span class="c1">// let's assume today is ALSO 2017-06-21</span>
<span class="nv">$now</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">DateTimeImmutable</span><span class="p">(</span><span class="s1">'now'</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nv">$now</span> <span class="o">></span> <span class="nv">$estimatedDeliveryDate</span><span class="p">)</span> <span class="p">{</span>
<span class="k">echo</span> <span class="s1">'Package is late!'</span><span class="p">;</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="k">echo</span> <span class="s1">'Package is on the way.'</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Since it’s June 21 in the code sample, this code should print “Package is on the way.” After all, the day isn’t over yet, it might just be coming later in the afternoon.</p>
<p>Except the code doesn’t do that. Because we didn’t specify the time component, PHP helpfully zero pads <code class="language-plaintext highlighter-rouge">$estimatedDeliveryDate</code> to <code class="language-plaintext highlighter-rouge">2017-06-21 00:00:00</code>. On the other hand, <code class="language-plaintext highlighter-rouge">$now</code> is calculated for…now. “Now” includes the current time (which probably isn’t midnight), so you’ll get <code class="language-plaintext highlighter-rouge">2017-06-21 15:33:34</code> which is indeed later than <code class="language-plaintext highlighter-rouge">2017-06-21 00:00:00</code>.</p>
<h2 id="solution-1">Solution 1</h2>
<p>“Oh, this is a quick fix.” folks might say and update it to the following.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$estimatedDeliveryDate</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">DateTimeImmutable</span><span class="p">(</span><span class="s1">'2017-06-21'</span><span class="p">);</span>
<span class="nv">$estimatedDeliveryDate</span> <span class="o">=</span> <span class="nv">$estimatedDeliveryDate</span><span class="o">-></span><span class="nf">setTime</span><span class="p">(</span><span class="mi">23</span><span class="p">,</span> <span class="mi">59</span><span class="p">);</span>
</code></pre></div></div>
<p>Cool, we changed the time to include up to midnight. Except the time is padded to <code class="language-plaintext highlighter-rouge">23:59:00</code> so if you look in the last 59 seconds of the day, you’ll have the same problem.</p>
<p>“Grrr, okay.” folks might say.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$estimatedDeliveryDate</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">DateTimeImmutable</span><span class="p">(</span><span class="s1">'2017-06-21'</span><span class="p">);</span>
<span class="nv">$estimatedDeliveryDate</span> <span class="o">=</span> <span class="nv">$estimatedDeliveryDate</span><span class="o">-></span><span class="nf">setTime</span><span class="p">(</span><span class="mi">23</span><span class="p">,</span> <span class="mi">59</span><span class="p">,</span> <span class="mi">59</span><span class="p">);</span>
</code></pre></div></div>
<p>Cool, now it’s fixed.</p>
<p>…Unless you’re on PHP 7.1 which adds microseconds to <code class="language-plaintext highlighter-rouge">DateTime</code> objects. So now it only occurs on the last second of the day. I may be biased after working on too many high traffic systems but sooner or later a user or a automated process will hit that and complain. Good luck tracking down THAT bug. :-/</p>
<p>Okay, let’s add microseconds.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$estimatedDeliveryDate</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">DateTimeImmutable</span><span class="p">(</span><span class="s1">'2017-06-21'</span><span class="p">)</span>
<span class="nv">$estimatedDeliveryDate</span> <span class="o">=</span> <span class="nv">$estimatedDeliveryDate</span><span class="o">-></span><span class="nf">modify</span><span class="p">(</span><span class="s1">'23:59:59.999999'</span><span class="p">);</span>
</code></pre></div></div>
<p>And this works.</p>
<p>Until we get nanoseconds.</p>
<p>In PHP 7.2.</p>
<p>Okay, okay, we CAN reduce the margin of error further and further to the point that errors become unrealistic. Still, at this point it should be clear this approach is flawed: <a href="https://en.wikipedia.org/wiki/Zeno%27s_paradoxes#Dichotomy_paradox">we’re chasing an infinitely divisible value closer and closer to a point we can never reach</a>. Let’s try a different approach.</p>
<h2 id="solution-2">Solution 2</h2>
<p>Instead of calculating the last moment before our boundary, let’s check against the boundary instead.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$estimatedDeliveryDate</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">DateTimeImmutable</span><span class="p">(</span><span class="s1">'2017-06-21'</span><span class="p">);</span>
<span class="c1">// Start calculating when it's late instead of the last moment it's running on time</span>
<span class="nv">$startOfWhenPackageIsLate</span> <span class="o">=</span> <span class="nv">$estimatedDeliveryDate</span><span class="o">-></span><span class="nf">modify</span><span class="p">(</span><span class="s1">'+1 day'</span><span class="p">);</span>
<span class="nv">$now</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">DateTimeImmutable</span><span class="p">(</span><span class="s1">'now'</span><span class="p">);</span>
<span class="c1">// We've changed the > operator to >=</span>
<span class="k">if</span> <span class="p">(</span><span class="nv">$now</span> <span class="o">>=</span> <span class="nv">$startOfWhenPackageIsLate</span><span class="p">)</span> <span class="p">{</span>
<span class="k">echo</span> <span class="s1">'Package is late!'</span><span class="p">;</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="k">echo</span> <span class="s1">'Package is on the way'</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>So this version works and it’s always accurate throughout the whole day. Unfortunately, it’s also become more complex. If you don’t encapsulate this logic within a value object or similar, it’ll get missed somewhere in your app.</p>
<p>Even if you do encapsulate it, we’ve made this one type of operation (>=) logical and consistent but it’s not a consistent fix for all operations. If we wanted to support equality checks, for example, we’d have to do another, different type of special data juggling to make that operation work correctly. Meh.</p>
<p>Finally (and this might just be me) this solution has the misleading smell of a potentially missed domain concept. “Is there a <code class="language-plaintext highlighter-rouge">LatePeriodRange</code>? A <code class="language-plaintext highlighter-rouge">DeliveryDeadline</code>?” you might say. “The package enters into a late period, then….something happens? The domain expert never mentioned a deadline, but it seems to be there. Is that different than the <code class="language-plaintext highlighter-rouge">EstimatedDeliveryDate</code>? Where does it go?” It doesn’t go. It doesn’t go anywhere. It’s just a weird quirk of the implementation that’s now stuck in your head.</p>
<p>So, this is a better solution in that it consistently yields a correct answer…but it’s not a great solution. Let’s see if we can do better.</p>
<h2 id="solution-3">Solution 3</h2>
<p>So, all we want to do is compare two days. Now, if we picture a <code class="language-plaintext highlighter-rouge">DateTime</code> object as a set of numbers (year, month, day, hour, month, second, etc…) everything up to the day part is working fine. All of the problems we’ve had are due to the extra values after that: hour, minute, second, etc. We can argue about the annoying and insidious ways those values keep leaking in there, but the fact remains that the time component that’s wrecking our checks.</p>
<p>If the day component is all that’s important to us, why do we put up with these extra values? Unless it rolls over into the next day, a few extra hours or minutes won’t change the outcome of the business rules.</p>
<p>So, let’s just throw the extra cruft away.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Simplify the dates down to just the day, discarding the rest</span>
<span class="nv">$estimatedDeliveryDate</span> <span class="o">=</span> <span class="nf">day</span><span class="p">(</span><span class="k">new</span> <span class="nc">DateTimeImmutable</span><span class="p">(</span><span class="s1">'2017-06-21'</span><span class="p">));</span>
<span class="nv">$now</span> <span class="o">=</span> <span class="nf">day</span><span class="p">(</span><span class="k">new</span> <span class="nc">DateTimeImmutable</span><span class="p">(</span><span class="s1">'now'</span><span class="p">));</span>
<span class="c1">// Now the comparison is simple</span>
<span class="k">if</span> <span class="p">(</span><span class="nv">$now</span> <span class="o">></span> <span class="nv">$estimatedDeliveryDate</span><span class="p">)</span> <span class="p">{</span>
<span class="k">echo</span> <span class="s1">'Package is late!'</span><span class="p">;</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="k">echo</span> <span class="s1">'Package is on the way.'</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">// Clunky but effective way to discard extra precision. PHP</span>
<span class="c1">// will zero pad the remaining values such as milli/nanosecond.</span>
<span class="c1">// In the case of dates, we can just use the setTime function but for</span>
<span class="c1">// other precisions, you'll have to use other logic to discard the extra</span>
<span class="c1">// data beyond what you need.</span>
<span class="k">function</span> <span class="n">day</span><span class="p">(</span><span class="kt">DateTimeImmutable</span> <span class="nv">$date</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nv">$date</span><span class="o">-></span><span class="nf">setTime</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>This gives us the simpler comparison/calculation we saw in solution 1, with the accuracy we had in solution 2. It’s just…the ugliest version of the code yet, plus it’s super easy to forget to call day() within in your code.</p>
<p>However, the code IS easy to abstract. More importantly though, it’s becoming clear that when we’re talking about estimated delivery dates, we’re ALWAYS talking about a day, never about a time. Both of these things make this a good candidate for pushing this into a type.</p>
<h2 id="encapsulation-at-last">Encapsulation At Last</h2>
<p>In other words, let’s make this a value object.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$estimatedDeliveryDate</span> <span class="o">=</span> <span class="nc">EstimatedDeliveryDate</span><span class="o">::</span><span class="nf">fromString</span><span class="p">(</span><span class="s1">'2017-06-21'</span><span class="p">);</span>
<span class="nv">$today</span> <span class="o">=</span> <span class="nc">EstimatedDeliveryDate</span><span class="o">::</span><span class="nf">today</span><span class="p">();</span>
<span class="k">if</span> <span class="p">(</span><span class="nv">$estimatedDeliveryDate</span><span class="o">-></span><span class="nf">wasBefore</span><span class="p">(</span><span class="nv">$today</span><span class="p">))</span> <span class="p">{</span>
<span class="k">echo</span> <span class="s1">'Package is late!'</span><span class="p">;</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="k">echo</span> <span class="s1">'Package is on the way.'</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Look how nice that reads. The value object itself is nice and boring:</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">EstimatedDeliveryDate</span>
<span class="p">{</span>
<span class="k">private</span> <span class="nv">$day</span><span class="p">;</span>
<span class="k">private</span> <span class="k">function</span> <span class="n">__construct</span><span class="p">(</span><span class="kt">DateTimeImmutable</span> <span class="nv">$date</span><span class="p">)</span>
<span class="p">{</span>
<span class="nv">$this</span><span class="o">-></span><span class="n">day</span> <span class="o">=</span> <span class="nv">$date</span><span class="o">-></span><span class="nf">setTime</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">static</span> <span class="k">function</span> <span class="n">fromString</span><span class="p">(</span><span class="kt">string</span> <span class="nv">$date</span><span class="p">):</span> <span class="kt">self</span>
<span class="p">{</span>
<span class="c1">// Possibly verify YYYY-MM-DD format, etc</span>
<span class="k">return</span> <span class="k">new</span> <span class="nc">static</span><span class="p">(</span><span class="k">new</span> <span class="nc">DateTimeImmutable</span><span class="p">(</span><span class="nv">$date</span><span class="p">));</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">static</span> <span class="k">function</span> <span class="n">today</span><span class="p">():</span> <span class="kt">self</span>
<span class="p">{</span>
<span class="k">return</span> <span class="k">new</span> <span class="nc">static</span><span class="p">(</span><span class="k">new</span> <span class="nc">DateTimeImmutable</span><span class="p">(</span><span class="s1">'now'</span><span class="p">));</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">function</span> <span class="n">wasBefore</span><span class="p">(</span><span class="kt">EstimatedDeliveryDate</span> <span class="nv">$otherDate</span><span class="p">):</span> <span class="kt">bool</span>
<span class="p">{</span>
<span class="k">return</span> <span class="nv">$this</span><span class="o">-></span><span class="n">day</span> <span class="o"><</span> <span class="nv">$otherDate</span><span class="o">-></span><span class="n">day</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Because we’ve now made this a class, we’re automatically enforcing a lot of helpful rules:
You can only compare a <code class="language-plaintext highlighter-rouge">EstimatedDeliveryDate</code> to another <code class="language-plaintext highlighter-rouge">EstimatedDeliveryDate</code>, so the precision always lines up.</p>
<p>The correct precision handling is in a single internal place, the consuming code never needs to consider precision at all.</p>
<p>It’s easy to test.</p>
<p>You’ve got a great single place to centralize your timezone handling (not discussed here but super important).</p>
<p>One quick pro-tip: I’ve used a <code class="language-plaintext highlighter-rouge">today()</code> method here to show how you can have multiple constructors. In practice, I’d recommend creating a system clock and get your “now” instances from that, it’ll make your unit tests <strong>much</strong> easier to write. The “real” version would probably look like:</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$today</span> <span class="o">=</span> <span class="nc">EstimatedDeliveryDate</span><span class="o">::</span><span class="nf">fromDateTime</span><span class="p">(</span><span class="nv">$this</span><span class="o">-></span><span class="n">clock</span><span class="o">-></span><span class="nf">now</span><span class="p">());</span>
</code></pre></div></div>
<h1 id="precision-through-imprecision">Precision Through Imprecision</h1>
<p>The important takeaway here isn’t “value objects, yay, inline juggling, boo!” It’s that we were able to remove several classes of errors by reducing the precision of the <code class="language-plaintext highlighter-rouge">DateTime</code> we were handling. If we hadn’t done that, the value object would still be handling all of these edges cases and probably failing at some of them too.</p>
<p>Reducing the quality of data to get a correct answer might seem counter-intuitive but it’s actually a more realistic view of the system we’re trying to model. Our computers might run in picoseconds but our business (probably) doesn’t. Plus, <a href="https://blogs.msdn.microsoft.com/ericlippert/2010/04/08/precision-and-accuracy-of-datetime/">the computer is probably lying</a> anyways.</p>
<p>As devs, it might feel we’re being more flexible and future-proof by keeping all possible information. After all, who are you to decide what information to throw away? Yet, the truth is that while information can <em>potentially</em> be worth money in the future, it <em>definitely</em> costs money to keep it until that future. It’s not just the cost of a bigger hard drive either, it’s the cost of complexity, of people, of time, and in the case of bugs, reputation. Sometimes working with data in its most complex form will turn out to be worth the cost but sometimes it isn’t, so just blindly saving everything you can because you can isn’t always a winning game.</p>
<p>To be clear: I’m not recommending you just randomly remove available time information.</p>
<p>What I <strong>am</strong> recommending: Explicitly choose a precision for your time points, together with your domain experts. If you’re getting more precision than you expect, it can cause bugs and additional complexity. If you’re getting less precision than you expect, it can cause bugs and failed business rules. The important thing is that we define the expected and necessary level of precision.</p>
<p>Further, choose the precision separately for each use case. Rounding will usually be in the value object, not at the system clock level. As we’ll talk about later, some places still need nanosecond precision but others might only need a year. Getting the precision right makes the language clearer.</p>
<h2 id="this-crap-is-everywhere">This Crap Is Everywhere</h2>
<p>It’s worth pointing out that we’ve only talked about a specific type of bug here: excess precision throwing off greater than/less than checks. But this advice applies to a much wider set of errors. I won’t go into all of them, though I do want to point out a personal favorite, “leftover” precision.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Let's assume today is June 21st, so this equals June 28</span>
<span class="nv">$oneWeekFromNow</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">DateTimeImmutable</span><span class="p">(</span><span class="s1">'+7 days'</span><span class="p">);</span>
<span class="c1">// Also June 28 but set explicitly or loaded from DB</span>
<span class="nv">$explicitDate</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">DateTimeImmutable</span><span class="p">(</span><span class="s1">'2017-06-28'</span><span class="p">);</span>
<span class="c1">// Comparing based on state, are these the same date?</span>
<span class="nb">var_dump</span><span class="p">(</span><span class="nv">$oneWeekFromNow</span> <span class="o">==</span> <span class="nv">$explicitDate</span><span class="p">);</span>
</code></pre></div></div>
<p>No, they’re not the same date because <code class="language-plaintext highlighter-rouge">$oneWeekFromNow</code> also has the current time whereas <code class="language-plaintext highlighter-rouge">$explicitDate</code> is set to <code class="language-plaintext highlighter-rouge">00:00:00</code>. Delightful.</p>
<p>The examples above talked about precision primarily in time vs date but modeling precision applies to any unit of time. Imagine how many scheduling apps only need times to the minute and how many financial apps need support for quarters of the year.</p>
<p>Once you start looking at it, you realize how many time errors can be explained by undefined precision. They might look like bad range checks or poorly designed bounds but when you dive in, you start to see a pattern emerge.</p>
<p>My experience is that this class of errors are often missed in testing. System clock objects aren’t a common sight (yet), so testing code that uses the current time is a bit tricky. And when there are tests, the fixtures often don’t pad the date out completely so so it’s easy to miss the error windows.</p>
<p>Nor is this a problem specific to PHP’s <code class="language-plaintext highlighter-rouge">DateTime</code> library. When I tweeted about this last week, Anthony Ferrara mentioned how Ruby’s time precision varies depending on the operating system yet the database library had an fixed level. That sounds fun to debug.</p>
<p>Time is just hard to work with. Time math doubly so.</p>
<h2 id="choosing-a-level-of-precision">Choosing A Level Of Precision</h2>
<p>So we can say that choosing a level of precision for your time objects is super important but how do we select the right one? As a rule of thumb, I would say be open-ended with timepoints for your technical needs but set an explicit level of precision for all of your domain objects.</p>
<p>For your logs, your event sourcing data, your metrics, go as fine-grained as you need/want/can. These are primarily aimed at technical personnel who are more familiar with fine grained dates and the extra precision is often necessary for debugging. You’ll likely need to get very finegrained for system or sequenced data. That’s okay, it’s what the constraints demand.</p>
<p>For business concerns, talk to your domain experts about how fine-grained that information needs to be. They can help you balance what they’re using now vs what they might need in the future. Business rules are often an area where you’re playing with borrowed knowledge, so shedding complexity can be a smart move. Remember, you’re not after an accurate-to-real-life model, you’re after a useful one.</p>
<p>Within the code, this might occasionally lead to varying levels of precision, even within the same class. For example, consider this class in an event sourced application.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">OrderShipped</span>
<span class="p">{</span>
<span class="c1">// Order object that's capped to day precision.</span>
<span class="k">private</span> <span class="nv">$estimatedDeliveryDate</span><span class="p">;</span>
<span class="c1">// Order object that's capped to second level precision.</span>
<span class="k">private</span> <span class="nv">$shippedAt</span><span class="p">;</span>
<span class="c1">// Event sourcing object that's capped to microsecond</span>
<span class="k">private</span> <span class="nv">$eventRecordedAt</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>If the varying levels of precision seem strange, remember that these time points have very different use cases. Even the <code class="language-plaintext highlighter-rouge">$shippedAt</code> and <code class="language-plaintext highlighter-rouge">$eventRecordedAt</code> might point to the same “time”, but they belong to very different sections of the code.</p>
<p>You might also find the business is working with units (and therefore precisions) of time you don’t expect: quarters, financial calendars, shifts, morning/afternoon/evening parts. There’s a lot of interesting conversations to be had in exploring these extra units.</p>
<h1 id="changing-requirements">Changing Requirements</h1>
<p>Another good part of having these conversations: If the business rules change in the future and you turn out to need more precision than originally recorded, then it was a joint decision and you talk about how to fix the legacy cases. Ideally, we can shift it from being a technical problem to a business one.</p>
<p>In most cases, this can be simple: “We originally only needed the date they signed up but now we need the time so we can see if it falls before business closing times.” Maybe this affects a small number of accounts and you can set them to the beginning of the next business day. Or just zero pad the dates. Or maybe there’s an extra business rule where signing up after 18:00 sets the subscription end date to tomorrow+1 year instead of today+1 year. Talk to them about it. Folks are more proactive and understanding with changes if you include them in the discussion from the beginning (if only to mitigate blame).</p>
<p>In more complex scenarios, you can look at reconstructing data based on other data in your system. Maybe we can derive it from event sourcing times or user registration dates. In some cases, it simply isn’t possible and you’ll have to construct new business rules about what to do with migrating legacy cases. But the truth is, you can’t plan for everything and you probably won’t know what will change. That’s life.</p>
<p>So that’s my thoughts about time precision: use what you need and no more.</p>
<h2 id="appendix-an-ideal-solution">Appendix: An Ideal Solution</h2>
<p>Going forward, I feel there’s real practical benefits to choosing fixed precisions and modeling them as custom types. My ideal PHP time library would probably be something that provides units of time as abstract classes that I extend into my value objects and then build on.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">ExpectedDeliveryDate</span> <span class="kd">extends</span> <span class="nc">PointPreciseToDate</span>
<span class="p">{</span>
<span class="p">}</span>
<span class="kd">class</span> <span class="nc">OrderShippedAt</span> <span class="kd">extends</span> <span class="nc">PointPreciseToMinute</span>
<span class="p">{</span>
<span class="p">}</span>
<span class="kd">class</span> <span class="nc">EventGenerationTime</span> <span class="kd">extends</span> <span class="nc">PointPreciseToMicrosecond</span>
<span class="p">{</span>
<span class="p">}</span>
</code></pre></div></div>
<p>By pushing the precision to the class, we force a decision about precision. We can limit methods like “setTime()” to the precisions they actually apply to (not on Dates!) and we can round <code class="language-plaintext highlighter-rouge">DateInterval</code> to whatever makes sense for the type. Most of the utility methods could have protected visibility and my value objects could expose only those that make sense for my domain. Also, we’d be encouraging folks to create value objects. So. Many. Value objects. Yessss.</p>
<p>Bonus points if the library makes it easy to define custom units of time.</p>
<p>Actually building it though? Ain’t nobody got time for that.</p>
<p><em>Many thanks to Frank de Jonge, Jeroen Heijmans, Anna Baas and Matthias Noback for feedback on earlier drafts of this article!</em></p>Ross Tucktl;dr When creating value objects representing time, I recommend choosing how finegrained the time should be with your domain experts and round it off to that precision in the value object.Formatting Exception Messages2015-10-27T11:30:00+01:002015-10-27T11:30:00+01:00https://rosstuck.com/formatting-exception-messages<p>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 <a href="https://github.com/doctrine/doctrine2/blob/4fc1781d78fab42377fedda843045371b14f8f1e/lib/Doctrine/ORM/ORMException.php">better part of a decade</a>. Still, many folks are surprised by it, so this article explains the how and why.</p>
<h2 id="how-does-it-work">How does it work?</h2>
<p>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:</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nv">$row</span><span class="o">-></span><span class="nf">hasColumns</span><span class="p">(</span><span class="nv">$expectedColumns</span><span class="p">))</span> <span class="p">{</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nc">Exception</span><span class="p">(</span><span class="s2">"Row is missing one or more columns"</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>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.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">InvalidRowException</span> <span class="k">extends</span> <span class="err">\</span><span class="nc">Exception</span>
<span class="p">{</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Now we throw our custom Exception instead:</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nv">$row</span><span class="o">-></span><span class="nf">hasColumns</span><span class="p">(</span><span class="nv">$expectedColumns</span><span class="p">))</span> <span class="p">{</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nc">InvalidRowException</span><span class="p">(</span><span class="s2">"Row is missing one or more columns"</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>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 <code class="language-plaintext highlighter-rouge">NoDatabaseConnectionException</code> but only log an <code class="language-plaintext highlighter-rouge">InvalidRowException</code> before continuing.</p>
<p>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.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nv">$row</span><span class="o">-></span><span class="nf">hasColumns</span><span class="p">(</span><span class="nv">$expectedColumns</span><span class="p">))</span> <span class="p">{</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nc">InvalidRowException</span><span class="p">(</span>
<span class="s2">"Row #"</span> <span class="mf">.</span> <span class="nv">$row</span><span class="o">-></span><span class="nf">getIndex</span><span class="p">()</span> <span class="mf">.</span> <span class="s2">" is missing one or more columns"</span>
<span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>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 <code class="language-plaintext highlighter-rouge">InvalidRowException</code> but we’d need to format them all to include the row number. Booorrrriiing.</p>
<h2 id="moving-the-formatting">Moving the Formatting</h2>
<p>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:</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">InvalidRowException</span> <span class="k">extends</span> <span class="err">\</span><span class="nc">Exception</span>
<span class="p">{</span>
<span class="k">public</span> <span class="k">static</span> <span class="k">function</span> <span class="n">incorrectColumns</span><span class="p">(</span><span class="kt">Row</span> <span class="nv">$row</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="k">new</span> <span class="nc">static</span><span class="p">(</span><span class="s2">"Row #"</span> <span class="mf">.</span> <span class="nv">$row</span><span class="o">-></span><span class="nf">getIndex</span><span class="p">()</span> <span class="mf">.</span> <span class="s2">" is missing one or more columns"</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>And now we can clean up the importing code without losing readability:</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nv">$row</span><span class="o">-></span><span class="nf">hasColumns</span><span class="p">(</span><span class="nv">$expectedColumns</span><span class="p">))</span> <span class="p">{</span>
<span class="k">throw</span> <span class="nc">InvalidRowException</span><span class="o">::</span><span class="nf">incorrectColumns</span><span class="p">(</span><span class="nv">$row</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>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.</p>
<p>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.</p>
<p>Maybe common errors warrant more complex output, like including both the expected <em>and</em> the received list of columns.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">static</span> <span class="k">function</span> <span class="n">incorrectColumns</span><span class="p">(</span><span class="kt">Row</span> <span class="nv">$row</span><span class="p">,</span> <span class="nv">$expectedColumns</span><span class="p">)</span>
<span class="p">{</span>
<span class="nv">$expectedList</span> <span class="o">=</span> <span class="nb">implode</span><span class="p">(</span><span class="s1">', '</span><span class="p">,</span> <span class="nv">$expectedColumns</span><span class="p">);</span>
<span class="nv">$receivedList</span> <span class="o">=</span> <span class="nb">implode</span><span class="p">(</span><span class="s1">', '</span><span class="p">,</span> <span class="nv">$row</span><span class="o">-></span><span class="nf">getColumns</span><span class="p">());</span>
<span class="k">return</span> <span class="k">new</span> <span class="nc">static</span><span class="p">(</span>
<span class="s2">"Row #"</span> <span class="mf">.</span> <span class="nv">$row</span><span class="o">-></span><span class="nf">getIndex</span><span class="p">()</span> <span class="mf">.</span> <span class="s2">" did not contain the expected columns. "</span> <span class="mf">.</span>
<span class="s2">" Expected columns: "</span> <span class="mf">.</span> <span class="nv">$expectedList</span> <span class="mf">.</span>
<span class="s2">" Received columns: "</span> <span class="mf">.</span> <span class="nv">$receivedList</span>
<span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>The code here got significantly richer but the consuming code only needed to pass one extra parameter.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nv">$row</span><span class="o">-></span><span class="nf">hasColumns</span><span class="p">(</span><span class="nv">$expectedColumns</span><span class="p">))</span> <span class="p">{</span>
<span class="k">throw</span> <span class="nc">InvalidRowException</span><span class="o">::</span><span class="nf">incorrectColumns</span><span class="p">(</span><span class="nv">$row</span><span class="p">,</span> <span class="nv">$expectedColumns</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>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.</p>
<p>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.</p>
<h2 id="multiple-use-cases">Multiple Use Cases</h2>
<p>So far we’ve created a method for one specific use case, an incorrect number of columns.</p>
<p>Maybe we have other issues with our CSV file, like the existence of blank lines. Let’s add a second method to our exception:</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">InvalidRowException</span> <span class="k">extends</span> <span class="err">\</span><span class="nc">Exception</span>
<span class="p">{</span>
<span class="c1">// ... incorrectColumns ...</span>
<span class="k">public</span> <span class="k">static</span> <span class="k">function</span> <span class="n">blankLine</span><span class="p">(</span><span class="nv">$rowNumber</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">return</span> <span class="k">new</span> <span class="nc">static</span><span class="p">(</span><span class="s2">"Row #</span><span class="nv">$rowNumber</span><span class="s2"> was a blank line."</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>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).</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">static</span> <span class="k">function</span> <span class="n">blankLine</span><span class="p">(</span><span class="nv">$rowNumber</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">return</span> <span class="k">new</span> <span class="nc">static</span><span class="p">(</span>
<span class="s2">"Row #</span><span class="nv">$rowNumber</span><span class="s2"> was a blank line. This can happen if the user "</span> <span class="mf">.</span>
<span class="s2">"exported the source file with incorrect line endings."</span>
<span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<h2 id="locking-it-down">Locking It Down</h2>
<p>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.</p>
<p>First off, we can’t in PHP. Exceptions all extend from a parent Exception class and can’t change their parent’s <code class="language-plaintext highlighter-rouge">__construct</code> access level from public to private.</p>
<p>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.</p>
<p>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:</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">InvalidRowException</span> <span class="k">extends</span> <span class="err">\</span><span class="nc">Exception</span>
<span class="p">{</span>
<span class="c1">// One off error messages can use this method...</span>
<span class="k">public</span> <span class="k">static</span> <span class="k">function</span> <span class="n">create</span><span class="p">(</span><span class="kt">Row</span> <span class="nv">$row</span><span class="p">,</span> <span class="nv">$reason</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">return</span> <span class="k">new</span> <span class="nc">static</span><span class="p">(</span><span class="s2">"Row "</span> <span class="mf">.</span> <span class="nv">$row</span><span class="o">-></span><span class="nf">getIndex</span><span class="p">()</span> <span class="mf">.</span> <span class="s2">" is invalid because: "</span> <span class="mf">.</span> <span class="nv">$reason</span><span class="p">);</span>
<span class="p">}</span>
<span class="c1">// ...and predefined methods can use it internally.</span>
<span class="k">public</span> <span class="k">static</span> <span class="k">function</span> <span class="n">blankLine</span><span class="p">(</span><span class="kt">Row</span> <span class="nv">$row</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">return</span> <span class="k">static</span><span class="o">::</span><span class="nf">create</span><span class="p">(</span><span class="nv">$row</span><span class="p">,</span> <span class="s2">"Is a blank line."</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Which might be useful but is probably pretty far out there. I haven’t seen a convenient way to enforce it though.</p>
<h2 id="the-big-picture">The Big Picture</h2>
<p>There’s one final benefit I’d like to touch on.</p>
<p>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.</p>
<p>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.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// One of these isn’t like the others and should probably be a different Exception class</span>
<span class="kd">class</span> <span class="nc">InvalidRowException</span> <span class="k">extends</span> <span class="err">\</span><span class="nc">Exception</span>
<span class="p">{</span>
<span class="k">public</span> <span class="k">static</span> <span class="k">function</span> <span class="n">missingColumns</span><span class="p">(</span><span class="kt">Row</span> <span class="nv">$row</span><span class="p">,</span> <span class="nv">$expectedColumns</span><span class="p">);</span>
<span class="k">public</span> <span class="k">static</span> <span class="k">function</span> <span class="n">blankLine</span><span class="p">(</span><span class="kt">Row</span> <span class="nv">$row</span><span class="p">);</span>
<span class="k">public</span> <span class="k">static</span> <span class="k">function</span> <span class="n">invalidFileHandle</span><span class="p">(</span><span class="nv">$fh</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>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.</p>Ross TuckOver 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 I Use Traits2015-05-18T11:20:00+02:002015-05-18T11:20:00+02:00https://rosstuck.com/how-i-use-traits<p>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.</p>
<h2 id="leverage-vs-abstraction">Leverage vs Abstraction</h2>
<p>The first thing you should do is go read this blog post: <a href="http://thinkrelevance.com/blog/2013/04/04/abstraction-or-leverage">“Abstraction or Leverage” from Michael Nygard</a>. It’s an excellent article.</p>
<p>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:</p>
<ul>
<li><strong>Abstraction</strong> gathers similar code behind a higher level concept that’s more concise for other code to work with.</li>
<li><strong>Leverage</strong> gathers similar code together so you only have one place to change it.</li>
</ul>
<p>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 <em>behind</em> the concept of a Repository.</p>
<p>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.</p>
<p>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.</p>
<h2 id="whats-this-have-to-do-with-traits">What’s this have to do with traits?</h2>
<p>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.</p>
<p>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?</p>
<p>I use traits when I want leverage, not abstraction.</p>
<p>Sometimes.</p>
<h2 id="sometimes">Sometimes?</h2>
<p>Benjamin Eberlei makes a good argument that <a href="http://www.whitewashing.de/2013/04/12/traits_are_static_access.html">traits have basically the same problems as static access</a>. You can’t exchange or override them and they’re lousy for testing.</p>
<p>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.</p>
<p>Traits have roughly the same constraints, plus they can only be used when mixed into a class. They’re more macro than object.</p>
<p>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.</p>
<p>An example I often use is generating domain events on an entity:</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">trait</span> <span class="nc">GeneratesDomainEvents</span>
<span class="p">{</span>
<span class="k">private</span> <span class="nv">$events</span> <span class="o">=</span> <span class="p">[];</span>
<span class="k">protected</span> <span class="k">function</span> <span class="n">raise</span><span class="p">(</span><span class="kt">DomainEvent</span> <span class="nv">$event</span><span class="p">)</span>
<span class="p">{</span>
<span class="nv">$this</span><span class="o">-></span><span class="n">events</span><span class="p">[]</span> <span class="o">=</span> <span class="nv">$event</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">function</span> <span class="n">releaseEvents</span><span class="p">()</span>
<span class="p">{</span>
<span class="nv">$pendingEvents</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-></span><span class="n">events</span><span class="p">;</span>
<span class="nv">$this</span><span class="o">-></span><span class="n">events</span> <span class="o">=</span> <span class="p">[];</span>
<span class="k">return</span> <span class="nv">$pendingEvents</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p><a href="https://gist.github.com/rosstuck/09804eed5fb9020a1ff0">While we can refactor this to an abstraction</a>, 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.</p>
<p>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.</p>
<p>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.</p>
<p>Assertions are a good example of where I prefer static methods, despite seeing them commonly placed in traits. Still, I find <code class="language-plaintext highlighter-rouge">Assertion::positiveNumber($int)</code> gives me the aforementioned benefits and it’s easier to understand what it is (or isn’t) doing to the calling class.</p>
<p>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 <code class="language-plaintext highlighter-rouge">$this->foo</code> relies on the value of <code class="language-plaintext highlighter-rouge">$this->bar</code>. 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.</p>
<p>So, to restate: I use traits when I want leverage that needs access to an object’s internal state.</p>
<h2 id="parent-classes">Parent Classes</h2>
<p>Everything we’ve seen is also possible through inheritance. An <code class="language-plaintext highlighter-rouge">EventGeneratingEntity</code> would arguably be even better since <a href="http://3v4l.org/M80Zl">the events array would be truly private</a>. 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?</p>
<p>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 <em>traits are not composition</em> but it’s a reasonable guideline.</p>
<p>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.</p>
<p>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.</p>
<p>So, in the case of the event generation, I prefer the trait to a base <code class="language-plaintext highlighter-rouge">EventGeneratingEntity</code> because Event Generation is a supporting feature.</p>
<h2 id="interfaces">Interfaces</h2>
<p>I rarely (if ever) extend a class or create a trait without also creating an interface.</p>
<p>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.</p>
<p>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.</p>
<p>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.</p>
<h2 id="when-i-do-not-use-traits">When I do not use traits</h2>
<p>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.</p>
<p>There’s a few places I don’t like to use traits due to style preferences:</p>
<ul>
<li>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.</li>
<li>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.</li>
<li>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.</li>
</ul>
<p>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.</p>Ross TuckRecently, 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.Notes From 3 Conferences2014-10-12T20:26:19+02:002014-10-12T20:26:19+02:00https://rosstuck.com/notes-from-3-conferences<p>I started this month by speaking or hosting at 4 events in 2 countries over 5 days (<a href="https://amsterdam2014.drupal.org/">DrupalCon Amsterdam</a>, <a href="http://domcode.org">DomCode</a>, <a href="http://2014.zgphp.org">ZgPHP</a>, <a href="http://2014.webcampzg.org">WebCamp</a>). 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.</p>
<h2 id="drupalcon">DrupalCon</h2>
<p>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.</p>
<p>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 (<a href="https://amsterdam2014.drupal.org/sites/default/files/images/ams-exhibit-hall.png">check out the sponsors hall</a>). The keynote discussed Drupal as becoming a <a href="http://en.wikipedia.org/wiki/Public_good">Public Good</a>, 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.</p>
<p>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.</p>
<p>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.</p>
<p>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.</p>
<p>Some of the articles in the <a href="http://drupalwatchdog.com/">Drupal magazine</a> 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.</p>
<p>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.</p>
<h2 id="zgphp">ZgPHP</h2>
<p>Two days later, and I was presenting at ZgPHP in Zagreb, Croatia (my first trip to the region). The difference was intense.</p>
<p>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.</p>
<p>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.</p>
<p>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).</p>
<p>So, yes, it’s a small conference but by design. It was well run, well organized and a really nice community.</p>
<p>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.</p>
<h2 id="webcamp">WebCamp</h2>
<p>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.</p>
<p>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.</p>
<p>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.</p>
<p>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.</p>
<p>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.</p>
<p>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+).</p>
<p>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.</p>
<p>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.</p>
<h2 id="conclusion">Conclusion</h2>
<p>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)!</p>
<p>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.</p>
<p>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?</p>
<p>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.</p>
<p>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?</p>
<p><em>Many thanks to <a href="https://twitter.com/igorwhiletrue">Igor Wiedler</a> for proofreading an earlier version of this article</em></p>Ross TuckI 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.Tips on Speaking2014-09-12T01:22:21+02:002014-09-12T01:22:21+02:00https://rosstuck.com/tips-on-speaking<p>Earlier this evening, I was a guest on <a href="http://nocapes.github.io">NoCapes</a>, 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.</p>
<p>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.</p>
<p>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.</p>
<p>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.</p>
<h2 id="getting-accepted">Getting Accepted</h2>
<ul>
<li>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.</li>
<li>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.</li>
<li>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 your stuff.</li>
<li>If you’re submitting to a conference that requires traveling, always submit multiple talks (at least 3, maybe more). If they’re going to pay for a flight and hotel, they’re probably going to want 2 or more talks from you.</li>
<li>If you’re attending a conference you’d like to speak at, rock it hard at the uncon and then tell the organizers you’re going to submit next year. They’ll remember you. Some conferences even give away guaranteed speaker slots to the best uncon speakers of the year.</li>
<li>It’s perfectly okay to submit talks you haven’t written yet, provided you have time to write them. Shoot in a few ideas and let the organizers sort out which ones are good. Likewise, don’t be afraid to reuse talks at other conferences.</li>
<li>It’s okay to pick subjects you need to do further research into. In fact, it’s often a great motivator to do so. Just don’t pick subjects you know absolutely zero about, people expect some experience or credentials from their speakers (unless your talk is “How I Stumbled Through Putting X into Production” which is also valid as an intro tutorial).</li>
<li>Sad to say but it’s still often about who you know. Find out who the influential speakers or groups in your area are and go out of your way to meet them. 90% of them will already want to help.</li>
<li>It’s all about getting that first talk. Once you have that done, you can use it to get the second and the third and…</li>
</ul>
<h2 id="writing">Writing</h2>
<ul>
<li>Start writing with lots of time. Literally, at least a month out.</li>
<li>The #1 tip: If you have bullet lists, break each bullet point up into an individual slide.</li>
<li>If you do have lots of text on the same slide, use the appear animation to stagger the lines. Otherwise, people will read ahead and not listen to you (or worse, become bored).</li>
<li>There is no right number of slides. I’ve seen great speakers use anywhere from 20 slides to 280 slides for 45 minute slots.</li>
<li>Don’t start writing slides at the beginning of the talk, skip to the cool technical part you want to talk about. Get that section right and then build the rest of the talk around that.</li>
<li>When writing, I often sketch out 30-60 seconds of talking, then backtrack and create the slides for that. Then I do that part again with the slides, adjust or scrap, then write the next 30-60 seconds of talking. Repeat until done.</li>
<li>It’s good to have an About Me intro but keep it under 45 seconds.</li>
<li>Anticipate the questions your audience will have at any given moment in a talk and then address them immediately. If you don’t, they’ll stop listening to what you’re saying until its question time while they mule this over or wait for you to address it.</li>
<li>Don’t ever be afraid to rewrite but don’t make major rewrites in the days leading up to the conference, you will forget and goof them.</li>
<li>Your talk doesn’t need to have a story, but build it like one. It should have a lead-in, build up, a climax and a resolution. Emotion has a place, even in technical talks.</li>
<li>If you’re having trouble finding a voice, pick speakers you like and imitate them until you find one that feels comfortable. That’ll put you in the right area, then refine it until you find yours. This doesn’t have to be a technical speaker: in fact, I’d recommend stand-up comedians. That’s not to say it has to be funny, but these are folks with the stagecraft to keep an audience enraptured for hours with almost nothing but talking. You can learn a lot from them.</li>
<li>Gimmicks can lend spice to a talk but don’t over use them.</li>
<li>The only good animation is the “appear” animation. Don’t use animated slide transitions and don’t let meme GIFs loop indefinitely.</li>
</ul>
<h2 id="talk-formats">Talk Formats</h2>
<ul>
<li>Don’t do live demos. These are high risk, high reward propositions. If it goes smoothly and it’s genuinely impressive, you <em>might</em> look amazing. That said, almost every live demo will crash and burn horribly. Including yours.</li>
<li>If you do go this route, remember: it will also likely take more than network communication to genuinely impress the audience.</li>
<li>Likewise, live coding is a universally bad idea. Even if it goes perfectly (and it won’t), the speed at which you can deliver is severely reduced. Even amazing developers are boring after 30 minutes of typing at a podium.</li>
<li>Instead, consider making a screen recording and embedding it in your presentation. This can fail too but the odds are much lower. You can also speed this up, pause it, rewind it, etc and it leaves you more free to talk and manage your time without fear.</li>
<li>Never count on an internet connection. No, not even with speaker-only wifi. No, not even tethering on your phone. Never. Count. On. Internet.</li>
</ul>
<h2 id="the-weeks-before-your-talk">The Weeks Before Your Talk</h2>
<ul>
<li>Practice. Practice Practice practice.</li>
<li>Always back up your presentation twice: a USB stick that you carry with you and and online (email, Google Drive, Dropbox). Don’t forget the additional dependencies like fonts, movies, etc.</li>
<li>Always ask about the projector connection beforehand. Be prepared. When in doubt, prepare for VGA. The only place this might not be true is development offices: many are populated exclusively by Mac users and may not have a VGA adapter on hand.</li>
<li>If you’re a Mac user, bring your own connectors. Many conferences have them, but many don’t or have a limited supply.</li>
<li>Don’t get drunk the night before your talk. Seriously, be a professional. Conference culture features a lot of drinking but attendees paid good money to see you speak so don’t show up with a hangover. Even if you’re in the afternoon slot, save the booze for the post-talk celebration.</li>
<li>Even a cheap remote is worth its weight in gold. Seriously, don’t get on stage without a remote, it’s incredibly freeing.</li>
<li>When practicing, don’t just stare at your monitor since this will become a bad habit when you present. I once suggested giving your talk to a stuffed animal since you can make eye contact with it; silly as it sounds, an elePHPant makes a great reviewer.</li>
<li>Controlling your body language is important. Practice your talk standing up and work hard on creating a firm posture: it looks good to the audience but more importantly, it keeps you calm and projects your voice. Fidgeting will make you nervous, unsteady and distract the audience.</li>
<li>You’re going to be standing for almost an hour and talking, which can be a surprisingly physical strain. Practice so you’re ready for this. A lot of the exhaustion can be bad breathing techniques, which you can work on.</li>
<li>When practicing, you’ll often go over time a few minutes. That’s usually okay. When giving your talk, you’ll probably speed up a bit or not backtrack as much in practice, so it’s going to go quicker. Eventually, you’ll find out what that magic number is and be able to plan accordingly.</li>
<li>Until then, prep carefully, don’t plan too much material and think about your pacing and what you can cut or extend if necessary. Always build in an escape hatch or two.</li>
<li>Practice more!</li>
</ul>
<h2 id="the-day-of-your-talk">The Day of Your Talk</h2>
<ul>
<li>Sleep well. Have a decent breakfast, nothing too crazy.</li>
<li>Practice your entire talk the morning of the conference if time allows.</li>
<li>Resist the temptation to tweak anything else with your slides, it’ll just disturb your practice. It’s time, you have to play it as it lies.</li>
<li>Dress accordingly: Comfortable shoes are a must. Think about how you’ll look in the room: If it’s dim or darkened, don’t wear all black since you’ll look like a floating head. If you’re standing in front of a colored backdrop, don’t wear something that blends in (like a red shirt in front of red stage curtains).</li>
<li>Show up early. If your conference has a room monitor or an assigned volunteer for you, check in with them, learn the their name. If the crap hits the fan, these folks can save your bacon.</li>
<li>Always attend sound check if you can. Find these problems early.</li>
<li>See if you can get a peek at the room or stage first. Pace it, see how it feels. Set your laptop up somewhere and see if you can see your slides comfortably.</li>
<li>It might be worth skipping the talk in the slot ahead of yours and find a quiet corner to review your slides right before. This helped me a lot when I was starting out.</li>
<li>Not to sound like your parents on a car trip, but use the bathroom first. Yes, even if you don’t think you have to.</li>
<li>If this is your first talk, it almost seems tradition that you’re going to come down with a cold right before hand. Take something with minimal side effects (acetaminophen or paracetamol) or suck a cough drop. If you’re congested, nose spray is the best thing but it doesn’t kick in until 5-10 minutes later so don’t use it just before going on stage. Whatever you’ve got to do, do it.</li>
<li>Hand-mics take training to use well, so skip them in favor of anything else if possible. Face mics or lapel mics are the best but even a fixed podium mic can be better.</li>
</ul>
<h2 id="the-moments-beforehand">The Moments Beforehand</h2>
<ul>
<li>Once the previous speaker is totally done, wait for them to clear the podium and then setup ASAP. If the speaker is taking a little while and is answering private questions, give them a minute before heading to the podium. They’ll usually see you standing there with your bag and take the hint, but if they don’t, it’s okay to ask politely if you can go ahead and setup.</li>
<li>Soundcheck everything real quick and check the space. Check you can see your laptop clearly from where you want to stand. Check your remote batteries.</li>
<li>Silence your phone and dump it in your bag. Otherwise, you’re going to get a tweet notifications during the talk and folks will start tweeting at you, just to troll you.</li>
<li>If you’re feeling good, maybe do some pre-show audience particpation. Talk to folks in the first row, goof off a bit. I used to play nyan.cat on the big screen to loosen everyone up.</li>
<li>Breathe and relax. These are often the scarest moments but it’s going to be okay.</li>
</ul>
<h2 id="giving-your-talk">Giving Your Talk</h2>
<ul>
<li>The number one thing new speakers goof is looking at the big screen. Look at your laptop. Look at the stage monitor. Look at the audience. Never, ever look at the big screen. Yes, I know it’s big and shiny. Don’t look at it. You’ll twist and turn, ignore your audience, etc. It’s bad.</li>
<li>Likewise, don’t use your laser pointer. If there’s something on a slide you want to highlight, add that to your slides as an arrow or highlight or fade out surrounding text. Laser pointers tremble, distract and can even make the audience vaguely nauseous.</li>
<li>Don’t go too fast. You’re likely going to freak out a bit the first time and go too fast. I’m infamous for doing this from the early days of my career. Time dilates on stage, what feels like an eternity on stage will often prove to only be a bare second on the video playback. Speak clearly, relax.</li>
<li>Most room monitors will give you a signal at important time intervals: usually 15, 10, 5 and 1 minutes to go. Give them a little nod or thumbs up to confirm you saw. Don’t freak out at the signal. Trust in your training, hold your ground and hold your pace.</li>
<li>In tech, it’s common to see folks poking at their phones or laptops while you’re speaking. It’s not disrepect or boredom, we’re just multitasking geeks. Often those folks poking at their phones are sending out tweets about how awesome you are.</li>
<li>Look at the audience when speaking. Consider all parts of the room. Pick a few faces here and there and rotate between them every couple of minutes. Don’t go creepy-stare-face but look for friends or people into it, use them for support.</li>
<li>Consider the local culture. At the risk of stereotyping, crowds have different vibes depending on where you go: the British laugh a lot, even when you’re not telling a joke so plan for it. The Dutch are more restrained but don’t do audience participation. Adapt accordingly.</li>
</ul>
<h2 id="handling-questions">Handling Questions</h2>
<ul>
<li>Always repeat the question to ensure you understand it, and for both the recording and others in the room. This is a hard one to remember but it reflects well on your polish.</li>
<li>Check your room monitor for how much time is allowed for questions (if any). If there’s no room monitor, check the time discreetly.</li>
<li>The knowledge level in the room can vary enormously. Even beginner questions deserve your respect. Never use your position to denigrate someone.</li>
<li>There’s a chance you’re going to get “pointed” questions, which are often not questions but argumentative attendees or someone looking to take a whack at you. These often come with elaborate backstories or a particular tone or a “don’t you think…”.</li>
<li>Don’t ever take the bait on these, the moment you become angered, you’ve lost control of the situation. Instead, try to answer factually and calmly. Always take the high road. Often, there’s a veiled barb or underlying question, it can be helpful to address that head on. If you can’t resolve the question directly, offer to talk to the attendee afterwards. “Hmm, well, come talk to me afterwards” can get you out of almost any sticky situation.</li>
<li>If you get a really advanced or tricky question that you don’t know the answer to, don’t BS it. People can smell it and someone might call you on it. Again, you can get really far with: “Hmm, that’s a good one, I’m not sure. Come talk to me afterwards and we’ll see if we can figure it out.” If someone from the audience calls out an answer, always be supportive and thank them if it sounds legit: “Oh, good one, that might work”.</li>
</ul>
<h2 id="after-your-talk">After Your Talk</h2>
<ul>
<li>Say thank you, point folks to your joind.in link again with your final slide.</li>
<li>Remember to switch off your mic!</li>
<li>People are going to come up to the podium to ask more questions. Say hi, be inviting and polite to them.</li>
<li>While you’re doing the private questions and riding the endorphin rush, pack up your stuff and clear the podium ASAP. The other speaker will likely be fidgeting and ready to get setup almost immediately. Take the remaining questions off to the side or out in the hall.</li>
<li>Double check you’ve got everything (I always forget my remote’s sheath) and leave the mic for the next person or hand it over to the room monitor.</li>
<li>Handle all of the private questions before disappearing. If someone is taking up too much time, politely give them a hint or just give a gentle acknowledgement to the next person in line. Try to at least hear everyone fairly quickly, since folks will often head off to the next talk. You can always make an agreement to meet again later with folks who have larger issues. Triage.</li>
<li>Have business cards within easy reach.</li>
<li>Don’t just leave the conference now that your talk is done. Stick around, meet folks, answer questions. Part of the experience people pay for is getting to hob nob with speakers, network and talk to you in hallways and socials. Remember, that’s what you were flown in for. Be professional. Hiding out to relax for a slot after your talk is okay but blowing the conference immediately after your talk is prima donna BS.</li>
</ul>
<h2 id="social-media-followup">Social Media Followup</h2>
<ul>
<li>Post your slides to Slideshare/Speakerdeck/Wherever and tweet them on the event’s hashtag. It’s acceptable to do this via the joind.in page so you often get more feedback.</li>
<li>Odds are, you won’t be happy with your performance. That’s okay. It means you still have potential to become a better speaker. Honestly, I’ve had talks I felt were bombs that the audience was still satisfied with. The ultimate metric here is how you feel about things and if you communicated your message.</li>
<li>Don’t freak out and start checking your reviews immediately. Give it some time and let a few trickle in. Take them seriously, try to improve whatever folks mention. Don’t post defensive comments.</li>
<li>Likewise, reviews tend to be dominated by folks who either loved your talk or hated it. Rarely do you get both camps under one roof, so keep it in mind. Often a bad talk on joind.in simply gets the “crickets” treatment (though as a new speaker you’ll often have smaller rooms and thus fewer reviews). If you had a well attended talk but got noticeably fewer reviews than other talks at the conference… you may have some soul searching to do.</li>
<li>Vicious reviews can happen. They’re designed to hurt the most but sometimes they contain an element of truth. Take something constructive away if you can, but ultimately, screw those haters.</li>
</ul>
<h2 id="hanging-out-in-hallways">Hanging Out in Hallways</h2>
<ul>
<li>Once you’ve given your talk, folks will randomly ask you questions all the time. Handle them with respect (unless you’re, you know, using the bathroom or something).</li>
<li>Many conferences have separate badges for speakers. These typically draw attention to you and people want to ask what you’re speaking about, etc. This can be great for networking or breaking the ice but you can also just flip the badge around backwards if you’d like to have a normal conversation.</li>
</ul>
<h2 id="the-social">The Social</h2>
<ul>
<li>You’ll get more technical questions at the social so be ready. Also, a fair number of people will just want to come up and meet you, shake your hand, etc. Always be willing to interrupt what you’re doing and shake someone’s hand because it’s going to happen.</li>
<li>Don’t hang out with just the cool speaker crowd, make an effort to meet random folks. Also, treat everyone with respect and assume they’re smarter than you; you never know when someone you casually met is actually hugely famous (this has happened to be a few times).</li>
<li>If someone is monopolizing your time or making you feel uncomfortable, you can always excuse yourself to get another drink or take a bathroom break. (I’ve only had to do this twice in practice so if I’ve ever done this at a conference, please don’t think I was avoiding you).</li>
<li>Folks will often offer to treat you to free drinks, so be gracious but judicious in accepting. Being a speaker doesn’t entitle you to anything.</li>
<li>Take the time to find and thank the organizers. They work hard and do appreciate this.</li>
<li>Okay, now you can get a little drunk.</li>
</ul>
<h2 id="the-less-than-glamorous-tips">The Less Than Glamorous Tips</h2>
<ul>
<li>Your nose might start running during the talk. If so, take the time to turn away from the mic and wipe it. Nothing is worse than a speaker with the sniffles, especially with a face mic.</li>
<li>Bringing tissues, cough drops and even nose spray is often a very good idea. Always keep an open tissue in your back pocket or on the podium. Cough drops are also a surprisingly good ice breaker with other speakers.</li>
<li>Stage lights can be blinding. They’ll also make your eyes water and your nose run even more. Try to get used to them during sound check since this is the only way you can practice, short of staring into the heat of a thousand suns. Before the talk, when people are filing in, take note of where they start to sit. This way, if you really do become blinded, you can still pretend to make eye contact with the audience.</li>
<li>Con Flu is a real thing and you’re going to be shaking a lot of hands. Washing yours regularly might reduce your chances of getting sick afterwards.</li>
</ul>Ross TuckEarlier 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.Notes from LaraconEU2014-09-02T00:00:00+02:002014-09-02T00:00:00+02:00https://rosstuck.com/notes-from-laraconeu<p>Having spent the previous weekend at LaraconEU, I wanted to jot my thoughts down about the conference, particularly some of the upcoming features unveiled by Taylor Otwell (the framework’s <a href="http://en.wikipedia.org/wiki/Benevolent_dictator_for_life">BDFL</a>). To clarify, I’ve never used Laravel, have no plans to do so right now and all of these features are still in active development. I just want to talk about technical and community impressions so take everything you read with a grain of salt.</p>
<h2 id="new-directory-structure">New directory structure</h2>
<p>The next big Laravel release is going to ship with less of a Rails-inspired structure (think: app/models, app/controllers, or ZF1) and will instead move to a PSR-4 structure. This looks great for 2 reasons: first, it brings the framework more in line with existing community standards (and tooling). Second, I believe this change will encourage devs to design their objects more freely, rather than try to fit everything into the pre-labeled types of objects.</p>
<p>Taylor is also shipping a plugin that will support the old directory structure seamlessly, so you can go ahead and upgrade to the other stuff without letting this change hold you back.</p>
<h2 id="autowiring">Autowiring</h2>
<p>One of the most controversial parts of Laravel are the Facades, essentially static shortcuts to objects in the DI layer. Stealing an example from the docs, you might have a controller like this:</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">PageController</span> <span class="kd">extends</span> <span class="nc">BaseController</span> <span class="p">{</span>
<span class="k">public</span> <span class="k">function</span> <span class="n">showStuff</span><span class="p">()</span>
<span class="p">{</span>
<span class="k">return</span> <span class="nc">View</span><span class="o">::</span><span class="nf">make</span><span class="p">(</span><span class="s1">'some.template'</span><span class="p">,</span> <span class="p">[]);</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>In this case, the View object is the Facade. Being static makes it convenient but harder to test and isolate. While there’s <a href="http://laravel.com/docs/facades">some interesting stuff going on behind the scenes</a> to make it somewhat testable, the new version of Laravel renders the point moot by adding autowiring IoC to more objects, like controllers. This lets us rewrite the above example to:</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">PageController</span> <span class="kd">extends</span> <span class="nc">BaseController</span> <span class="p">{</span>
<span class="k">public</span> <span class="k">function</span> <span class="n">showStuff</span><span class="p">(</span><span class="kt">View</span> <span class="nv">$view</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">return</span> <span class="nv">$view</span><span class="o">-></span><span class="nf">make</span><span class="p">(</span><span class="s1">'some.template'</span><span class="p">,</span> <span class="p">[]);</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>This seems like a small change but the effect is profound. Our dependencies are clearer and we can mock them very easily. This new feature preserves the ease of use, makes room for better OO, and does it without breaking BC. Nice.</p>
<p>I’m not a huge fan of autowiring IoC myself but considering the tradeoffs, I think this is a great change. In fact, I’d go far as to say this is the killer feature for the next version and would highly recommend Laravel devs upgrade just to get access to this (when it’s deemed stable, of course).</p>
<h2 id="custom-requests">Custom Requests</h2>
<p>The most interesting feature was the new customs Request classes. Essentially, this let you create typed HTTP requests with custom validation and authorization rules that run before allowing access to the controller.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">UserController</span> <span class="kd">extends</span> <span class="nc">BaseController</span> <span class="p">{</span>
<span class="k">public</span> <span class="k">function</span> <span class="n">createUser</span><span class="p">(</span><span class="kt">CreateUserRequest</span> <span class="nv">$request</span><span class="p">)</span>
<span class="p">{</span>
<span class="c1">// do stuff</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>In the example above, if the HTTP request is a POST, the $request is already prefilled and validated before ever reaching the controller, cleaning up the code a bit. The custom Request classes can be generated with an artisan command to save some boilerplate setup.</p>
<p>Once you see it in action, it’s pretty clear this is an integrated Command Bus, which is pretty fascinating. If you know me, I’m bonkers about command bus service layers and this is the first time I’ve seen a framework take an opinionated stance in that direction so I consider this a plus.</p>
<p>At the same time, there were unresolved questions about this feature to me. Can I easily reuse this in CLI scripts to trigger the same actions? How extensive is the coupling to Laravel’s auth and validation libraries? Isn’t there a lot of state flying around with request method dependent behavior? Shawn McCool had some interesting ideas about this so I’m reserving judgement until I see the final feature.</p>
<p>Regardless, I can’t help but feel it’s a really cool to see a framework take a step like this, even if I have quibbles about implementation. Again, this seems like a measured tradeoff between ease-of-use and best practices.</p>
<h2 id="contracts">Contracts</h2>
<p>One of the coolest things at the entire conference was the upcoming Illuminate\Contracts repo, which is a repository of only key Laravel interfaces. This opens the door to a lot of standalone implementations and hopefully better architecture overall. This is something I’m 100% behind and hope to see more frameworks do in the future.</p>
<p>One of the new interfaces demoed was a Filesystem, with the first adapter backed by the <a href="https://github.com/thephpleague/flysystem">Flysystem library</a>. I think this is also fantastic for several reasons: OO filesystem access makes testing and decoration easier, Flysystem is a great library that deserves more attention and finally, this might help <a href="https://twitter.com/frankdejonge">Frank de Jonge</a> eventually become more famous than <a href="https://twitter.com/ssx">Scott Wilcox</a>.</p>
<h2 id="socialize">Socialize</h2>
<p>This is a new social login library that’s coming with the next version. The version demoed used a static facade which I thought was unfortunate, but the functionality looked great. The application had a github backed login with literally less than 10 lines of code.</p>
<h2 id="wrapup">Wrapup</h2>
<p>Looking at the decisions Laravel is making, I feel it’s moving in a good direction, while preserving a preference for <a href="http://thinkrelevance.com/blog/2013/04/04/abstraction-or-leverage">leverage over abstraction</a>. And you know what? That’s okay.</p>
<p>Generally, the audience felt open and willing to discuss challenging subjects. Topics like TDD and service layers were regularly discussed in the halls and I wish I’d had more time to mingle and meet folks. The level was mixed but folks were hungry to learn more. It wasn’t perfect, there were some awkward moments and not everyone was on board with everything. Nonetheless, there was definitely a feeling of going forward.</p>
<p>I’d like to give a shout out to some of the newer speakers like <a href="https://twitter.com/kayladnls">Kayla Daniels</a> for an amazing first talk fighting the good fight, <a href="https://twitter.com/erikaheidi">Erika Heidi</a> the most improved speaker every time I see her, the fine speaker and gentleman <a href="https://twitter.com/kirkbushell">Kirk Bushell</a> and <a href="https://twitter.com/stauffermatt">Matt Stauffer</a> whose delivery will likely give me a run for my money soon.</p>
<p>I want to compliment the organizers for putting on a great conference. They’re friends of mine, so I have an obvious bias, but I thought everything from the food to the schedule to the venue was great.</p>
<p>There are some other possible reasons for this positive impression, it’s no secret my step up from dark horse speaker to closing keynote garnered me a lot of love. Still, I’d like to believe it’s because the Laravel community is starting to shed its reputation as a framework for beginners and making moves to stand as a valued member of the wider community; something should all welcome.</p>Ross TuckHaving spent the previous weekend at LaraconEU, I wanted to jot my thoughts down about the conference, particularly some of the upcoming features unveiled by Taylor Otwell (the framework’s BDFL). To clarify, I’ve never used Laravel, have no plans to do so right now and all of these features are still in active development. I just want to talk about technical and community impressions so take everything you read with a grain of salt.