<?xml version="1.0" encoding="UTF-8"?><rss 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" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Nick Timkovich on Medium]]></title>
        <description><![CDATA[Stories by Nick Timkovich on Medium]]></description>
        <link>https://medium.com/@nicktimko?source=rss-ae7029d0f876------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/2*eea_fZngGq3n4jJqEgXNsg.png</url>
            <title>Stories by Nick Timkovich on Medium</title>
            <link>https://medium.com/@nicktimko?source=rss-ae7029d0f876------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 15 Nov 2026 09:03:11 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@nicktimko/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[APIs aren’t perfect, but they can be better]]></title>
            <link>https://medium.com/telnyx-engineering/apis-arent-perfect-but-they-can-be-better-1ca019844a06?source=rss-ae7029d0f876------2</link>
            <guid isPermaLink="false">https://medium.com/p/1ca019844a06</guid>
            <category><![CDATA[backend-development]]></category>
            <category><![CDATA[api-design]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[rest-api]]></category>
            <category><![CDATA[api]]></category>
            <dc:creator><![CDATA[Nick Timkovich]]></dc:creator>
            <pubDate>Tue, 02 Jun 2020 18:09:45 GMT</pubDate>
            <atom:updated>2020-06-02T19:54:04.524Z</atom:updated>
            <content:encoded><![CDATA[<p>In the 10 years Telnyx has been around, our product offerings have grown and evolved. By working with our customers, we have learned to fulfill their needs in increasingly easy-to-use ways. Our telephony engineers would release some features, messaging engineers (that’s me!) others, and number inventory engineers more. We delivered a very functional API to customers — important to be sure — but it was not always the most consistent or easy to understand.</p><p>Our engineering division used to be able to maintain consistency with zero effort using this one weird trick: just have one engineer. As the team grew, one engineer would do things one way, another that way, but by sharing the same code base, it would passively converge on the true way. Later on, engineering split roughly along the lines of our usage products and account support, and so ended one group of people looking at one codebase. The river between the groups caused a speciation event, and new traits could emerge independently in the two groups. Additional splits occurred later: splitting off inventory, splitting messaging. In each case, new traits could and would arise to fulfill their technological niches.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*oOBHACh9uj5tLfjW" /><figcaption>We have lively debates about which of our teams best resemble what modern-day organisms. I’ve found Thermus aquaticus to be fantastically useful. Image: <a href="https://commons.wikimedia.org/wiki/File:Tree_of_life_with_genome_size.svg">Gringer</a>, public domain</figcaption></figure><p>When I joined the company two years ago, our teams had already speciated. I joined the colony of <em>Telnyxus mercurii </em>(from the Roman god Mercury) and adopted the view from the messaging niche: a very deep, but very narrow view—everything messaging and only messaging. I knew every permutation of options, features introduced that few used, and what happens in that strange edge-case. The considerations I placed on adding features and fields were to be consistent with whatever our group had, but often they were novel, so I just shopped it around my team. However, they may not have been new to <em>other</em> teams. I wasn’t as familiar with what the other teams were doing: time was spent on problems that telephony apps or numbering inventory may have already solved, but worse, inconsistencies arose in our API.</p><p>As much fun as I’m having, we don’t want our customers to have to be evolutionary technologists to make sense of what’s going on. Coming to our docs and API in modern-day, interacting with multiple products, they may ponder why widgets are timestamped with “created_at” in Unix milliseconds, and doodads have “date_created” in the RFC 3339 format. One object can be removed with HTTP DELETE, but another would require an HTTP POST with a ?delete=true querystring. These are the remnants of our API’s evolution brought about because individual product teams seldom need to interact with the public API of other teams, and a general view of the API being the “last thing” along the path to develop a new feature.</p><h3>Time for a change</h3><p>So we’ve evolved. It was messy and not obvious why there’s that appendix or tailbone. To clean up from our evolution, we decided to release a second major API version and adopt a style guide so our engineers could work towards a common public facade. By providing a consistent API,</p><ol><li>our documentation can be more consistent,</li><li>developers integrating can understand new products faster, and</li><li>we can maintain more SDKs for your language of choice by relying on the uniformity.</li></ol><h3>…but change is hard.</h3><p>APIs are difficult to change. Adding fields is <em>generally</em> safe, but clients may be expecting fields in a specific order and may process responses in ‘creative’ ways which could be thrown off by something different. Removing or changing existing fields can be much more difficult, if not impossible. In theory, you could log and check who updates those fields, but you can’t check if they’re being read. Notifying users to update their code via your website might get some, via email some more, but until you make the breaking change, you won’t know. Ramifications are not immediate as well: it could only occur in rare (to the customer) circumstances. The customer may not use that one feature often, or could just be in a lull. Months later you can get questions about “why don’t we see X” anymore.</p><p>There are some proactive approaches to mitigate this API ossification. A project I used to work on, OpenStack, generalized their V2 API to use <a href="https://docs.openstack.org/api-guide/compute/microversions.html">microversions</a>. This would allow clients to declare which microversion they wanted via an HTTP header, and if the server supported it (servers would support a range), it would reply with the mutually supported response schema. However, this in and of itself requires a change to the API. Additionally, the clients and software using them must be periodically updated even if nothing functionally changes, to stay in the supported band of versions. This is OK for a coalition of projects like OpenStack, but when the components are us and our customer’s software, it can be a costly proposition to tell them they need to update every release cycle.</p><p>However you change, it should be gradual, allowing for users to migrate by opting-in over time. Taking down your entire version X API over a weekend, then bringing up version X+1 is a way to <em>not</em> do it (but that we’ve seen.)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*KVbB4KtzL21vJrcX.jpg" /><figcaption>World v1 shutting down for maintenance, v2 will up in a few years. Evolve or die! Image: <a href="https://en.wikipedia.org/wiki/Don_Davis_(artist)#/media/File:Planetoid_crashing_into_primordial_Earth.jpg">NASA/Don Davis</a>, public domain</figcaption></figure><h3>Guiding principles</h3><p>OK, so we needed to unify, but how? What would it look like? Adopting an API design guide is good for any organization. As a Pythonista, I try to take many “Pythonic” ideas (which are not necessarily <em>about</em> Python) to heart. For instance, <a href="https://www.python.org/dev/peps/pep-0008/">PEP-8</a> teaches us:</p><blockquote>A style guide is about consistency. Consistency with this style guide is important. Consistency within a project is more important. Consistency within one module or function is the most important.</blockquote><p>But it should be tempered. <a href="https://www.python.org/dev/peps/pep-0020/">The Zen of Python</a> also applies, such as</p><blockquote>Readability counts.<br>Special cases aren’t special enough to break the rules.<br>Although practicality beats purity.</blockquote><p>Whatever you do, choose a style as a team. It ensures a consistent “voice” no matter who is writing parts of your API, with what language, using whatever libraries. If you don’t like something about it, fork it and change it. If it’s silent on a matter that causes inconsistencies, make it explicit, make it yours. Engineers, testers, and users should all be contributing to the guide.</p><h3>Finding the One True Way</h3><p>What is it? Does it exist? When we chose to go in our final direction a year ago, and still now, there does not appear to be One True Way. If there was The Way, everyone from AWS, GitHub, and Google would all have been using that way and this wouldn’t be hard. That said, I am severely understating my predecessors&#39; contributions: HTTP, TLS, TCP/IP, and more underpin it all and are all part of The Way.</p><p>On the application layer, however, things are a little rockier. REST (or REST-<em>esque</em> depending on how stringent you can be) has provided HTTP with sane semantics unlike the wild west of 90s web dev. JSON isn’t XML, therefore it’s good. However, how to model and structure data still varies. Back in the day, SOAP as a form of XML-RPC would allow auto-discovery of calls and objects, but XML was a bit of a bear to deal with and is now considered more of a dinosaur.</p><p>HATEOAS (Hypermedia As The Engine Of Application State) is typically mentioned along with REST and does proscribe a bit more. Links (URLs or paths) to connect objects, define relationships, and show valid actions when in a given state. This has the advantage of being a discoverable API, and you can avoid versioning entirely! But then means that your users <em>must</em> <a href="https://twitter.com/fielding/status/376835835670167552">rediscover the API</a>. Unfortunately, lazy developers like me generally make calls by firing a JSON/query string directly to the previously discovered/documented endpoint with a semantically correct HTTP verb and happily getting the data in one round trip. The code it takes to do that is clear and straightforward, but even as a fairly experienced Python programmer, I don’t know what clients are out there that will do HATEOAS discovery for me, and I don’t have the time to develop my own. Even if I did, you’ll need to thwart your users from “misusing” your API and hardcoding paths. In effect, SDKs then turn from an optional feature (to provide and use) to be mandatory.</p><p>During our initial search for a guide, <a href="https://jsonapi.org/">JSON-API</a> was brought up. It’s a specification that follows many RESTful and HATEOAS principles, notably extensive linking and referencing of related resources. The decisions against it principally boiled down to a perception of complicatedness and lack of adoption by bigger players. Our initial view of sample specifications and responses seemed overly complicated, for us to provide, and we had a concern that customers may feel the same. I’m still having trouble finding larger players that have a publicly avowed “JSON-API” interface. Many like GitHub V3 make use of Hypermedia but seem more generally HATEOAS.</p><h3>Our choice</h3><p>We ended up using the <a href="https://github.com/interagent/http-api-design">Heroku/Interagent’s API design guide</a> as a starting point and forked and extended it to our domain of telephony. Phone numbers will always be phone_number, not number, pn, tn, tel, telephone_number, or anything else. Local access and transport areas (LATA) are lata. The style was a good balance of being prescriptive in many areas, parsimonious, and able to accommodate a wide variety of workflows required at Telnyx.</p><p>Typical additions to the API guide are usually about constraining formats, as what’s “natural” in one language may be slightly different in another language. “Trivia” like how a date-time is formatted, or if query parameters are “starts_with” or “startswith”, don’t take much effort to fix if done as part of the development. The improved fit and finish of the API is something users <em>won’t</em> notice, as they can just get on with what they need to do. My OXO peeler isn’t the sharpest in the drawer, but it’s the one I reach for most often because it’s just easy and feels right.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*1qjyWlnnykM7Dxs8CRTn1A.jpeg" /><figcaption>Thermus aquaticus lives on, just being awesome. Image: <a href="https://www.flickr.com/photos/bernd_thaller/27702569359">Bernd Thaller</a> CC-BY 2.0</figcaption></figure><h3>Looking forward</h3><p>So now we have a consistent <a href="https://developers.telnyx.com/docs/v2?utm_source=medium&amp;utm_medium=blog_eng&amp;utm_campaign=202006_api">version 2 of our API</a>. That’ll last forever, right? Nope, we’ll need to improve it later. We even needed to improve it between our beta and final and did so in a rolling manner where our customers can switch over at their and our leisure. Tech is constantly evolving and the smoothest, obvious way to do things changes with it. I have hopes that one of the “binary JSON” formats like <a href="https://developers.google.com/protocol-buffers">Protobuf</a>, <a href="https://msgpack.org/">MsgPack</a>, or <a href="https://avro.apache.org/docs/current/">Avro</a> take off with a killer design and there’s ubiquitous usage of it in public APIs (I imagine they’re much more common internally). GitHub’s version 4 moved to GraphQL, which has many strengths that I value much more after undertaking our whole saga, and maybe we’ll beat them to it (version 3 is before version 4…haha). Maybe it’ll be something I read about on HackerNews tomorrow.</p><p>But I’m done for a bit. It’s <a href="https://telnyx.com/sign-up?utm_source=medium&amp;utm_medium=blog_eng&amp;utm_campaign=202006_api">your turn to use our API</a> and see if we succeeded. Hit me up <a href="https://twitter.com/nicktimko">@nicktimko</a> on Twitter with what you think.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1ca019844a06" width="1" height="1" alt=""><hr><p><a href="https://medium.com/telnyx-engineering/apis-arent-perfect-but-they-can-be-better-1ca019844a06">APIs aren’t perfect, but they can be better</a> was originally published in <a href="https://medium.com/telnyx-engineering">Telnyx Engineering</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[RIP Pipenv: Tried Too Hard. Do what you need with pip-tools.]]></title>
            <link>https://medium.com/telnyx-engineering/rip-pipenv-tried-too-hard-do-what-you-need-with-pip-tools-d500edc161d4?source=rss-ae7029d0f876------2</link>
            <guid isPermaLink="false">https://medium.com/p/d500edc161d4</guid>
            <category><![CDATA[python]]></category>
            <category><![CDATA[pipenv]]></category>
            <category><![CDATA[continuous-integration]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[pip]]></category>
            <dc:creator><![CDATA[Nick Timkovich]]></dc:creator>
            <pubDate>Fri, 24 Jan 2020 16:59:50 GMT</pubDate>
            <atom:updated>2020-01-24T16:59:50.114Z</atom:updated>
            <content:encoded><![CDATA[<p>Pipenv is dead. It went all of 2019 without a single release, despite about 650 commits to master since the last release. Comments from developers on the project explain it “<a href="https://github.com/pypa/pipenv/issues/4058#issuecomment-565550646">has been held back</a> by several subdependencies and a complicated release process”. In the past, there were also comments that internal changes to pip broke it, but pip is continuing to evolve in response to the <a href="https://pyfound.blogspot.com/2019/11/seeking-developers-for-paid-contract.html">PSF funding developers</a> to work on it. Will they hit this moving target and make a release in 2020? Do I care?</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*njKGP9llyWjBRrvz0rzHrg.jpeg" /><figcaption>Rocketing in popularity! (<a href="https://en.wikipedia.org/wiki/File:Antares_Orb-3_launch_failure_(201410280009HQ).jpg">Image: NASA/Joel Kowsky</a>)</figcaption></figure><p>My principal reasons for using Pipenv were twofold. First, was the ability to have reproducible builds through an exhaustively defined lock file, with every package and version specified, then hashed for good measure. Second, I could do the above while maintaining a clean, minimal list of direct dependencies for my application.</p><h4>Pin everything…</h4><p>The reason for a lock file should be clear: so you can have reproducible builds. pip install mypackage may work when you build and test on your workstation, and through one release cycle, but what about when you make a small fix later? Why did changing one line of code and rebuilding cause everything to explode? <em>There was a new incompatible release among one of your dependencies.</em> Precisely defining all packages and their exact versions leads to reproducible builds that are easier to diagnose and bisect when they go wrong.</p><p>Bonus features in the lock file include package hashes. It can improve security, but the failures I’ve seen are because of using multiple package indexes. At Telnyx we have a private PyPI that we use to distribute Python libraries. We adapted a synchronous library to asyncio, but later someone else did so and released it publically with the same name. The collision led to sometimes downloading the private version, sometimes the public, depending on how the indexes were configured on the user’s machine, their build container, or the CI infrastructure. Our private PyPI also allows re-uploading of the same version, which is also made clear when the hash check fails.</p><p>The locked list of dependencies should be deliberately generated and validated through tests. This is often by a developer on their workstation, and they can immediately check before entering a broken commit into the repo. Diffing the lock file will show what new versions were installed, and the version can be pinned to an older version, or source changed to accommodate the change.</p><h4>…and also only what you need</h4><p>OK, but why do we need a separate list of dependencies? Imagine a simple cycle of pinning everything in a singular requirements.txt and regenerating it with pip freeze. The file will not track <em>why</em> certain packages are installed, and if you explicitly remove a direct dependency from it, you’ll be keeping around all of its sub-dependencies for no reason. Additionally, you can enter version resolution hell wherein trying to bump one package for a new version means it needs another package, but a different version than you have pinned. Why is that package pinned? Are you using it directly where you care about the changes, or is it just for one of your deps? Or multiple?</p><p>In this minimal list, we can pin just what we need, excluding incompatible or buggy versions <em>purposefully</em>, and allowing incidental upgrades where we can. This can provide bug fixes and performance improvements (admittedly there can be regressions…), and preclude integrating with deprecated features in older libraries that will be a large maintenance burden later.</p><h4>pip-compile: does one thing</h4><p>Note that none of the features listed include virtual environment management. I use Pyenv for this on my machine, and in production, setting using pip and the built-in venv package is best. Why install anything when you can create a virtual environment in one line, and pip install with one more? They’re ever-so-slightly onerous to call if you use full paths, but you’re typing it <em>once</em> in the Dockerfile or other setup scripts anyways.</p><pre>python3 -m venv /opt/appvenv<br>/opt/appvenv/bin/python3 -m pip install requirements.txt</pre><p>So how do I get that requirements.txt while holding on to the features I liked? Enter <a href="https://github.com/jazzband/pip-tools">pip-tools</a>. Making a wiser decision than Pipenv, pip-tools goes with the UNIX philosophy of “do one thing, and do it well”. It provides a few commands, but one of them: pip-compile can bake one requirements-style file into another, complete with versions and hashes.</p><pre>pip-compile --quiet \<br>    --generate-hashes \<br>    --output-file=requirements.txt \<br>    requirements.in</pre><p>Pipenv <a href="https://github.com/pypa/pipenv/tree/d10b2a216a25623ba9b3e3c4ce4573e0d764c1e4/pipenv/patched/piptools"><em>uses</em> this library</a> to do it — we can cut out the middleman! What’s more, the generated requirements.txt is perfectly readable by pip, so you don’t need to install the tooling in your production system, saving time, space, and exposure to bugs.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/624/0*bec4qvNbOajp_0mN" /><figcaption>I think I’ve been guilty of inflating Pipenv’s download stats; every container build pulls it</figcaption></figure><p>How can you make the switch? If you’re willing to shake up the versions from your Pipfile.lock, converting the Pipfile to a requirements.in is sometimes just a slightly-tedious bunch of editing. However, if you have a lot of libraries, and want to keep their versions locked to make sure changing tools didn’t break anything, I wrote <a href="https://github.com/nicktimko/pipenv2tools">a script</a> that will do it for you!</p><pre># in a path with a Pipfile and Pipfile.lock<br># prereqs: `pip install toml pip-tools`</pre><pre>curl -sSL <a href="https://raw.githubusercontent.com/nicktimko/pipenv2tools/master/pipenv2tools">https://raw.githubusercontent.com/nicktimko/pipenv2tools/master/pipenv2tools</a> | python -</pre><p>So even if Pipenv came out with a new release fixing all the outstanding bugs and pain points I’ve come across, I won’t go back.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d500edc161d4" width="1" height="1" alt=""><hr><p><a href="https://medium.com/telnyx-engineering/rip-pipenv-tried-too-hard-do-what-you-need-with-pip-tools-d500edc161d4">RIP Pipenv: Tried Too Hard. Do what you need with pip-tools.</a> was originally published in <a href="https://medium.com/telnyx-engineering">Telnyx Engineering</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[We’ll Do It Live!: Don’t Write Dead Code.]]></title>
            <link>https://medium.com/@nicktimko/well-do-it-live-don-t-write-dead-code-2404a8651aaf?source=rss-ae7029d0f876------2</link>
            <guid isPermaLink="false">https://medium.com/p/2404a8651aaf</guid>
            <category><![CDATA[open-source]]></category>
            <category><![CDATA[web-apps]]></category>
            <category><![CDATA[saas]]></category>
            <category><![CDATA[software-development]]></category>
            <dc:creator><![CDATA[Nick Timkovich]]></dc:creator>
            <pubDate>Sat, 31 Dec 2016 03:26:54 GMT</pubDate>
            <atom:updated>2022-10-12T14:42:29.195Z</atom:updated>
            <content:encoded><![CDATA[<p>Code at rest is a dreary thing. Worse than that, it’s ignored.</p><p>Software is wondrous because it can be distributed for pennies, and with open-source software, licensed for free. However, source code or even binaries don’t <em>do</em> anything unless they’re <em>run</em>. Knowing how to run code can be tricky, you need to have the proper environment. The quality of documentation varies, and what’s obvious to the people with the skills to develop a tool, is not to those that may want to install it.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*nr6N5Mgs_ab-OHk5sVKgYQ.jpeg" /><figcaption>Slippin’ into darkness.</figcaption></figure><p>Case in point, this was my thought process while trying to set up this blog on GitHub Pages. jekyll build? No, need Jekyll installed. Docs say use Bundler. Bundler doesn&#39;t support Ruby 2.0. How do I upgrade Ruby on OS X, and should I? Maybe use RVM, that&#39;s maybe like pyvenv? OK, kinda works, using the &quot;minimal&quot; theme, still don&#39;t know how/why it&#39;s hitting GitHub and throwing rate limit errors at me…</p><p>This is frustrating. Even from someone who raves about Python, is reasonably skilled with it, and perversely enjoys stepping over those sorts of hurdles. Thankfully, none of that environmental configuration is needed. GitHub provides the service to <a href="https://help.github.com/articles/using-jekyll-with-pages">build your pages for you</a>, no Ruby required. Hell, <em>you don’t even need Git,</em> just a browser and some time.</p><p>Providing software as a service (and keeping that service up) makes sense to me as an engineer, loath as I am to bandy about that buzzword. It completely bypasses the problems of installation and configuration. Users don’t need to set up a finicky environment that is liable to break because some library got upgraded past where its version was pinned, and providers are able to get their tools used, seeing how they run and where they break to make them better.</p><h3>Web apps are king.</h3><p>They reduce the barrier to entry to a click. Putting your awesome, bespoke tools up on the web for anyone with a browser to use is one of the best forms of advertising, and something I’d strongly suggest my academic colleagues do whenever possible. Despite the protestations of a former advisor, successful academics are heavily engaged in marketing. Reading the trends and trying to fulfill the needs of <em>Nature</em>, et al. to get published. Put a URL in your paper and say <em>“try me now!”</em></p><p>Get that code <em>moving</em>.</p><p><em>Originally published at </em><a href="https://amaral.northwestern.edu/blog/do-it-live"><em>amaral.northwestern.edu/blog/do-it-live</em></a><em> on December 31, 2016.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=2404a8651aaf" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The Ultimate Language: AVR Assembly]]></title>
            <link>https://medium.com/@nicktimko/ultimate-language-shootout-37e60e86948b?source=rss-ae7029d0f876------2</link>
            <guid isPermaLink="false">https://medium.com/p/37e60e86948b</guid>
            <category><![CDATA[chipy]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[polyglot-programming]]></category>
            <category><![CDATA[apocalypse]]></category>
            <dc:creator><![CDATA[Nick Timkovich]]></dc:creator>
            <pubDate>Thu, 13 Oct 2016 23:00:43 GMT</pubDate>
            <atom:updated>2022-10-12T13:29:49.693Z</atom:updated>
            <content:encoded><![CDATA[<p>In the ChiPy Ultimate Language Shootout, shooters have 5 minutes to extol the virtues of their chosen (non-Python) language. For the event in October, I chose the Atmel AVR flavor of assembly because I could torture the definition of “ultimate” to point unequivocally to it, plus I could come up with a fun theme around it. Someone declared they would represent Babbage’s Analytical Engine, taking an even lower-level tack that could undercut my position, but they were a no-show.</p><p>Prepared with my 100% undeniable facts and smooth delivery, I ended up winning the day. View the <a href="https://s3.us-east-2.amazonaws.com/static-nick-solutions/uls-timkovich-assembly.pdf">PDF</a>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*HrTCmQsPkihQgewm.jpg" /></figure><p><a href="https://drive.google.com/file/d/0B1zqAXydzfECYkVVeFdwZXNfVVU/view?usp=sharing">Mirror</a></p><p><em>Originally published at </em><a href="https://nicktimko.dev/chipy-uls-2016.html"><em>https://nicktimko.dev</em></a><em> on October 13, 2016.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=37e60e86948b" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>