text: <![CDATA[David Boike]]> 2017-03-17T15:47:54+00:00 <![CDATA[David Boike]]> Octopress <![CDATA[Introduction to NServiceBus]]> 2017-03-17T00:00:00+00:00 <div style="float:right;margin:1em;"> <img src="/images/learning-nservicebus-cover-small.png" style="width:175px;height:213px;vertical-align:text-top;" /> <img src="/images/learning-nservicebus-2ndEd.jpg" style="border:solid 1px #999;width:162px;height:200px;vertical-align:text-top;box-shadow:6px 6px 5px #ddd" /> </div> <p>If you’re looking at my blog right now (hint: you are) then you might already know that I am the author of <a href=""><em>Learning NServiceBus</em></a> which focused on NServiceBus 4, and <a href=""><em>Learning NServiceBus - Second Edition</em></a> which focused on NServiceBus 5.</p> <p>Now NServiceBus 6 has been released, and with the change to a fully async API, quite a bit has changed. In fact, enough has changed that if you tried to use my latest book, which is called <em>Learning NServiceBus</em>, to actually, you know, <em>learn NServiceBus</em>, it might not be the greatest experience in the world.</p> <p>The problem is, writing books sucks. A lot. So I’m not doing that anymore.</p> <!-- more --> <h2 id="whats-wrong-with-books">What’s wrong with books?</h2> <p <em>just to make sure there were actually words in it</em>, and then I closed it and put every single copy on my bookshelf.</p> <p>I seriously did not want to look at those words one more time. I stopped.</p> <p.</p> <p>Just a bit over a year after I published, NServiceBus 5 was released, making my book <em>completely wrong</em>. I figured that, at the very least, updating the book to a new major version would require much less effort than went into the first version.</p> <p.</p> <p>And here we are again. Now that NServiceBus 6 has been released, the second book is also completely wrong. Putting words to <em>actual paper</em> is just no good way to actually educate people how to use a software product that’s changing and evolving.</p> <p>So now that I have the advantage of working direclty for the <a href="">makers of NServiceBus</a>, we’ve decided to go in a bit of a different direction. I’ve been working on a new <a href="">Introduction to NServiceBus</a> tutorial, hosted within our documentation site. That means we’ll be able to keep the tutorial up-to-date and relevant using the same tech we use for our documentation and samples, in a way a paper book could never hope to accomplish.</p> <h2 id="the-new-tutorial">The new tutorial</h2> <p.</p> <p.</p> <p>When complete, the system you build will look something like this:</p> <p><a href=""><img src="/images/intro-to-nsb-tutorial-diagram.svg" style="border:solid 1px #ccc;padding:1em;" /></a></p> <p>Sound interesting? If so, give the <a href=""><strong>Introduction to NServiceBus</strong></a> tutorial a try, and then ping me on Twitter <a href="">@DavidBoike</a> to let me know what you think.</p> <p!</p> <img src="" height="1" width="1" alt=""/> <![CDATA[The code isn't everything]]> 2017-02-25T00:00:00+00:00 <p>Since I work from home, I make it a point to go out for lunch at least once per week. It helps to keep me from going a bit nuts staying in the house all day, especially during cold, snowy Minnesota winters.</p> <p … <a href="/2010/05/qr-codes-the-lamest-thing-to-never-reach-critical-mass/">not exactly a fan of QR codes</a>, but this seems like a pretty good use for them. I had never seen their system in action so I decided to check it out.</p> <p>So after placing my order, I ask the employee at the register if he can scan the QR code in the app, and he looked at me like I was born on Mars.</p> <!-- more --> <p>I looked around the restaurant. On every table, there’s a table tent advertising the new app. There’s a giant, backlit poster right next to the ordering counter advertising the new app. This is clearly a pretty big push for them.</p> <p><em>But he had no idea what I was talking about.</em></p> <p.</p> <p>Well that didn’t work either. Even though the barcode was printed on the receipt very clearly, the app refused to scan it. I had to enter the numeric code below the barcode manually.</p> <p>This got me thinking about the things people – <em>especially software developers</em> – completely forget about in software projects.</p> <p.</p> <p.</p> <p>So just remember, the code isn’t everything.</p> <img src="" height="1" width="1" alt=""/> <![CDATA[Inbox Few - How I wrangle my email]]> 2017-01-31T00:00:00+00:00 <p>I used to be a practitioner of Inbox Infinite. The incoming messages would just land at the top of my inbox, and as I scrolled down, the date of the email would slowly get closer and closer to the date when I originally opened my Gmail account.</p> <p>Let’s just say I could scroll down a long damn way.</p> <p>My primary method of determining if something was <em>handled</em> was whether or not it was read. If I needed to look at it later, mark it as unread. It worked out alright, as a software developer I didn’t get that much email to start with, and work generally happened only during work hours.</p> <p>When I joined <a href="">Particular Software</a> it became quickly apparent that how I managed my email was going to have to change.</p> <!-- more --> <p>Particular Software is a 100% dispersed organization with no “home office.” We have people in North America, Europe, and Australia. The sun never goes down on us, and so throughout most of the week, during every hour of the day, someone <em>somewhere</em> is working.</p> <p>We also do all our work in GitHub, from work on code in our public repositories, right down to discussing changes to our parental leave policy.</p> <p>This results in <em>lots of notification emails</em>. The problem isn’t just dealing with them in my inbox. I also need to curtail the sheer amount of them that are archived so that I have a remote chance of finding anything <em>else</em> in my email.</p> <p>So here’s the system I’ve come up with to wrangle my email. I’m not necessarily saying it will work for you, but I’ve found it works for me.</p> <h2 id="basic-setup-and-filters">Basic setup and filters</h2> <p>I like to use a native Mail client, not the Gmail web interface, especially since I prefer to blend my personal and work email together into one experience. I actually really like Apple’s built-in Mail app when I’m on my MacBook Pro.</p> <p>So the first thing I had to turn off is Gmail’s tabbed email system that separates Social/Promotions/Updates/Forums content into different tabs in the Gmail web interface, because it doesn’t do any good from a native client.</p> <p>Instead, I set up filters to map this kind of stuff to labels/folders in Gmail. You can take advantage of Gmail’s intelligence to identify these messages and direct them where you want.</p> <p>Using the searches <code class="highlighter-rouge">category:social</code> and <code class="highlighter-rouge">category:promotions</code>, you can create Gmail filters to move these to separate labels, skip the inbox, and never mark it as important. I direct these to labels called <strong>Notifications</strong> and <strong>Notify</strong>, and this cleans up an amazing amount of what would otherwise land in my Inbox.</p> <p>I frequently skim these folders once per day, and mark them read en masse.</p> <p>I also have another Gmail filter for advertising that somehow makes it through Gmail’s algorithms. The search is along the lines of <code class="highlighter-rouge">from:(A OR B OR C OR ...)</code> and I add to it as necessary. Honestly though, I can’t remember the last time I amended that filter. Gmail seems to be really good at that.</p> <p>Lastly, I have a filter for <code class="highlighter-rouge">from:notifications@github.com</code> that applies a <strong>GitHub</strong> label, but here I do <em>not skip the Inbox</em>. More on this later.</p> <h2 id="inbox-few">Inbox Few</h2> <p>It didn’t take long after joining Particular to realize that using Read/Unread status on a message to keep track of what I needed to do with it would not work. I just get too many GitHub notifications.</p> <p.</p> <p>I tried Inbox Zero, but found it impossible to get to zero. I’m not sure if that would even be a good thing. If I didn’t have anything to do in my persistent queue, that might be bad for job security?</p> <p.</p> .</p> <p>Once I get down to roughly this scale, what’s left can fit in my head and I can start to make better value judgments about what Big Ticket task is truly worth my time and then start on that. Usually I’ll also take a scan of the <a href="">GitHub issues assigned to me</a> and take that into consideration.</p> <p <a href="">Slack’s reminder feature</a> to point me back to a specific issue URL at some time in the future.</p> <p.</p> <h2 id="cleaning-up-cruft">Cleaning up cruft</h2> <p.</p> <p.</p> <p>To deal with this, I use a <a href="">Google Apps Script</a> to delete email conversations out of Gmail after a certain period.</p> <p>These scripts are really easy to make. They are stored in Google Drive, so you just go to the link above and click the <strong>Start Scripting</strong> button. Save it in a Drive folder and you can set it up to run once per night without having to hassle with a crontab or anything.</p> <p>Here’s my script that archives messages with the <em>Notify</em> and <em>Advertising</em> labels after 30 days, which is plenty long enough to retrieve a coupon the day my wife wants to go shopping. It also archives messages in the <strong>GitHub</strong> label (remember that from earlier?) after 180 days.</p> <div class="highlighter-rouge"><pre class="highlight"><code); } </code></pre> </div> <p>Through the clock-ish icon in the script editor, you can schedule this script to run the <code class="highlighter-rouge">main</code> <em>many</em> times to get through all the junk in my previous Inbox Infinite.</p> <p.</p> <h2 id="summary">Summary</h2> <p.</p> <p>Some have suggested I use Google Inbox instead of all this, especially because the “Snooze” feature might help with the problem of getting a message out of the way but coming back to it later, whether or not anyone has replied.</p> <p <a href="">Boxy</a>.</p> <p>Basically, what I’ve got now seems to be working out fine. Why would I mess with that?</p> <img src="" height="1" width="1" alt=""/> <![CDATA[How to build Gmail's "Undo Send" feature]]> 2015-06-30T00:00:00+00:00 <p>The other day I read this article about how Gmail will <a href="">finally let you “Undo Send” emails you wish you didn’t send</a>.</p> <p>Really Google? <em>Really?</em> What took you so long? I mean, I know you’ve been very busy shuttering Google Reader and all that, but offering the ability to undo sending an email within 30 seconds is actually pretty easy to build.</p> <p>At least, it is with <a href="">NServiceBus</a>, and specifically, using an NServiceBus <a href="">Saga</a>. I’ll show you how.</p> <p>“Undo Send” is really just a specific case of a much more general pattern I’ll call the buyer’s remorse pattern.</p> <!-- more --> <h2 id="buyers-remorse-pattern">Buyer’s remorse pattern</h2> <p><a href="">In real life</a>, we might get buyer’s remorse when we buy an expensive car and then realize just how long we’re going to have to make expensive payments on it. In software, we’re not talking about a purchase - we’re really referring to any action that cannot be easily undone. Sending emails fall squarely within this category of problems, along with charging credit cards, which can cause <em>real</em> buyer’s remorse.</p> <p>Using the buyer’s remorse pattern simply means that instead of immediately sending the email, the software will wait a certain amount of time first, in case the user thinks better about what they just did and wants to back out.</p> <p>The time delay is the tricky part of implementing buyer’s remorse, but with NServiceBus, it becomes easy.</p> <h2 id="step-by-step">Step-by-step</h2> <p>I won’t cover how to do buyer’s remorse in your UI. I would assume your user would click the Send button, and then you’d display an alert bar saying “Your message has been sent. (Click to undo)”. For the sake of this example, let’s assume this is a single-page application, and both the “Send” button and “Click to undo” would fire a request to a REST API that could send NServiceBus commands to a back-end service.</p> <h3 id="message-definitions">Message definitions</h3> <p>Here’s what the commands would look like:</p> <div class="highlighter-rouge"><pre class="highlight"><code>public class SendEmail : ICommand { public Guid MessageId { get; set; } public EmailDetails MessageDetails { get; set; } } public class UndoSendEmail : ICommand { public Guid MessageId { get; set; } } </code></pre> </div> <p>The <code class="highlighter-rouge">MessageId</code> is just a <code class="highlighter-rouge">Guid</code> that serves as a unique identifier for the message being sent. That way when we “send” the message, and then subsequently “undo send”, we know we’re talking about the same message.</p> <p>I’ll leave the <code class="highlighter-rouge">EmailDetails</code> class up to you. Actually, that’s the <em>real</em> hard part about sending an email. Classes like <a href=""><code class="highlighter-rouge">System.Net.MailMessage</code></a> and <a href=""><code class="highlighter-rouge">System.Net.MailAddress</code></a> are chock full of get-only properties and other gross stuff that don’t make them good candidates to include in messages, plus they probably contain way more information than you really need for your use case anyway. So just create your own containing only get/set properties for the details you need.</p> <p>We’re also going to need a class to represent the timeout message. This is far from complex:</p> <div class="highlighter-rouge"><pre class="highlight"><code>public class UndoSendTimeout { } </code></pre> </div> <h3 id="basic-saga-structure">Basic saga structure</h3> <p>We start with the scaffolding of an NServiceBus Saga that handles these messages. An NServiceBus Saga is really just a collection of message handling methods that store some shared state in a database between messages.<) { // TODO } public void Handle(UndoSendEmail message) { // TODO } public void Timeout(UndoSendTimeout state) { // TODO } </code></pre> </div> <p>For the moment, let’s ignore <code class="highlighter-rouge">UndoSendPolicyData</code>, the class that represents the state stored in the database between messages.</p> <p>You may find it odd that both the <code class="highlighter-rouge">SendEmail</code> command and the <code class="highlighter-rouge">UndoSendEmail</code> command are both implemented as <code class="highlighter-rouge">IAmStartedByMessages<TMessage></code> rather than the alternative <code class="highlighter-rouge">IHandleMessages<TMessage></code>, when clearly if the <code class="highlighter-rouge">UndoSendEmail</code> occurs, it will happen later in time. It’s important to remember that in an eventually consistent, asynchronous system, it’s possible that <code class="highlighter-rouge">SendEmail</code> could be delayed for some reason and <code class="highlighter-rouge">UndoSendEmail</code> might actually arrive first!</p> <p>Because of this possibility, it’s best to use <code class="highlighter-rouge">IHandleMessages<TMessage></code> <em>only for messages sent by the Saga itself!</em></p> <p>The last thing to look at is the <code class="highlighter-rouge">ConfigureHowToFindSaga</code> method, which teaches the persistence how to look for saga data for each incoming message. For both message types, this is saying “Find a property in the message called <code class="highlighter-rouge">MessageId</code>, and try to match that up to some saga data in the database with a matching <code class="highlighter-rouge">MessageId</code>.” If none is found, and the message is an <code class="highlighter-rouge">IAmStartedByMessages<TMessage></code> then the Saga will create new data for us.</p> <p>Now let’s get back to the <code class="highlighter-rouge">UndoSendPolicyData</code> class that will store our saga data for us while we’re waiting for the timeout period.</p> <div class="highlighter-rouge"><pre class="highlight"><code>public class UndoSendPolicyData : ContainSagaData { public Guid MessageId { get; set; } public EmailDetails MessageDetails { get; set; } public bool UndoSend { get; set; } } </code></pre> </div> <p>We store the <code class="highlighter-rouge">MessageId</code>, so that our saga-finding mapper can match it up later. We also store the message details received from the <code class="highlighter-rouge">SendEmail</code> command. Lastly, an <code class="highlighter-rouge">UndoSend</code> indicator lets us know if an <code class="highlighter-rouge">UndoSendEmail</code> command has been received.</p> <h3 id="message-handlers">Message handlers</h3> <p>Now let’s start to implement our message handlers, starting with the handler for the <code class="highlighter-rouge">SendEmail</code> command:</p> <div class="highlighter-rouge"><pre class="highlight"><code>public void Handle(SendEmail message) { this.Data.MessageId = message.MessageId; this.Data.MessageDetails = message.MessageDetails; this.RequestTimeout<UndoSendTimeout>(TimeSpan.FromSeconds(30)); } </code></pre> </div> <p>When the Saga receives its very first message, the saga data (in <code class="highlighter-rouge">this.Data</code>) will be uninitialized, so it’s very important to fill it with information from the incoming command. We don’t actually want to send the email yet, so we request a timeout from the Saga infrastructure so that we can get a <code class="highlighter-rouge">UndoSendTimeout</code> reminder in 30 seconds.</p> <p>Next, let’s handle the <code class="highlighter-rouge">UndoSendEmail</code> command:</p> <div class="highlighter-rouge"><pre class="highlight"><code>public void Handle(UndoSendEmail message) { this.Data.MessageId = message.MessageId; this.Data.UndoSend = true; } </code></pre> </div> <p>We don’t actually <em>do</em> much of anything here either. We still initialize the <code class="highlighter-rouge">MessageId</code> property, because remember that it’s possible for <code class="highlighter-rouge">UndoSendEmail</code> to arrive first, meaning the saga data could be uninitialized for this handler as well.</p> <p>Lastly, we implement the handler for the <code class="highlighter-rouge">UndoSendTimeout</code> message:</p> <div class="highlighter-rouge"><pre class="highlight"><code>public void Timeout(UndoSendTimeout state) { if (this.Data.UndoSend == false) { SendEmail(this.Data.MessageDetails); } this.MarkAsComplete(); } </code></pre> </div> <p>If we haven’t cancelled the send, then we call a method that will build the <code class="highlighter-rouge">MailMessage</code> from our message details and dispatch it to the SMTP server. Then, in either case, we call <code class="highlighter-rouge">MarkAsComplete()</code>, which will remove the saga data from the database. If the Saga did receive an <code class="highlighter-rouge">UndoSendEmail</code> command then the message just goes away, no harm, no foul.</p> <p>So remember that the messages could arrive in any order. This means that one of the following will happen:</p> <ol> <li><code class="highlighter-rouge">SendEmail</code> arrives, and the user does not undo, so the email is sent 30 seconds later.</li> <li><code class="highlighter-rouge">SendEmail</code> arrives, and the <code class="highlighter-rouge">UndoSendEmail</code> command arrives a bit later, so when the timeout fires, the email is not sent.</li> <li><code class="highlighter-rouge">SendEmail</code> is delayed and <code class="highlighter-rouge">UndoSendEmail</code> arrives first. The saga data is created with <code class="highlighter-rouge">UndoSend == true</code>. When <code class="highlighter-rouge">SendEmail</code> arrives, it dutifully requests the timeout. 30 seconds later, the timeout is received, and because <code class="highlighter-rouge">UndoSend</code> is set, the email is not sent.</li> <li><code class="highlighter-rouge">SendEmail</code> arrives, and the user stares at their screen for 29 seconds, then finally sends <code class="highlighter-rouge">UndoSendEmail</code> too late. The timeout fires, sends the email, and removes the saga data. Finally, the <code class="highlighter-rouge">UndoSendEmail</code> arrives, and because it is also an <code class="highlighter-rouge">IAmStartedBy<T></code> message, it recreates the saga data! Oops!</li> </ol> <p>Scenario #4 isn’t really what we had in mind, but it illustrates that we always need to consider what will happen if messages arrive out of their expected order. There are a lot of ways to handle this, including an additional timeout to delay cleaning up the saga for a much longer period (perhaps 24 hours), or a timestamp added to the <code class="highlighter-rouge">UndoSendEmail</code> command so that it could be effectively ignored if old enough. I’ll leave implementing one of those as an exercise for the reader.</p> <h2 id="full-code">Full code</h2> <p>Here is the full code for the <code class="highlighter-rouge">UndoSendPolicy</code> saga, for those who prefer to see everything at once:<) { this.Data.MessageId = message.MessageId; this.Data.MessageDetails = message.MessageDetails; this.RequestTimeout<UndoSendTimeout>(TimeSpan.FromSeconds(30)); } public void Handle(UndoSendEmail message) { this.Data.MessageId = message.MessageId; this.Data.UndoSend = true; } public void Timeout(UndoSendTimeout state) { if (this.Data.UndoSend == false) { SendEmail(this.Data.MessageDetails); } this.MarkAsComplete(); } private void SendEmail(EmailDetails email) { // Dispatch the message to the SMTP server } } public class UndoSendPolicyData : ContainSagaData { public Guid MessageId { get; set; } public EmailDetails MessageDetails { get; set; } public bool UndoSend { get; set; } } public class SendEmail : ICommand { public Guid MessageId { get; set; } public EmailDetails MessageDetails { get; set; } } public class UndoSendEmail : ICommand { public Guid MessageId { get; set; } } public class EmailDetails { // Up to you - create what you need for your use case } public class UndoSendTimeout { } </code></pre> </div> <h2 id="summary">Summary</h2> <p>Buyer’s remorse is a pattern to deal with operations that otherwise cannot be undone by delaying them for a short time while waiting for cancellation. With it we can implement Google’s Undo Send feature, but there are many more uses for it.</p> <p>Credit card charges are technically reversible, although doing so is messy, as it requires a charge reversal that would appear on the customer’s statement. It’s a lot cleaner to prevent the credit card from having ever been charged by introducing the time delay with the buyer’s remorse pattern.</p> <p>In fact, with e-commerce use cases, the buyer’s remorse pattern can get a little more interesting. It should always be possible to cancel an order. Just after the order, we can use the buyer’s remorse pattern to prevent accidental orders. After the credit card is charged and before products are shipped, we should be able to cancel the order and refund the payment. Even after products are shipped, we should be able to cancel the order, and provide a refund (perhaps partial) provided that the items are returned.</p> <p>All of these are great applications for sagas, which give you the ability to model business requirements together with the passage of time. Buyer’s remorse is just a start.</p> <img src="" height="1" width="1" alt=""/> <![CDATA[Goodbye WordPress, Hello Jekyll]]> 2015-05-21T00:00:00+00:00 <p>WordPress and I had an altercation the other day.</p> <p>I logged in to the management interface for my blog, and it was begging me to update to WordPress 4.2.2, and given the <a href="">number of security vulnerabilities</a> that have been in the news lately, I figured that was probably a good idea.</p> <p.</p> <p>Luckily, I got everything working on Version 4.2.2, but I resolved at that point that 4.2.2 would be my last.</p> <p>It’s not that I’m a huge WordPress hater. When it works it works well enough. But I absolutely disdain PHP, kind of like <a href="">this guy</a>, <em>really</em> want to the particular webhost I’m using <a href="">because</a> <a href="">reasons</a>, and moving my blog is a great first step.</p> <p>I recently joined <a href="">Particular Software</a> and we do everything on <a href="">GitHub</a>. No really, I mean <em>everything</em>. (Well OK, GitHub and <a href="">Slack</a>.) And while I’m no slouch at HTML when I really want to write, nothing beats Markdown. So it makes sense to take advantage of that.</p> <p>So, if you’re reading this post, my blog is now run by <a href="">Jekyll</a> on <a href="">GitHub Pages</a>. How does that work? Glad you asked.</p> <ol> <li>Create a new GitHub repository called <em>your-github-username</em>.github.io - mine is <a href="">davidboike.github.io</a>.</li> <li>Create a Jekyll repository. (This is the tricky part.)</li> <li>Write your posts as Markdown files.</li> <li>Push your changes to GitHub.</li> <li>GitHub compiles your posts from your master branch into HTML pages serves it up as static content.</li> </ol> <p>Rather than do a whole bunch of work on #2, I decided to stand on the shoulders of <a href="">Phil Haack</a> whose <a href="">blog post on converting his own blog</a> had originally informed me Jekyll, and <del>take inspiration from</del> outright steal his Jekyll repository as a starting point. Luckily, <a href="">he’s OK with that</a>. I did make some changes to make it my own.</p> <p>The trickiest part turned out to be porting my content. There is a <a href="">WordPress to Jekyll converter</a> but it goes pretty crazy on you, and doesn’t convert the WordPress HTML to Markdown. So I had to do a lot of work on my own to <a href="">convert the HTML to Markdown with Pandoc</a> and then clean up a lot of the mess afterwards.</p> <p!</p> <p>Hopefully this will make it even easier for me to blog in the future.</p> <img src="" height="1" width="1" alt=""/> <![CDATA[Joining Particular Software]]> 2015-04-30T15:32:05+00:00 <p>For the last few years, I have tried to arrange my career around the following two principles:</p> <ol> <li>Surround myself with the smartest people I can find.</li> <li>Be prepared to do the thing that scares me a little bit.</li> </ol> <p>And it’s been working great. This led me to leave a full-time SaaS company to join <a href="">ILM Professional Services</a>.</p> <p>I really can’t say enough good things about ILM. If you’re a software developer in the Minneapolis/St. Paul area, you love to code, and you have a thirst for knowledge, you should check them out. Tell them David sent you.</p> <p>These principles of mine also led me to write my book, <a href="">Learning NServiceBus</a>,.</p> <p>And that has all led to this moment.</p> <p>It’s sad to have to leave ILM, because they have become a family to me, but I am very excited to be joining <a href="">Particular Software</a> full-time on May 4. (That’s right, <a href="">May the Fourth</a>!) It’s pretty difficult to find someone smarter than Udi Dahan, and it will be a privilege to work for him. Add in all the other extremely smart and talented people in the company, and I just hope that I’ll be able to keep up.</p> <p>When I first moved away from home to go to college, my father told me, “Well son, this is going to be quite the adventure.” Well, the adventure continues, and I’m excited to get started.</p> <img src="" height="1" width="1" alt=""/> <![CDATA[Learning NServiceBus Second Edition]]> 2015-02-02T18:23:56+00:00 <p>I’m excited to say that the second edition of my book, <a href="">Learning NServiceBus</a>, has now been published!</p> <p><a href=""><img src="/images/learning-nservicebus-2ndEd.jpg" alt="Learning NServiceBus Second Edition" /></a></p> <p>The second edition of the book includes the following improvements over the first edition:</p> <ul> <li>Completely updated to cover NServiceBus 5.0</li> <li>All-new chapter on the Service Platform (ServiceControl, ServiceInsight, ServicePulse, and ServiceMatrix)</li> <li>More diagrams (these were unfortunately sparse in the first edition)</li> <li>Coverage of V5-specific features (Pipeline, Outbox)</li> <li>Revised and expanded…everything</li> </ul> <p>All told, there are <a href="">roughly 44 additional pages</a> (over the first edition) of just raw new content.</p> <p>And perhaps best of all, the new edition includes a foreward from <a href="">Udi Dahan</a>.</p> <p>Also, as always, so many thanks to everyone at Particular Software who were very helpful during the development of the book, and to my tech reviewers <a href="">Daniel Marbach</a>, <a href="">Hadi Eskandari</a>, <a href="">Roy Cornelissen</a>, and <a href="">Prashant Brall</a>, who made sure that you have the best content in your hands possible.</p> <p>The book is <a href="">available for purchase right now</a> from the publisher in physical and eBook forms, and will be available via other channels (Amazon, Barnes & Noble, Safari Books Online, etc.) shortly. I hope of course that you buy it, but more importantly, that you find it useful.</p> <img src="" height="1" width="1" alt=""/> <![CDATA[My Next Endeavor: Teaching]]> 2014-12-16T14:26:32+00:00 <div style="float:right;width:200px;margin:1em;"> <img src="/images/teaching..-300x217.png" /> </div> <p>Uncle Bob Martin is one of the true learned elders of our industry, one of those who signed the <a href="">Agile Manifesto</a> when I was still taking college courses. Recently, he <a href="">wrote about</a> (and <a href="">has talked about</a>) something that absolutely blew me away.</p> <p <strong>doubles every five years</strong>.</p> <p>This was not altogether unsurprising to me, until he pointed out that this means if the number of developers is doubling every five years, then at any given point in time <strong>half of all software developers on the planet have less than five years of experience</strong>.</p> <p><em>Woah.</em></p> <p>Half of ALL software developers are fairly junior developers without a lot of experience under their belt. So to really help advance the field of software development, we should be finding better ways to train those scores of junior developers joining our ranks each and every year.</p> <p>Luckily, I’ve been given the opportunity to do something about that.</p> <p>This January, I won’t be going to code up some website for a new client. As part of a partnership between <a href="">ILM</a>, <a href="">The Learning House</a>, the <a href="">Software Craftsmanship Guild</a>, and <a href="">Concordia University</a>, I will be serving as an Adjunct Professor at Concordia teaching the .NET track of the <a href="">Coding Bootcamp</a>, an intensive 12-week course designed to take a student with an aptitude for computers and turn them into a well-trained junior developer ready to write code in the real world.</p> <p.</p> <p>This is why I’m so excited about the <a href="">Coding Bootcamp curriculum</a>. .</p> <p.</p> <div style="float:right;width:240px;margin:1em;"> <img src="/images/applesoft.jpg" /> </div> <p>I don’t remember a lot about my early days in elementary school, but I do remember that my fourth grade teacher Mrs. Dickerson gave me a book about programming in AppleSoft BASIC <sup><a href="#footnote-1">1</a></sup> that I read cover to cover. (The book pictured <em>may</em>.</p> <p.</p> <p>If you would like to attend the Coding Bootcamp you can apply at <a href="">bootcamp.csp.edu</a>.</p> <p>Or, if you are looking for talented new developers, you can <a href="">join the employer network</a>.</p> <ol> <li>In yet another example of <a href="">Atwood’s Law</a>, <a href="">AppleSoft BASIC now runs in JavaScript</a>.</li> </ol> <img src="" height="1" width="1" alt=""/> <![CDATA[Wrapping a jQuery plugin in an AngularJS directive (Screencast)]]> 2014-06-16T05:00:43+00:00 <p>Recently I saw Evil Trout’s screencast <a href="">Wrapping a jQuery plugin in an Ember.js component</a>, and thought that it would be really valuable to show the exact same plugin implemented instead as an AngularJS directive.</p> <p>I want to be clear that I don’t intend to start some sort of Angular vs. Ember flame war. I happen to believe, as Ben Lesh concludes in his <a href="">excellent 6-part blog series comparing the two frameworks</a>, that Angular and Ember are two paths up the same mountain, and that together they are pushing the state of web development forward.</p> <p>It’s clear that I need better audio equipment if I intend to keep doing screencasts, but I think it’s passable. I hope you enjoy it!</p> <!-- more --> <div style="text-align: center; margin: 1em 0;"><iframe src="//" width="560" height="315" frameborder="0" allowfullscreen="allowfullscreen"></iframe></div> <img src="" height="1" width="1" alt=""/> <![CDATA[NServiceBus and the Mystery of IWantCustomInitialization]]> 2014-05-28T04:12:34+00:00 <p>Recently <a href="">Romiko Derbynew</a> was reading my book, <a href="">Learning NServiceBus</a>, and noticed a contradiction between the manuscript and the included source code:</p> <blockquote> <p>In the Sample for DependecyInjection in the book, the code is:</p> <p>public class ConfigureDependencyInjection : NServiceBus.<strong>IWantCustomInitialization</strong></p> <p>However in the book, is says</p> <p>IWantCustomInitialization should be implemented <strong>only on the class</strong> that implements <strong>IConfigureThisEndpoint</strong> and allows you to perform customizations that are unique to that endpoint.</p> </blockquote> <p <a href="">#FAIL</a>!</p> <p>So here’s the real scoop, or at least, updated information as I see it and would recommend now, circa NServiceBus 4.6.1.</p> <!-- more --> .</p> <p.)</p> <p>Unfortunately, it isn’t that easy.</p> <p>(The following bit of explanation references history that exists mainly in my mind and, therefore, may not be entirely accurate as I’m not willing to dig through years of Git history to prove it. I might get a detail or two wrong, but stay with me.)</p> .</p> <p>So in this before-time of long-long-ago, these two interfaces only worked when applied to the EndpointConfig (the class that implements IConfigureThisEndpoint) but the new ones can be on any class, and there can be multiple ones.</p> <p>Except as it turns out, IWantCustomInitialization pulls double-duty. It will execute either on the EndpointConfig OR as a standalone class, but with one critical difference: <strong>Whether or not it exists on the EndpointConfig changes the order of execution with respect to the other extension point interfaces!</strong></p> <p.</p> <p>Confused yet? Here’s the definitive updated order:</p> <ol> <li>IWantCustomLogging (only executes on EndpointConfig)</li> <li>IWantCustomInitialization, implemented on EndpointConfig</li> <li>IWantToRunBeforeConfiguration</li> <li>IWantCustomInitialization, implemented on its own class</li> <li>INeedInitialization</li> <li>IWantToRunBeforeConfigurationIsFinalized</li> <li>IWantToRunWhenConfigurationIsComplete *</li> <li>IWantToRunWhenBusStartsAndStops</li> </ol> <p><em>*.</em></p> <p>So what would I recommend about IWantCustomInitialization now?</p> <p.</p> <p>So that would make the code sample from the book <em>wrong</em>, even though it technically works. I would use INeedInitialization for that class instead.</p> <p <a href="">only place you can set up a custom DI container is from IWantCustomInitialization on the EndpointConfig</a>.</p> <p>And on a closing note, I would suggest that if you don’t get enough evidence that you are human and make mistakes by being a software developer, you should perhaps consider writing a book. ;-)</p> <img src="" height="1" width="1" alt=""/> <![CDATA[Failed Message Notification with ServiceControl]]> 2014-05-07T17:26:20+00:00 <p>In my post <a href="">Distributed System Monitoring Done Right</a>, I mentioned in passing how <a href="">ServicePulse</a> doesn’t ship with any built-in notification system for failed messages, but that you could easily build a system to send an email (or SMS, or carrier pigeon) to do so.</p> <p>In this post I’ll show you how.</p> <!-- more --> <p>First, create a new Class Project called ErrorNotify, and turn it into an endpoint by including the <a href="">NServiceBus.Host NuGet package</a>.</p> <p>Next, you need to reference the messages assembly that ServiceControl uses for its externally published events. It’s called ServiceControl.Contracts and you can find it in your ServiceControl installation directory. For me that’s located at:</p> <p>C:\Program Files (x86)\Particular Software\ServiceControl\ServiceControl.Contracts.dll</p> .</p> <p>To set the serializer to JSON, modify your EndpointConfig.cs given to you by NuGet so that it implements IWantCustomInitialization:</p> <script src=""></script> <p <a href="">ServiceInsight</a>and show you the offending message directly!</p> <script src=""></script> <p>Lastly, we need to modify the App.config file to subscribe to messages from the Particular.ServiceControl service.</p> <script src=""></script> <p>That’s it! Once we deploy this code, we will get email notifications of failures complete with links to ServiceInsight so we can go figure out exactly what went wrong.</p> <img src="" height="1" width="1" alt=""/> <![CDATA[RavenConf 2014 Slides and Video]]> 2014-04-30T15:47:32+00:00 <p>Here is the <a href="">RavenConf 2014</a> video and slides for my presentation “Modeling Tricks My Relational Database Never Taught Me” in which I compare SQL Server to Big Brother from <a href="">Apple’s 1984 ad</a> and RavenDB to the Dude from <a href="">The Big Lebowski</a>.</p> <!-- more --> <p align="center"><iframe src="//" height="315" width="560" allowfullscreen="" frameborder="0"></iframe></p> <p></p></p> <p align="center"><iframe src="" height="400" width="476" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe></p> <img src="" height="1" width="1" alt=""/> <![CDATA[Distributed System Monitoring Done Right]]> 2014-04-24T13:00:51+00:00 <p>When I first started writing <a href="">Learning NServiceBus</a>, I was targeting Version 4.0 which, at that time, was still several months away from release. Writing about something that’s still very much in flux is definitely a challenge, and to some extent I was definitely learning as I went.</p> <p>What really struck me during the writing process was how much easier people learning NServiceBus 4.0 were going to have it than I did when I learned NServiceBus 2.0. The developers at <a href="">Particular Software</a> (a name change from NServiceBus Ltd – a lot of people seem to think they were bought and this is not the case) are really obsessive about making a powerful framework as easy to use as possible, and I salute them for that.</p>  <a href="">once quoted during a live coding demo</a>, “Don’t worry I have been doing this for years. You never write this yourself; you always copy it from somewhere else.” Not exactly a glowing recommendation right?</p> <p>Then you start debugging and hope you didn’t screw anything up.</p> .</p> <p>NServiceBus 4.x is a fantastic platform to build distributed systems, but as of the <a href="">release of NServiceBus 4.0 in July 2013</a>, the big thing still missing was the ability to effectively debug a messaging system (let’s face it, gargantuan log files don’t count) and monitor a distributed system in production to make sure everything isn’t running off the rails.</p> <p>Well that’s all about to change.</p> <!-- more --> <h2 id="dont-build-your-own-monitoring-tools">Don’t Build Your Own Monitoring Tools</h2> <p!</p> .</p> <p.</p> <p <em>such a joy to work with.</em>(Sarcasm intentional.)</p> <p.</p> <p <a href="" title="Microsoft System Center Operations Manager">Microsoft SCOM<.</p> <p>What a pain! If only there was a company out there that understood how distributed systems worked that could make tools to address these issues!</p> <h2 id="the-service-platform">The Service Platform</h2> <p>The whole reason that NServiceBus Ltd. changed its name to Particular Software is that they were developing products to meet these needs, making NServiceBus itself only part of the story.</p> <p>NServiceBus is now joined by a bunch of friends:</p> <h3 id="servicecontrol">ServiceControl</h3> <p <a href="">RavenDB</a>.</p> <p.</p> <h3 id="serviceinsight">ServiceInsight</h3> .</p> <p.</p> <p>Check out the flow diagram in this screenshot.</p> <p><a href="/images/serviceinsight-flowdiagram.png"><img src="/images/serviceinsight-flowdiagram_thumb.png" alt="ServiceInsight Flow Diagram" /></a></p> <p>Notice how some of those messages have “policies” mentioned under the timestamp. Those are sagas, and show how the message flow integrates with sagas you write. This is because I’ve included the <a href="">ServiceControl.Plugin.SagaAudit NuGet Package</a> in my endpoints, which inserts itself into the pipeline to send saga auditing information to ServiceControl.</p> <p>If you click on one of those, or on the Saga tab near the bottom, you’ll get this amazing visualization showing the saga’s state changes in vivid detail, like this screenshot zoomed to show only the saga flow:</p> <p><a href="/images/serviceinsight-sagaflow.png"><img src="/images/serviceinsight-sagaflow_thumb.png" alt="ServiceInsight Saga Diagram" /></a></p> <p.</p> <h3 id="servicepulse">ServicePulse</h3> <p>Where ServiceInsight is the tool for a developer to debug a system, ServicePulse is the tool for my IT Manager and our other Ops friends to monitor our systems in production and make sure that everything is healthy.</p> <p>All you need to do is deploy the <a href="">ServiceControl.Plugin.Heartbeat NuGet package</a>.</p> <p>In addition, you can program your own custom checks to be tracked in ServicePulse. For instance, let’s say you needed to be sure a certain FTP server was up. You could program a custom check for that by including the <a href="">ServiceControl.Plugin.CustomChecks NuGet package</a> and creating a class that inherits PeriodicCheck.</p> <p>This is what ServicePulse looks like moments after I stopped debugging in Visual Studio, causing the heartbeat messages to stop.</p> <p><a href="/images/ServicePulse-Screenshot-Beta4-9.png"><img src="/images/ServicePulse-Screenshot-Beta4-9_thumb.png" alt="ServicePulse Screenshot" /></a></p> <p!</p> <p <a href="">HipChat bot</a>, and of course some will want all of the above!</p> <p>It’s convenient that ServiceControl is really just another endpoint. It has an events assembly ServiceControl.Contracts that contains events that you can subscribe to. Check out this <a href="">sample MessageFailedHandler</a> that shows how you could subscribe to the <a href="">MessageFailed</a> event and send a notification email.</p> <p>In the future there will be additional tooling to connect ServicePulse with <a href="" title="Microsoft System Center Operations Manager">Microsoft SCOM</a> and perhaps other monitoring suites as well.</p> <h3 id="servicematrix">ServiceMatrix</h3> <p>This article is mostly about system monitoring, and ServiceMatrix is really not a monitoring tool, but it deserves a mention because it is also a part of the new Service Platform suite of tools.</p> <p>ServiceMatrix is a Visual Studio plugin that makes it possible to build an NServiceBus system with graphical design tools, dragging and dropping to send messages from one endpoint to another, and that sort of thing. It really deserves an article all to itself.</p> <p.</p> <p>Aside from creation speed and baking in NServiceBus design best practices, ServiceMatrix contains two features I really feel are game-changers.</p> <p>First, whenever you debug your solution with ServiceMatrix, it will generate a debug session id that is shared with all your endpoints, and reported to ServiceControl via the <a href="">ServiceControl.Plugin.DebugSession NuGet Package</a>..</p> !</p> <h2 id="conclusion">Conclusion</h2> <p.</p> .</p> <p>But I didn’t have to.</p> <img src="" height="1" width="1" alt=""/> <![CDATA[NServiceBus Transport for RFC 1149]]> 2014-04-01T05:00:00+00:00 <p>As readers of this blog already know, <a href="">NServiceBus</a>.</p> <p><strong>But who wants that?</strong></p> <p>Honestly the developers at Particular have gone a little bit overboard with how easy they have made it to build these robust distributed systems. This is why it’s such good news that, thanks to me, there is finally an NServiceBus transport available that supports <a href="">RFC 1149: IP Datagrams over Avian Carriers</a>.</p> <p?</p> <p>And worst of all, without the system crashing down every Monday, Tuesday, and every other Thursday, your boss may start to realize he doesn’t need someone as skilled as you to run it anymore, and may replace you with a couple college interns.</p> <p>So what you need is a much less reliable transport, and that transport is <a href="">NServiceBus.Rfc1149</a>. You’re welcome.</p> <!-- more --> <p>So here’s how it works:</p> <ul> <li>Messages are stored as text files on a flash drive.</li> <li>The transport uses the first removable drive it can find with a “NServiceBus.Rfc1149” directory at the root level. It doesn’t create this for you. That would be too easy, and you’re not in this for easy.</li> <li>A directory is created for each machine name.</li> <li>Within the machine name directory, a directory is created for each queue.</li> <li>Sent messages are placed in the appropriate directory for the destination machine and queue.</li> <li>Each endpoint reads files from the appropriate queue directory.</li> <li>In order for the messages to be received by the other machines, you must remove the flash drive from the current machine, attach it to the leg of your avian carrier (a <a href="">domesticated rock pigeon, <em>Columba livia</em></a>, is recommended) and send the carrier to the physical location of the destination server. Every minute, the transport counts the messages bound for other machines and makes a recommendation for a destination server based on highest pending message count.</li> <li>If no suitable flash drive can be found, it is impossible to send outgoing messages, so sending messages will fail silently. It’s more fun that way.</li> <li>Because no messages can be sent if no flash drive is present, it’s advisable to use multiple flash drives with multiple avian carriers. We call this <em>scaling out</em>.</li> </ul> <p>Sound good? Here’s how to use it:</p> <ul> <li>Clone the <a href="">NServiceBus.Rfc1149</a> source from GitHub and build it yourself. Seriously, when it comes to development getting too easy, NuGet packages are half of the problem.</li> <li>Reference the NServiceBus.Rfc1149 assembly in your endpoints.</li> <li>Stock up on birdseed and newspaper for your avian carriers.</li> <li>Configure the RFC 1149 transport with the following:</li> </ul> <script src=""></script> <p>Then fire up your solution and enjoy the low latency and unreliability! Your job security should be ensured for years.</p> <hr /> <p><em>Yes, this is an April Fools post, but the transport really does work, after a fashion, and can be a useful exercise for understanding a little more about how NServiceBus works at its lower levels. <a href="">Check out the source code on GitHub</a>; it’s well-documented and should be instructive.</em></p> <img src="" height="1" width="1" alt=""/> <![CDATA[Speaking at RavenConf 2014]]> 2014-03-06T04:36:25+00:00 <p>I will also be giving my <strong>Modeling Tricks My Relational Database Never Taught Me</strong> talk at the first ever RavenDB conference in Raleigh, North Carolina on April 8. Click on the conference banner below for details.</p> <p><a href="" title="RavenDB 3.0 Conference and In-Depth Workshop"><img src="/images/ravenconf-2014.png" alt="RavenConf 2014" /></a></p> <img src="" height="1" width="1" alt=""/> <![CDATA[Speaking at TCDNUG on RavenDB Modeling]]> 2014-03-03T18:33:33+00:00 <p>This week I will be speaking at the Twin Cities .NET User Group:</p> <blockquote> <p><strong>Modeling Tricks My Relational Database Never Taught Me</strong> <strong>Date:</strong> Thursday, April 6, 5:30 PM <strong>Location:</strong> ILM Professional Services, 5221 Viking Drive, Edina, MN 55435</p> <p.</p> </blockquote> <p>As always, my employer ILM Professional Services will be providing the pizza at the meeting.</p> <p>TCDNUG has recently switched to using <a href="">Meetup.com</a> to register for these events, but apparently Meetup has become the <a href="">victim of a very sophisticated DDoS attack and is temporarily unavailable</a>. Seriously, who does that?</p> <p>So if you are unable to actually register, <strong>please come anyway</strong>. We would love to see you there!</p> <img src="" height="1" width="1" alt=""/> <![CDATA[Excerpt from Learning NServiceBus]]> 2013-11-13T03:34:26+00:00 <p>My publisher has allowed me to reprint my favorite part of my book, <a href="">Learning NServiceBus</a>, here on my blog. It is the introduction to Chapter 3, Preparing for Failure.</p> <p>Why is it my favorite? Chapter 3 is the chapter that deals with how to be ready for the inevitable errors that will befall a system due to the <a href="">fallacies of distributed computing</a>, stupid user tricks, and plain outright buggy code. This is the part of NServiceBus that <a href="">really grabbed me in the beginning</a> and has never let go.</p> <p>Plus, and I can’t stress this point enough, <strong><em>this is the part of the book about Batman</em></strong>.</p> <!-- more --> <blockquote> <p>Alfred: Why do we fall sir? So that we can learn to pick ourselves up. Bruce: You still haven’t given up on me? Alfred: Never.</p> <p>-Batman Begins (Warner Bros., 2005)</p> <p.</p> <p.</p> <p>It is at this moment of failure that Alfred insists he will never give up on Bruce. I don’t want to spoil the movie if, by chance, you haven’t seen it, but let’s just say some bad guys get what’s coming to them.</p> <p.</p> <p>Software fails. Software engineering is an imperfect discipline, and despite our best efforts, errors will happen. Some of us have surely felt like Bruce, when an unexpected error makes it seem as if the software we built is turning to so much ash around us.</p> <p>But like Alfred, NServiceBus will not give up. If we apply the tools that NServiceBus gives us, even in the face of failure, we will not lose consistency, we will not lose data, we can correct the error, and we will make it through.</p> <p>And then the bad guys will get what’s coming to them.</p> <p>In this chapter we will explore the tools that NServiceBus gives us to stare failure in the face and laugh.</p> </blockquote> <p>In the rest of the chapter, you learn about NServiceBus message handlers’ fault tolerance, error queues and replay, automatic and second-level retries, express and expiring messages, message auditing, and integration with web services.</p> <p>If you’d like to read more, you can <a href="">download a preview of Chapter 1</a> from Packt, or buy the book from <a href="">Packt</a>, <a href="">Amazon</a>, <a href="">Amazon UK</a>, or <a href="">Barnes & Noble</a>.</p> <p>Or, if you’d like to get formal NServiceBus training from me in person, you can attend the course I’ll be leading in December. Go to <a href="">training.ilmservice.com</a> for details and to register.</p> <img src="" height="1" width="1" alt=""/> <![CDATA[100,000 Views!]]> 2013-11-07T14:59:13+00:00 <p.</p> <p.)</p> <p>What I can say is that this blog has done a tremendous amount to advance my career, so if you are a junior developer thinking about starting a blog, don’t think about it, <em>just do it</em>. You will become a better writer, and learn things better through the process of explaining them to others. Then one day, it may help land you a great job or opportunity that may not have been available to you otherwise.</p> <p>OK that’s it, I promised myself this post would not become a long-winded “why blogging is awesome” post.</p> <p>So thank you to everyone for sharing in this arbitrary milestone with me. I hope that if you have found yourself here you have found something worthwhile. If not, leave me a comment and maybe I can do something about it!</p> <img src="" height="1" width="1" alt=""/> <![CDATA[Delivering official NServiceBus Training Course]]> 2013-11-05T17:37:22+00:00 <p>While of course <a href="">buying my book</a>.</p> <p>This is why I am so excited to be offering <a href="">the formal 4-day NServiceBus training course</a>. The course will be held on December 9-12 at <a href="">ILM’s offices</a> in Minneapolis, Minnesota. This is the official course with the official curriculum originally developed by <a href="">Udi Dahan</a> himself, but updated for all of the new features in NServiceBus V4.</p> <p><a href=""><strong>Click here for all the details for the course, and to register to attend.</strong></a></p> <p>If you have any questions about the course, please <a href="">contact me through the training site contact form</a> or through the comments on this post and I’ll answer any question I can.</p> <p>I’m looking forward to meeting some talented developers and hopefully throwing back a tasty beverage or two as well!</p> <p>We’re also planning to hold more training courses on other topics soon, so be sure to <a href="">watch my Twitter feed</a> for updates.</p> <img src="" height="1" width="1" alt=""/> <![CDATA[InjectRouteData ActionFilter for ASP.NET MVC]]> 2013-10-28T20:23:48+00:00 <p>If you really want to take control of your ASP.NET routes to create a RESTful or at least RESTish URL naming scheme, first you need to let go of default MVC convention-based routes (Controller/Action/{id}) and use something like <a href="">AttributeRouting</a>. (AR is now <a href="">half-baked into MVC 5</a>, unfortunately without some of the more useful things AttributeRouting has to offer, like the <a href="">~/routes.axd route debugging handler</a>.)</p> <p.</p> <p>In any case, it shouldn’t be that hard. This is something that should be handled at the infrastructure level, so let’s look at how to do that via an InjectRouteData ActionFilter attribute:</p> <script src=""></script> <p:</p> <script src=""></script> <p>This way you don’t have to have the awkward repetitive code at the beginning of each action method getting the thing by its id, you just have the thing already available.</p> <p.</p> .</p> <img src="" height="1" width="1" alt=""/>