<?xml version="1.0" encoding="UTF-8"?>
<rss version='2.0' xmlns:dc="http://purl.org/dc/elements/1.1/"
  xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Andrew Goode</title>
    <description>Lost Turing to Eugene Goostman, I now just pretend to be human.</description>
    <link>https://nexdrew.silvrback.com/feed</link>
    <atom:link href="https://nexdrew.silvrback.com/feed" rel="self" type="application/rss+xml"/>
    <category domain="nexdrew.silvrback.com">Content Management/Blog</category>
    <language>en-us</language>
      <pubDate>Fri, 27 Jun 2014 13:22:00 -1100</pubDate>
    <managingEditor>andrewbgoode@gmail.com (Andrew Goode)</managingEditor>
      <item>
        <guid>https://nexdrew.silvrback.com/rest-api-conventions#5525</guid>
          <pubDate>Fri, 27 Jun 2014 13:22:00 -1100</pubDate>
        <link>https://nexdrew.silvrback.com/rest-api-conventions</link>
        <title>The Authoritative Guide on REST API Conventions</title>
        <description>...or something like that</description>
        <content:encoded><![CDATA[<p>Designing a REST API can be difficult. Some frameworks, like Ruby on Rails, come with built-in conventions, which help, but sometimes your framework is quite willing to let you shoot yourself in the foot. For developers using those frameworks, I&#39;d like to offer the following, which is a collection of conventions/rules that will help you write an intuitive and consistent API. (For developers <em>not</em> using a framework - what&#39;s wrong with you?)</p>

<ol>
<li><p><strong>URLs should reference entities (nouns) and not actions (verbs).</strong></p>

<ul>
<li>The action or verb should be defined by HTTP (GET, PUT, POST, DELETE)</li>
</ul></li>
<li><p><strong>Entity names in URLs should be plural.</strong></p>

<ul>
<li>There are exceptions to this rule (e.g. when the entity name is not an actual entity that can be listed), but the exceptions should be rare.</li>
</ul></li>
<li><p><strong>Use GET for listing entities or reading a single entity.</strong></p>

<ul>
<li>e.g. <code>GET /entities</code> returns a list of entites (list may be wrapped)</li>
<li>e.g. <code>GET /entities/123</code> returns a single entity with ID 123</li>
</ul></li>
<li><p><strong>Use PUT for idempotent entity changes.</strong></p>

<ul>
<li>An operation is considered idempotent if it has the same result regardless of how many times it is executed. Think of idempotent as assignment or overwriting, e.g. <code>x = 1</code> or <code>Map.put</code></li>
<li>Generally applies to <em>update</em> operations</li>
<li>e.g. <code>PUT /entities/123</code> updates entity with ID 123</li>
</ul></li>
<li><p><strong>Use POST for non-idempotent entity creations/changes.</strong></p>

<ul>
<li>An operation that is not idempotent is one that causes changes each time it is called, e.g. <code>x++</code> or <code>List.add</code></li>
<li>Generally applies to <em>create</em> operations</li>
<li>e.g. <code>POST /entities</code> creates a new entity</li>
</ul></li>
<li><p><strong>Use DELETE for deleting entities.</strong></p>

<ul>
<li>e.g. <code>DELETE /entities/123</code> deletes entity with ID 123</li>
</ul></li>
<li><p><strong>Entity names should correspond to a particular object type.</strong></p>

<ul>
<li>This means that return types should be the same when the last entity name in a URL is the same.</li>
<li>e.g. <code>/burgers</code> and <code>/burgers?meat=beef</code> and <code>/restaurants/123/burgers</code> should all return the same object type.</li>
</ul></li>
<li><p><strong>The response body for a GET (singular entity) should be a valid request body for a PUT at the same URL.</strong></p>

<ul>
<li>e.g. If Fleet object type is returned from <code>GET /fleets/123</code>, then Fleet object type should be accepted by <code>PUT /fleets/123</code> (assuming that an update is supported)</li>
</ul></li>
<li><p><strong>PUT and POST should accept data as request body in proper content type.</strong></p>

<ul>
<li>i.e. Creations should be accomplished by POSTing JSON or XML (instead of name-value pairs or URL-encoded forms) in the request body.</li>
</ul></li>
<li><p><strong>Nested paths should be reserved for entity relationships or context, not for categorization.</strong></p>

<ul>
<li>This means (1) a nested path should always contain an ID of the parent entity and (2) any level of a nested path should be a valid URL.</li>
<li>e.g. <code>/admin/messages</code> should be <code>/adminmessages</code> or just <code>/messages</code></li>
</ul></li>
<li><p><strong>Nested paths should probably be limited to 1 or 2 levels.</strong></p>

<ul>
<li>It’s generally easier to switch context than it is to maintain a full hierarchy with parent IDs.</li>
<li>e.g. <code>/distributors/123/accounts/456/fleets/789/mobiles/321/pins/6</code> is certainly ridiculous when <code>/mobiles/321/pins/6</code> is specific enough to get the same thing.</li>
</ul></li>
<li><p><strong>Filtering, sorting, and paging an entity list should be accomplished via URL parameters.</strong></p>

<ul>
<li>e.g. <code>/mobiles?fleetId={fleetId}&amp;page={num}&amp;pageSize={num}&amp;sort={propertyName}</code></li>
</ul></li>
<li><p><strong>Use consistent entity/parameter names when possible.</strong></p>

<ul>
<li>Check existing API or other designs when you have a question about a name that may be used elsewhere.</li>
<li>It’s ok to support multiple names of the same thing for the same call, but be consistent.</li>
<li>e.g. If <code>?lat={lat}&amp;lon={lon}</code> is already used somewhere, then don’t use <code>?latitude={lat}&amp;longitude={lon}</code> or <code>?lat={lat}&amp;lng={lon}</code> unless you already support the first option.</li>
</ul></li>
<li><p><strong>Err on the side of flexibility.</strong></p>

<ul>
<li>e.g. Support both <code>/fleets/123/mobiles</code> and <code>/mobiles?fleetId=123</code></li>
</ul></li>
<li><p><strong>Version your API via the URL.</strong></p>

<ul>
<li>This makes it easy for clients to ask for a specific version and helps you to segregate differences cleanly.</li>
<li>e.g. Version 1 of your API should be available under <code>/v1</code> (or similar) with URLs like <code>/v1/contacts</code> and <code>/v1/teams/5/members</code>. Version 2 would then be available under <code>/v2</code>.</li>
</ul></li>
<li><p><strong>Use appropriate HTTP status codes for error responses.</strong></p>

<ul>
<li>e.g. An invalid request should return a status code in the 400s, and an unexpected server error should return a status code in the 500s.</li>
</ul></li>
<li><p><strong>All errors returned should use the same data structure in the body of the response.</strong></p>

<ul>
<li>When errors occur, you need to give your client enough info about the error to know what went wrong and how to fix it - as long as the info does not present a security vulnerability.</li>
<li>This means an invalid request like <code>GET /events?occurringBefore=never</code> <em>does not</em> return a response with a list of Event objects, it returns a response with an Error object (stating that &quot;never&quot; is not a valid value for the &quot;occurringBefore&quot; param).</li>
<li>Your Error response should probably include fields like an application-defined <code>code</code> (to help distinguish between specific problems that might return the same HTTP status), a <code>message</code> for the client program (<em>does not</em> need to support i18n), and a <code>userMessage</code> for the end-user (<em>does</em> need to support i18n).</li>
</ul></li>
</ol>

<p>I also highly recommend <a href="http://blog.codinghorror.com/the-ultimate-dogfooding-story/">dogfooding</a> your own API (i.e write and use your own client for your API). Doing so will certainly help you weed out the confusing and difficult parts of your API.</p>

<p>Obviously, these guidelines don’t cover everything (e.g. consistent data structures across all lists, conventional formats for certain datatypes, how to do authentication e.g. OAuth, etc), but these are battle-tested and should serve as basic rules your API should conform to. As you&#39;re building and testing your API, you&#39;ll undoubtedly encounter questions that are not addressed here. When that happens, discuss with your team and add to your adopted conventions as necessary.</p>

<p><em>(Originally written Monday, February 25th, 2013)</em></p>
]]></content:encoded>
      </item>
      <item>
        <guid>https://nexdrew.silvrback.com/reviewing-code#5385</guid>
          <pubDate>Sun, 22 Jun 2014 08:05:53 -1100</pubDate>
        <link>https://nexdrew.silvrback.com/reviewing-code</link>
        <title>Reviewing Code</title>
        <description></description>
        <content:encoded><![CDATA[<p><img alt="Nerd humor" src="https://silvrback.s3.amazonaws.com/uploads/5776ce7b-85bd-4940-979e-449d49f10b4e/code-review-2_large.jpg" /></p>

<p>Reviewing code is a necessary part of software development, but I&#39;ve found that many developers either don&#39;t know how to do good code reviews or just don&#39;t do it effectively.</p>

<p>Here&#39;s the quick-and-dirty list I usually give my software teams. Answer these questions while reviewing someone else&#39;s code and it will eventually become second-nature to you.</p>

<h1 id="first-the-low-level">First the low-level:</h1>

<ul>
<li>Is the code syntactically and logically correct?</li>
<li>Is the code actually doing what it’s intended to do?</li>
<li>Does the code use resources efficiently (e.g. db call, memory consumption, etc)?</li>
<li>Is the code reasonably documented?</li>
<li>Is the code too complicated or confusing to follow?</li>
<li>Is there a better way of doing what the code is doing?</li>
</ul>

<h1 id="then-the-high-level">Then the high-level:</h1>

<ul>
<li>Does the code produce the desired functionality?</li>
<li>Does the code directly or indirectly introduce problems for other/existing/transitive functionality?</li>
<li>Does the code follow conventions or precedents of similar existing functionality?</li>
<li>Is this the best place to put this logic?</li>
<li>Does the code smell (i.e. does it make you uneasy, even if you can’t exactly say why)?</li>
</ul>

<p>All of these can pretty much be summed up by <strong>If I were implementing this functionality, is this the way I&#39;d write my code?</strong></p>

<p>Obviously it takes a little experience to know how to answer these questions, but that will come with time and practice.</p>

<p>Happy reviewing!</p>

<p><em>(Originally written Wednesday, March 13th, 2013)</em></p>
]]></content:encoded>
      </item>
      <item>
        <guid>https://nexdrew.silvrback.com/so-long-dave#5134</guid>
          <pubDate>Fri, 13 Jun 2014 16:41:21 -1100</pubDate>
        <link>https://nexdrew.silvrback.com/so-long-dave</link>
        <title>So Long</title>
        <description>and Thanks for All the Drinks</description>
        <content:encoded><![CDATA[<h1 id="a-couple-days-ago-i-learned-that-my-best-friend-at-work-is-leaving-his-name-is-dave">A couple days ago, I learned that my best friend at work is leaving. His name is Dave.</h1>

<p>It didn&#39;t come as any big surprise since I knew of several other things leading up to this point, but I had no idea if his timeline was several months out or only a few weeks away. Turns out to be even shorter than that. He&#39;ll be gone, leaving not only this company but also this state, in just a week and a half.</p>

<p>Today, after our weekly team lunch, he came to my office and told me he had accepted an offer. We talked about his new opportunity, what the interview process was like, how quickly everything had happened, how much we have enjoyed working with each other and have learned from each other, and covered some logistics. Then he gave his notice to our VP and told the rest of the team. And that was that.</p>

<p>Now that it&#39;s official, the realization is starting to sink in. Some of the things I have anticipated for a long time are finally here, and things will be changing very soon. If I don&#39;t get my bearings and hop aboard a car, I&#39;ll miss the train. Dave&#39;s exit is now a catalyst for my own.</p>

<h1 id="about-dave-though">About Dave, though...</h1>

<p><img alt="Dave" class="sb_float" src="https://silvrback.s3.amazonaws.com/uploads/9b4d72d4-8143-43ad-a4b9-faab07db3d06/dmcnavish-small_large.jpg" /></p>

<p>It&#39;s tough to know what to say. All at once I&#39;m sad to see him go, excited for his opportunities, discouraged about losing his day-to-day friendship, and proud of his well-earned success.</p>

<p>He&#39;s the type of person that can learn any new technology in less than a day and can master it in a week. Be it a <a href="http://nodejs.org/">Node.js</a> app backed by <a href="http://www.mongodb.org/">Mongo</a>, a <a href="http://www.sparkjava.com/">Spark</a> app using <a href="http://projects.spring.io/spring-integration/">Spring Integration</a> for messaging, an <a href="http://developer.android.com/index.html">Android</a> app consuming a REST API, or loading a bunch of data into <a href="http://www.elasticsearch.org/">ElasticSearch</a> and building a find-anything UI on top of it, Dave can pump out POCs like nobody&#39;s business. (Not to mention, he can fine-tune a Windows registry like a musical instrument!)</p>

<p>He really is one of the best software developers I&#39;ve ever met, but more than that, he&#39;s a great guy with a positive, matter-of-fact attitude that made our team and my life better. He always looked forward to a challenge and never said no to, or complained about, any assignment ever given. He provided invaluable insight, was always tuned-in to his fellow team members, and constantly provided ideas for improving practices and processes to make everyone more productive. I&#39;ve had the privilege of working and learning alongside him for the past 3 years, and I&#39;ve really seen him grow into a great team leader.</p>

<h1 id="and-above-all-that-i-just-plain-like-him">And, above all that, <em>I just plain like him.</em></h1>

<p>One thing you should know about Dave is that he&#39;s a pretty healthy guy too, so he drinks water whenever we go out to eat. Our team goes out to lunch together at least once a week, usually on Fridays, and Dave and I would grab lunch together frequently beyond that. Out of the hundreds of times we&#39;ve eaten together, I don&#39;t think I&#39;ve <em>ever</em> seen him order anything to drink besides water for lunch. I, on the other hand, usually order overpriced soda. But, on several occasions, Dave has been snubbed with <em>my</em> drink on <em>his</em> bill.</p>

<p><img alt="Another free drink, compliments of Dave" class="sb_float" src="https://silvrback.s3.amazonaws.com/uploads/23403fed-c1a4-4b59-bf80-eacf36c04d11/drinks-1_large.jpg" /></p>

<p>The first time it happened, it was funny. The second time it happened, it was just strange. The third time, I suspect conspiracy. But it really has happened so often that it&#39;s now just a regular thing. It&#39;s almost weird if Dave <em>doesn&#39;t</em> end up paying for my drink. But, of course, Dave&#39;s the type of guy who rolls with the punches and happily pays on my behalf without any expectation of reimbursement. I literally probably owe him about $40 worth of non-alcoholic beverages.</p>

<p>So, Dave, if you&#39;re reading this, thanks for the countless drinks you&#39;ve bought me, and thanks for making my job and life a little sweeter every day for the past few years. You&#39;re a class act, and I&#39;m gonna miss you. I really do wish you and your wife all the best. If you ever need anything or just want to shoot the breeze, all you have to do is call. I&#39;ll keep your tab open at the usual spots.</p>

<h1 id="so-long-and-thanks-for-all-the-drinks">So long, and thanks for all the drinks.</h1>

<p>P.S. <a href="http://lifecorporatedev.blogspot.com/">You can read Dave&#39;s old blog here.</a></p>
]]></content:encoded>
      </item>
  </channel>
</rss>