<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>jeffhui.net</title><link>https://www.jeffhui.net/</link><description>Recent content on jeffhui.net</description><generator>Hugo -- 0.134.3</generator><language>en-us</language><lastBuildDate>Thu, 19 Mar 2026 18:10:19 -0700</lastBuildDate><atom:link href="https://www.jeffhui.net/index.xml" rel="self" type="application/rss+xml"/><item><title>Datastar Basics</title><link>https://www.jeffhui.net/writings/2025/datastar/</link><pubDate>Thu, 19 Mar 2026 18:10:19 -0700</pubDate><guid>https://www.jeffhui.net/writings/2025/datastar/</guid><description>&lt;p>&lt;a href="https://data-star.dev/">Datastar&lt;/a> is an &lt;a href="https://htmx.org/">HTMX&lt;/a>-like framework that attempts to minimize the amount of Javascript you write using a few concepts:&lt;/p>
&lt;ul>
&lt;li>Use html attributes for dynamism prefixed with &lt;code>data-&lt;/code>&lt;/li>
&lt;li>Easy in-document updates similar to &lt;a href="https://turbo.hotwired.dev/">Turbo&lt;/a>&lt;/li>
&lt;li>Real-time updating via &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events">SSE&lt;/a>&lt;/li>
&lt;li>Signals for client-side state&lt;/li>
&lt;/ul>
&lt;p>If we compare it to other approaches, we can understand some of the tradeoffs:&lt;/p>
&lt;ul>
&lt;li>Unlike React, signals are global to a page and are expected to have less state than a full SPA. Complex UI elements are recommended to be &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_components">web components&lt;/a> with Datastar.&lt;/li>
&lt;li>Real-time updating via SSE for compression and automatic reconnects provided by the browser (instead of WebSockets which &lt;a href="https://hexdocs.pm/phoenix_live_view/Phoenix.LiveView.html">LiveView&lt;/a> uses)&lt;/li>
&lt;li>Unlike HTMX, it uses mostly just plain Javascript so you don&amp;rsquo;t have to include &lt;a href="https://hyperscript.org/">hyperscript&lt;/a>, &lt;a href="https://hyperscript.org/">Alpinejs&lt;/a> or another supplementary library for more complex logic.&lt;/li>
&lt;li>HTML content is swapped via dom morph swaps instead of innerHTML replacement by default in an attempt to better preserve the DOM state.&lt;/li>
&lt;/ul>
&lt;p>Datastar is explicitly NOT a Single Page Application framework. Whenever something should be another page, it should be a separate server-rendered page. As a default, complexity should be pushed towards the server:&lt;/p></description></item><item><title>Algebraic Data Types: Product &amp; Sum Types</title><link>https://www.jeffhui.net/writings/2025/adt/</link><pubDate>Sun, 17 Aug 2025 13:22:03 -0700</pubDate><guid>https://www.jeffhui.net/writings/2025/adt/</guid><description>&lt;p>ADTs is a fancy term for a type composed from other types. There are two kinds of Algebraic Data Types.&lt;/p>
&lt;h2 id="product-types">Product Types&lt;/h2>
&lt;p>Product types are structs and tuples, which contain a sequence of types.&lt;/p>
&lt;p>Most programming languages have product types, so ADTs are often seen as shorthand for sum types, but that’s technically inaccurate.&lt;/p>
&lt;h2 id="sum-types">Sum Types&lt;/h2>
&lt;p>Sum types are unions plus enums. They contain one of the specified underlying types:&lt;/p></description></item><item><title>Object Oriented Programming</title><link>https://www.jeffhui.net/compendium/oop/</link><pubDate>Thu, 24 Jul 2025 01:51:17 -0700</pubDate><guid>https://www.jeffhui.net/compendium/oop/</guid><description>&lt;p>Object Oriented Programming is really two different ideas: message-passing and compile-time hierarchies. The former informs modern distributed systems and the latter is the basis of popular modern programming architectures.&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align: left">Problem&lt;/th>
&lt;th style="text-align: left">Small-talk / Message Passing Lineage&lt;/th>
&lt;th style="text-align: left">Modern / Compile-Time Lineage&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align: left">Encourages everything to be solved with &amp;hellip;&lt;/td>
&lt;td style="text-align: left">Message passing&lt;/td>
&lt;td style="text-align: left">Classes&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">Integrating two existing pieces of code&lt;/td>
&lt;td style="text-align: left">Proxy Objects, Dynamic Dispatch&lt;/td>
&lt;td style="text-align: left">Adapters&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">Extending code without modifying original code &amp;hellip;&lt;/td>
&lt;td style="text-align: left">Delegation&lt;/td>
&lt;td style="text-align: left">Inheritance&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">Calling a method implementation is &amp;hellip;&lt;/td>
&lt;td style="text-align: left">Asynchronous and knowable only at runtime&lt;/td>
&lt;td style="text-align: left">Synchronous and compile-time known&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">Iterating on Program Development by &amp;hellip;&lt;/td>
&lt;td style="text-align: left">Updating one object at a time while preserving state, Limited type checking&lt;/td>
&lt;td style="text-align: left">Compile-time, Static type checking, Update full program by reseting state&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>While both are technically about objects, one focuses on using mechanisms of messages to solve problems, while the other focuses on using classes and inheritance to solve problems.&lt;/p></description></item><item><title>Event Sourcing</title><link>https://www.jeffhui.net/compendium/event-sourcing/</link><pubDate>Sun, 06 Jul 2025 10:47:39 -0700</pubDate><guid>https://www.jeffhui.net/compendium/event-sourcing/</guid><description>&lt;p>Event Sourcing departs from traditional state-centric data management. Instead of treating the current state of entities as the primary source of truth, Event Sourcing recognizes that the sequence of changes—the events—contains richer, more complete information about what actually happened in your system.&lt;/p>
&lt;p>Consider the difference between a bank account balance and a bank statement. Traditional CRUD systems store the equivalent of just the current balance:&lt;/p>
&lt;ul>
&lt;li>Account 12345 has $1,247.83.&lt;/li>
&lt;/ul>
&lt;p>Event Sourcing stores the complete statement:&lt;/p></description></item><item><title>Monads: Are they worth it?</title><link>https://www.jeffhui.net/writings/2025/monads/</link><pubDate>Sat, 10 May 2025 12:59:43 -0700</pubDate><guid>https://www.jeffhui.net/writings/2025/monads/</guid><description>&lt;p>Monads are interfaces for sequencing behaviors related to a data type.&lt;/p>
&lt;p>Monads are similar to Unix pipes. They transform input and return the same output type. While pipes describe the function, Monads describe the data type flowing through pipes.&lt;/p>
&lt;p>Let’s look at pseudocode defining a monad:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-java" data-lang="java">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// Java: one of the best languages for defining interfaces...&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">interface&lt;/span> &lt;span style="color:#a6e22e">Monad&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>M, T&lt;span style="color:#f92672">&amp;gt;&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// Return is a class method: static isn&amp;#39;t legal java&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">static&lt;/span> Monad&lt;span style="color:#f92672">&amp;lt;&lt;/span>M, T&lt;span style="color:#f92672">&amp;gt;&lt;/span> &lt;span style="color:#a6e22e">Return&lt;/span>(value T)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Monad&lt;span style="color:#f92672">&amp;lt;&lt;/span>M, U&lt;span style="color:#f92672">&amp;gt;&lt;/span> Bind&lt;span style="color:#f92672">&amp;lt;&lt;/span>U&lt;span style="color:#f92672">&amp;gt;&lt;/span>(f Function&lt;span style="color:#f92672">&amp;lt;&lt;/span>T, U&lt;span style="color:#f92672">&amp;gt;&lt;/span>) &lt;span style="color:#75715e">// f = func(T) -&amp;gt; U&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>We define the Monad as a generic interface. &lt;em>M&lt;/em> is the data type implementing the monad interface and &lt;em>T&lt;/em> is the input type for pipeline functions. &lt;em>M&lt;/em> is the output value and &lt;em>T&lt;/em> is the input type. In the simplest case, both can be the same type, like &lt;code>Text&lt;/code> in Unix pipes.&lt;/p></description></item><item><title>Typescript Retrospective</title><link>https://www.jeffhui.net/writings/2024/ts-retro/</link><pubDate>Tue, 01 Oct 2024 20:37:50 -0700</pubDate><guid>https://www.jeffhui.net/writings/2024/ts-retro/</guid><description>&lt;p>As part of trying out Svelte, I&amp;rsquo;ve also stepped into the modern web development
ecosystem. I previously worked primarily in Clojurescript, so my reference point
is based on being away from conventional web dev for many years.&lt;/p>
&lt;h1 id="the-good-parts">The Good Parts&lt;/h1>
&lt;h2 id="getting-started-is-easy">Getting Started is Easy&lt;/h2>
&lt;p>Not having to build anything yourself can be nice if you want to deliver
something quickly. This is doubly true when Svelte allows you to pull a library
that doesn&amp;rsquo;t have explicit view framework support (eg - ReactJS). Need auth? Use
&lt;a href="https://authjs.dev/">AuthJS&lt;/a>. Everything is so &lt;a href="https://www.youtube.com/watch?v=SxdOUGdseq4">easy&lt;/a>.&lt;/p></description></item><item><title>Svelte 5 for ReactJS Users</title><link>https://www.jeffhui.net/writings/2024/svelte-5/</link><pubDate>Mon, 23 Sep 2024 22:17:00 -0700</pubDate><guid>https://www.jeffhui.net/writings/2024/svelte-5/</guid><description>&lt;p>Disclaimer: I didn’t learn Svelte before v5, so this is an experience report on
translating Svelte 4 code to 5.&lt;/p>
&lt;p>This is a blind jump into Svelte.&lt;/p>
&lt;h1 id="the-basics">The Basics&lt;/h1>
&lt;p>Svelte components end in &lt;code>.svelte&lt;/code> like &lt;code>.jsx&lt;/code> or &lt;code>.tsx&lt;/code>. They look more
HTML-like than JavaScript. In comparison, ReactJS is more JavaScript-like than
HTML.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-svelte" data-lang="svelte">&lt;span style="display:flex;">&lt;span>&amp;lt;&lt;span style="color:#f92672">script&lt;/span>&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">let&lt;/span> { &lt;span style="color:#a6e22e">name&lt;/span> } &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">$props&lt;/span>();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&amp;lt;/&lt;span style="color:#f92672">script&lt;/span>&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&amp;lt;&lt;span style="color:#f92672">h1&lt;/span>&amp;gt;Hello, {&lt;span style="color:#a6e22e">name&lt;/span>}!&amp;lt;/&lt;span style="color:#f92672">h1&lt;/span>&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="typescript">Typescript&lt;/h2>
&lt;p>To use TypeScript, add &lt;code>lang=”ts”&lt;/code> to the script tag:&lt;/p></description></item><item><title>Toml Crash Course</title><link>https://www.jeffhui.net/writings/2024/toml-crashcourse/</link><pubDate>Thu, 19 Sep 2024 16:28:34 -0700</pubDate><guid>https://www.jeffhui.net/writings/2024/toml-crashcourse/</guid><description>&lt;h1 id="background">Background&lt;/h1>
&lt;p>Since migrating this site to &lt;a href="https://gohugo.io/">Hugo&lt;/a>, I felt like it was finally time to
avoid learning TOML.&lt;/p>
&lt;p>This assumes you don&amp;rsquo;t know &lt;a href="https://toml.io/">TOML&lt;/a> but know other &lt;a href="https://www.json.org/">data&lt;/a>
&lt;a href="https://yaml.org/">formats&lt;/a>? Time to speedrun through.&lt;/p>
&lt;h1 id="the-30-second-start">The 30-second Start&lt;/h1>
&lt;p>You can think of toml as key value file format with namespace prefixes that
translate to JSON:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-toml" data-lang="toml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># this is a comment&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">key&lt;/span> = &lt;span style="color:#e6db74">&amp;#34;value&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>[&lt;span style="color:#a6e22e">my-key-prefix&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">key2&lt;/span> = &lt;span style="color:#e6db74">&amp;#34;value2&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">person&lt;/span>.&lt;span style="color:#a6e22e">name&lt;/span> = &lt;span style="color:#e6db74">&amp;#34;John&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Conceptually produces&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-json" data-lang="json">&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;key&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;value&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;my-key-prefix&amp;#34;&lt;/span>: {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;key2&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;value2&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> },
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;person&amp;#34;&lt;/span>: {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;name&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;John&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Dot-notation indicates a nested object. In the spec, TOML calls objects tables.&lt;/p></description></item><item><title>check.statem: Generating Test Programs</title><link>https://www.jeffhui.net/2020/01-check.statem.html</link><pubDate>Sun, 05 Jan 2020 00:00:00 +0000</pubDate><guid>https://www.jeffhui.net/2020/01-check.statem.html</guid><description>&lt;p>One of the most interesting parts of generative testing (aka
&lt;a href="https://hackage.haskell.org/package/QuickCheck">QuickCheck&lt;/a>) is state machine testing. The original purpose I
built &lt;a href="http://github.com/jeffh/Fox">Fox&lt;/a> was to explore state machine testing. In particular, the talk
from John Hughes video was inspirational to exploring this further:&lt;/p>
&lt;p>
&lt;iframe class="center lit" width="560" height="315"
src="https://www.youtube-nocookie.com/embed/zi0rHwfiX1Q" frameborder="0"
allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
allowfullscreen>&lt;/iframe>
&lt;/p>
&lt;p>In short, John makes a case: dynamically generating state machines to detect
errors that is more effective and economical than traditional example based
tests. There&amp;rsquo;s lots of work managing example based tests that can be better
solved with generative testing.&lt;/p></description></item><item><title>Reading Code – Assertions &amp; Assumptions</title><link>https://www.jeffhui.net/2016/23-reading-code.html</link><pubDate>Wed, 31 Aug 2016 00:00:00 +0000</pubDate><guid>https://www.jeffhui.net/2016/23-reading-code.html</guid><description>&lt;p>I&amp;rsquo;m fascinated by how engineers read and interpret code that they work on a
daily basis. It&amp;rsquo;s no doubt different for everyone, but few explain how they go
about and understand an unfamiliar codebase.&lt;/p>
&lt;p>For me, being comfortable in a codebase usually means two things:&lt;/p>
&lt;ul>
&lt;li>Being able to jump to relevant, related parts of the code.&lt;/li>
&lt;li>Understand the implications of changing a piece of code
&lt;ul>
&lt;li>&lt;strong>Inside the system&lt;/strong> – impact of code quality. How does the code influence
code in the same project?&lt;/li>
&lt;li>&lt;strong>Outside the system&lt;/strong> – implications for human and program collaborators.
How does the code influence other projects, teams, or users?&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>Both can be addressed by following the data flow of the code. I refer to my
strategy as assertions and assumptions. Take this arbitrary
&lt;a href="https://github.com/django/django/commit/4bc6b939944183533ae74791d21282e613f63a96">code snippet&lt;/a>
from &lt;a href="https://github.com/django/django">Django&lt;/a>:&lt;/p></description></item><item><title>What's Your Engineering Culture?</title><link>https://www.jeffhui.net/2016/22-whats-your-engineering-culture.html</link><pubDate>Sun, 31 Jul 2016 00:00:00 +0000</pubDate><guid>https://www.jeffhui.net/2016/22-whats-your-engineering-culture.html</guid><description>&lt;p>When evaluating companies, it&amp;rsquo;s of utmost importance to learn about the engineering
culture. Culture for a company is similar to scope for code – culture provides a
context for getting work done.&lt;/p>
&lt;p>Companies advertise their culture, but note that each company has a different
culture. There&amp;rsquo;s plenty of articles about culture, so I won&amp;rsquo;t bother covering
that. Just remember they aren&amp;rsquo;t necessarily the same. Companies tend not to be
explicit about making sure their process matches what you expect. Be suspicious
for a company that can&amp;rsquo;t explain its culture because that just means they&amp;rsquo;re
not actively trying to cultivate one. And that means it&amp;rsquo;s implicitly defined
by the leaders of the company. Even if they choose not to define it.&lt;/p></description></item><item><title>TLDR Programming Concepts</title><link>https://www.jeffhui.net/2016/21-tldr-programming-concepts.html</link><pubDate>Thu, 30 Jun 2016 00:00:00 +0000</pubDate><guid>https://www.jeffhui.net/2016/21-tldr-programming-concepts.html</guid><description>&lt;p>Trying to concisely describe concepts is an interesting exercise. The ideal goal
is to build upon existing concepts, but as you add more concepts you run the
risk of being inconsistent.&lt;/p>
&lt;p>So with at most two sentences, I present a list of common programming concepts.
This goes without saying that lossy compression is inevitable.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Data&lt;/strong>: Ones and zeros.&lt;/li>
&lt;li>&lt;strong>Values&lt;/strong>: Meaningful data.&lt;/li>
&lt;li>&lt;strong>Types / Encodings&lt;/strong>: Interpretations of values.&lt;/li>
&lt;li>&lt;strong>State&lt;/strong>: A value that changes over time. Usually also considered a Value.&lt;/li>
&lt;li>&lt;strong>Variables&lt;/strong>: Names for values over time.&lt;/li>
&lt;li>&lt;strong>Collections&lt;/strong>: A value that&amp;rsquo;s a group of values of same type.&lt;/li>
&lt;li>&lt;strong>Structs&lt;/strong>: A value that&amp;rsquo;s a group of values with possibly differing types.&lt;/li>
&lt;li>&lt;strong>Classes&lt;/strong>: Structs with functions that have itself as the first argument.&lt;/li>
&lt;li>&lt;strong>Inheritance&lt;/strong>: A concise way to implement a class by referring to part of
its implementation from one class.&lt;/li>
&lt;li>&lt;strong>Multiple Inheritance&lt;/strong>: A class that inherits from multiple other classes.&lt;/li>
&lt;li>&lt;strong>Extensions&lt;/strong>: Adding methods to a previously defined type.&lt;/li>
&lt;li>&lt;strong>Mixins&lt;/strong>: Adding (Multiple) Inheritance to a previously defined type.&lt;/li>
&lt;li>&lt;strong>Interface / Protocols&lt;/strong>: Inheritance of a class that has only functions that
should be implemented by the class that inherits it.&lt;/li>
&lt;li>&lt;strong>Traits&lt;/strong>: Interfaces that may have function implementations.&lt;/li>
&lt;li>&lt;strong>Generics&lt;/strong>: Treating a type as a variable. Allows algorithms independent of
specific types.&lt;/li>
&lt;li>&lt;strong>Type Classes&lt;/strong>: Generic Interfaces.&lt;/li>
&lt;li>&lt;strong>Monad&lt;/strong>: An interface defining the expected behavior for &lt;code>map&lt;/code>.&lt;/li>
&lt;li>&lt;strong>Functor&lt;/strong>: An interface defining the expected behavior for &lt;code>apply&lt;/code>.&lt;/li>
&lt;li>&lt;strong>Pointers&lt;/strong>: A value that indicates where to find another value. A home
address is a pointer to a home.&lt;/li>
&lt;li>&lt;strong>Big-O Notation&lt;/strong>: A method to estimate the number of main-memory operations&lt;/li>
&lt;li>&lt;strong>Slice&lt;/strong>: A value that is a pointer and length into an existing collection&lt;/li>
&lt;li>&lt;strong>Value Objects&lt;/strong>: A struct / class with equality and hashCode semantics.&lt;/li>
&lt;li>&lt;strong>Object-Oriented Programming&lt;/strong>: The concept of classes talking to each other
using value objects.&lt;/li>
&lt;li>&lt;strong>Procedure&lt;/strong>: A sequence of operations to execute. Most programming languages
mean procedure when they say function.&lt;/li>
&lt;li>&lt;strong>Function&lt;/strong>: Vaguely defined / blurred by current norms. See Procedure.&lt;/li>
&lt;li>&lt;strong>Pure Function&lt;/strong>: A procedure that returns the same output for the same
inputs.&lt;/li>
&lt;li>&lt;strong>Side Effects&lt;/strong>: Any observable state that occurs besides a return value.&lt;/li>
&lt;li>&lt;strong>Functional Programming&lt;/strong>: The practice of using less state and more pure
functions.&lt;/li>
&lt;li>&lt;strong>Code&lt;/strong>: A value that is a series of operations&lt;/li>
&lt;li>&lt;strong>AST (Abstract Syntax Tree)&lt;/strong>: Hierarchy of typed code&lt;/li>
&lt;li>&lt;strong>Program&lt;/strong>: A collection of code that a computer that can execute.&lt;/li>
&lt;li>&lt;strong>Compiler&lt;/strong>: Program that takes code and produce programs.&lt;/li>
&lt;li>&lt;strong>Interpreter&lt;/strong>: A program that executes code without producing a program.&lt;/li>
&lt;li>&lt;strong>Emulator&lt;/strong>: A program that mimics the behavior of hardware.&lt;/li>
&lt;li>&lt;strong>Virtual Machine&lt;/strong>: A computer emulator where the hardware may not actually
exist (eg - Java Virtual Machine).&lt;/li>
&lt;li>&lt;strong>Static&lt;/strong>: Known at compile-time.&lt;/li>
&lt;li>&lt;strong>Dynamic&lt;/strong>: Known at execution-time.&lt;/li>
&lt;li>&lt;strong>Type Checker&lt;/strong>: A program that validates what types flowing through your
code.&lt;/li>
&lt;li>&lt;strong>Type Inference&lt;/strong>: A compiler or interpreter feature that can deduce types
without always explicitly specifying it in code.&lt;/li>
&lt;li>&lt;strong>Optimization&lt;/strong>: Writing code for the computer first, instead of humans.&lt;/li>
&lt;li>&lt;strong>Performance&lt;/strong>: Turning memory operations for lower frequency, and higher
throughput.&lt;/li>
&lt;li>&lt;strong>Reference Counting&lt;/strong>: Counting number of owners of a piece of memory to know
when to free it.&lt;/li>
&lt;li>&lt;strong>Garbage Collection&lt;/strong>: An embedded program that frees another program&amp;rsquo;s
memory that is no longer being used.&lt;/li>
&lt;li>&lt;strong>Reflection&lt;/strong>: Code that can inspect and/or modify itself as it&amp;rsquo;s executing.&lt;/li>
&lt;li>&lt;strong>Macros&lt;/strong>: An operation that can be translated to a sequence of operations
before program execution.&lt;/li>
&lt;li>&lt;strong>JIT (Just-In-Time) Compilation&lt;/strong>: A feature of interpreters or emulators
that compiles code during its execution.&lt;/li>
&lt;/ul>
&lt;hr>
&lt;p>The last concept pushes the limits of definitions this concise. Some interesting
implications result from these definitions:&lt;/p></description></item><item><title>Two Kinds of Abstractions</title><link>https://www.jeffhui.net/2016/20-two-kinds-of-abstractions.html</link><pubDate>Tue, 31 May 2016 00:00:00 +0000</pubDate><guid>https://www.jeffhui.net/2016/20-two-kinds-of-abstractions.html</guid><description>&lt;p>When someone talks about abstractions, they&amp;rsquo;re usually trying to make the
software more flexible. But that&amp;rsquo;s usually one of two kinds of abstractions.&lt;/p>
&lt;h2 id="build-an-abstraction-to-_hide-an-implementation_">Build an abstraction to &lt;em>hide an implementation&lt;/em>&lt;/h2>
&lt;p>Abstractions that hide implementations are more commonly touted as good designs.
&lt;a href="https://github.com/lostisland/faraday">Ruby&amp;rsquo;s Faraday&lt;/a> abstracts the specific HTTP library implementation.
Rails&amp;rsquo; &lt;a href="http://guides.rubyonrails.org/active_record_basics.html">ActiveRecord&lt;/a> abstracts the SQL you need to write to
interface with a relational database. The
&lt;a href="https://en.wikipedia.org/wiki/Data_mapper_pattern">Data Mapper Pattern&lt;/a> abstracts the persistent storage from
your application.&lt;/p></description></item><item><title>Design of Software Solutions</title><link>https://www.jeffhui.net/2016/19-design-of-software-solutions.html</link><pubDate>Sat, 30 Apr 2016 00:00:00 +0000</pubDate><guid>https://www.jeffhui.net/2016/19-design-of-software-solutions.html</guid><description>&lt;p>What&amp;rsquo;s the best way to model a solution? In software, there&amp;rsquo;s several common
ways of building solutions that solve specific problems. It&amp;rsquo;s worth trying to
identify their characteristics and the tradeoffs they make.&lt;/p>
&lt;h2 id="architect-the-software-after-the-current-problem">Architect the Software After the Current Problem&lt;/h2>
&lt;p>The easiest is way to model software. There&amp;rsquo;s no need to take into consideration
of future solutions the user may want.&lt;/p>
&lt;p>Sometimes this is what you need. If you&amp;rsquo;re writing a throw-away program, the
fastest possible way to implement it is to codify for the exact problem you&amp;rsquo;re
trying to solve. An example are most shell scripts. They tend to not be
abstracted and usually automate a very specific task.&lt;/p></description></item><item><title>Editing Text (Basics)</title><link>https://www.jeffhui.net/2016/18-editing-text-basics/</link><pubDate>Thu, 31 Mar 2016 00:00:00 +0000</pubDate><guid>https://www.jeffhui.net/2016/18-editing-text-basics/</guid><description>&lt;h1 id="background">Background&lt;/h1>
&lt;p>The problem seems simple: open, edit, and save text files. This can range from
JSON files to source code like every other editor.&lt;/p>
&lt;p>Turns out, this is a relatively difficult problem. The rise of
&lt;a href="https://atom.io" title="Github Atom">javascript&lt;/a> &lt;a href="https://code.visualstudio.com/" title="Microsoft Visual Studio Code">text&lt;/a> &lt;a href="http://brackets.io/" title="Adobe Brackets">editors&lt;/a> surfaces the performance
problem of editing large text. It&amp;rsquo;s a non-trivial problem. There are several
desirable characteristics that editors want:&lt;/p>
&lt;ul>
&lt;li>Editors need to &lt;strong>optimize for edits&lt;/strong>. Having immediate feedback for changes
is paramount to text editing. This includes editing large files.&lt;/li>
&lt;li>Editors need to &lt;strong>optimize for reads&lt;/strong>. This is implied for optimized edits so
that users can see immediate feedback to their edit. This also includes
support for large files.&lt;/li>
&lt;li>Editors should &lt;strong>minimize memory usage&lt;/strong>. Reduced overhead for storage of text
leaves more memory for more text buffers. This is useful for developers
editing multiple projects at once (eg - microservices).&lt;/li>
&lt;/ul>
&lt;p>Different data structures support these requirements in varying degrees of
success. For the sake of this article, I&amp;rsquo;m ignoring many other features editors
usually have:&lt;/p></description></item><item><title>Observation</title><link>https://www.jeffhui.net/2016/17-observation.html</link><pubDate>Mon, 29 Feb 2016 00:00:00 +0000</pubDate><guid>https://www.jeffhui.net/2016/17-observation.html</guid><description>&lt;p>The more you learn, the more this skill seems to be necessary. When missing a
bug or a refactor opportunity, I wonder how did I miss this? Sure, everyone
wants to learn from their mistakes. But noticing the little details gives you
the opportunity to adapt. Massive function definitions start off looking like
a common pattern for code that needs to be refactored. Those dozen one-letter
variables names probably should be better named. Shadowing a variable is prone
to introduce errors in the future. All those mental notes form from being able
to observe it.&lt;/p></description></item><item><title>Modeling the Domain</title><link>https://www.jeffhui.net/2016/16-domain-modeling/</link><pubDate>Sun, 31 Jan 2016 00:00:00 +0000</pubDate><guid>https://www.jeffhui.net/2016/16-domain-modeling/</guid><description>&lt;p>Let&amp;rsquo;s mentally build an API for an e-commerce site. Let&amp;rsquo;s say we&amp;rsquo;re tasked
with building the cart &amp;amp; checkout portion of the API. Building a RESTful API
seems like the natural choice. At first, a Cart seems like any other model
entity in the system. But what about a multi-page checkout step?&lt;/p>
&lt;ul>
&lt;li>Allow partial updating of the Cart model (sounds like a job for PATCH). We
need to preserve as much information as possible on the server to allow the
user to pick up where they left off.&lt;/li>
&lt;li>Each update needs to be validated against the current known state of the
world. Store credit may not fully cover an order that has an upgraded shipping
method specified later on.&lt;/li>
&lt;li>The final cart has to be &amp;ldquo;committed&amp;rdquo; where final validations need to be
performed before committed.&lt;/li>
&lt;li>And finally, the committed cart requires taking to third party APIs all along
the way (shipping, credit card processing, tax calculations) as well as at the
commit point.&lt;/li>
&lt;/ul>
&lt;p>REST doesn&amp;rsquo;t provide an easy way to model this.&lt;/p></description></item><item><title>Daily Processes Check-In</title><link>https://www.jeffhui.net/2015/15-daily-processes.html</link><pubDate>Mon, 30 Nov 2015 00:00:00 +0000</pubDate><guid>https://www.jeffhui.net/2015/15-daily-processes.html</guid><description>&lt;p>&lt;em>Instead of sounding prescriptive, this article is much more descriptive.&lt;/em>&lt;/p>
&lt;p>I&amp;rsquo;m describing my regular workflows: what is working; what isn&amp;rsquo;t working. I&amp;rsquo;m
documenting this for completely selfish reasons since it&amp;rsquo;s useful to track
progression (if any). It happens to be a great inflection point since a recent
illness has thrown me off my routine in the past week.&lt;/p>
&lt;hr>
&lt;p>Like most people, there&amp;rsquo;s a need to regularly do:&lt;/p>
&lt;ul>
&lt;li>Respond to messages (twitter, facebook, texts)&lt;/li>
&lt;li>Respond to mail (physical, email)&lt;/li>
&lt;li>Attend events (birthdays, social gatherings, meetups)&lt;/li>
&lt;li>Capture ideas (they tend to come up in the most random places)&lt;/li>
&lt;li>Living (rent, bills, taxes, laundry, cleaning)&lt;/li>
&lt;/ul>
&lt;p>All while (attempting) to achieve other goals:&lt;/p></description></item><item><title>Going Fast by Going Slow</title><link>https://www.jeffhui.net/2015/14-going-fast-by-going-slow.html</link><pubDate>Sat, 31 Oct 2015 00:00:00 +0000</pubDate><guid>https://www.jeffhui.net/2015/14-going-fast-by-going-slow.html</guid><description>&lt;p>People always ask about how did you learn this or work so quickly doing that?
It&amp;rsquo;s a tough question to answer elegantly. And it&amp;rsquo;s a cop-out to vaguely say I
spent my free time looking into that particular topic. It&amp;rsquo;s a
socially-acceptable excuse.&lt;/p>
&lt;p>But no doubt that this requires time. The time spent learning comes from
somewhere, since we all only have 24 hours in a day for this. In our field,
there&amp;rsquo;s always time you must dedicate to learning to keep up to date.&lt;/p></description></item><item><title>Process is King</title><link>https://www.jeffhui.net/2015/13-Process-is-King.html</link><pubDate>Wed, 30 Sep 2015 00:00:00 +0000</pubDate><guid>https://www.jeffhui.net/2015/13-Process-is-King.html</guid><description>&lt;p>There&amp;rsquo;s a process behind every result.&lt;/p>
&lt;p>If you say, &amp;ldquo;we have no process, there&amp;rsquo;s no meetings&amp;rdquo;, then that&amp;rsquo;s your process.
Admitting to no process simply indicates that you don&amp;rsquo;t have it formalized. A
poorly defined process hurts. Processes enable efficiency and consistency. They
can also act like a communication protocol among team members, teams, and
organizations. Process can improve your quality.&lt;/p>
&lt;p>Let&amp;rsquo;s think about how you deploy an application. What does that process look
like? A poorly defined deployment process is inconsistent – something
undesirable for a deployment. At minimum, a quick checklist works:&lt;/p></description></item><item><title>Communicating as an Engineer</title><link>https://www.jeffhui.net/2015/12-communicating-as-an-engineer.html</link><pubDate>Mon, 31 Aug 2015 00:00:00 +0000</pubDate><guid>https://www.jeffhui.net/2015/12-communicating-as-an-engineer.html</guid><description>&lt;p>As an engineer, one of the most valuable skills you can have is to communicate
effectively. This applies both to your fellow engineers as well as non-engineers
(PMs, designers, business). Obviously, this advice is generally applicable, but
many engineers don&amp;rsquo;t craft their communication to the business well. Common
problems are:&lt;/p>
&lt;ul>
&lt;li>Talking &lt;em>too much&lt;/em> about technical implementation.&lt;/li>
&lt;li>Talking &lt;em>too little&lt;/em> about technical implementation.&lt;/li>
&lt;/ul>
&lt;p>Too much technical implementation drowns out the important details that
businesses are concerned about. It drags on discussions and meetings
unnecessarily. Imagine if a designer talked for hours about how they picked the
correct border radius value and color for their buttons in a meeting. That&amp;rsquo;s a
waste of time for business stakeholders and engineers in that meeting. Getting
far into the weeds like that quickly wastes discussions or
meetings&lt;!-- raw HTML omitted -->&lt;!-- raw HTML omitted -->1&lt;!-- raw HTML omitted -->&lt;!-- raw HTML omitted -->.&lt;/p></description></item><item><title>Mental Schemas</title><link>https://www.jeffhui.net/2015/11-mental-schemas.html</link><pubDate>Thu, 30 Jul 2015 00:00:00 +0000</pubDate><guid>https://www.jeffhui.net/2015/11-mental-schemas.html</guid><description>&lt;p>It is difficult to always be improving in the software industry. In creative
fields, many artists &lt;a href="https://youtu.be/ikAb-NYkseI?t=9m41s">talk&lt;/a> about
&lt;a href="http://www.goodreads.com/quotes/309485-nobody-tells-this-to-people-who-are-beginners-i-wish">churn&lt;/a>.
When starting out, there&amp;rsquo;s an enormous amount of work to produce to get better.
If you&amp;rsquo;re new, there&amp;rsquo;s a massive amount of bad code you need to write. That&amp;rsquo;s
OK, it&amp;rsquo;s necessary. But the rate of improvement decays as time progresses. As
your notoriety grows, you can no longer just crank out code to get better, how
can you preserve some rate of improvement? It feels like the rate of learning
looks like this:&lt;/p></description></item><item><title>Software as Bridges</title><link>https://www.jeffhui.net/2015/10-software-bridges.html</link><pubDate>Mon, 29 Jun 2015 00:00:00 +0000</pubDate><guid>https://www.jeffhui.net/2015/10-software-bridges.html</guid><description>&lt;hr>
&lt;p>Software is always challenging to explain to non-engineers and having a metaphor
is valuable to explain complex concepts. Bridges happen to be a good analogy to
software. But the devil is always in the details.&lt;/p>
&lt;hr>
&lt;p>&lt;img loading="lazy" src="10-software-bridges/MillauBridge.jpg" alt="Millau Viaduct" />&lt;/p>
&lt;p>Any piece of software provides a benefit to its users. It&amp;rsquo;s similar to people
using bridges to cross rivers. As with bridges, many kinds of software can solve
the same problems.&lt;/p>
&lt;p>Some bridges support many cars and pedestrians which is analogous to a
high-throughput like a server that can support many users. Others are very nice
walkways with trees, a highly usable piece of software that supports only a few
users. Most of the time, users only see the bridge from the top. Like seeing
only the tip of an iceberg.&lt;/p></description></item><item><title>Seeking Simplicity</title><link>https://www.jeffhui.net/2015/09-seeking-simplicity.html</link><pubDate>Sun, 03 May 2015 00:00:00 +0000</pubDate><guid>https://www.jeffhui.net/2015/09-seeking-simplicity.html</guid><description>&lt;p>What is simple?&lt;/p>
&lt;p>Rich Hickey makes a good abstract definition, but it can be difficult to
translate to everyday code. I encourage you to
&lt;a href="http://www.infoq.com/presentations/Simple-Made-Easy">watch that&lt;/a> before
returning to this. I&amp;rsquo;ll still be here.&lt;/p>
&lt;p>Ok, let&amp;rsquo;s start at that definition. Hickey&amp;rsquo;s simplicity is the &lt;strong>disentangling
of concerns&lt;/strong>. It&amp;rsquo;s easy to convolute from what seems like straight-forward
statement.&lt;/p>
&lt;p>For example, a high-level example would be what domain-driven design proponents
argue for. Separate solving your problem domain from the machinery that you use
to solve it. Separate How from What or When.&lt;/p></description></item><item><title>Moving On</title><link>https://www.jeffhui.net/2015/08-moving-on.html</link><pubDate>Wed, 15 Apr 2015 00:00:00 +0000</pubDate><guid>https://www.jeffhui.net/2015/08-moving-on.html</guid><description>&lt;p>It&amp;rsquo;s a bittersweet end to a chapter. I&amp;rsquo;ve thoroughly enjoyed my time at Pivotal
Labs. I met a lot of great friends. I paired and talked with geniuses and
newcomers alike. And I&amp;rsquo;d recommend anyone with an opportunity to work at Labs to
take it immediately.&lt;/p>
&lt;p>I look back with great memories, shared turmoil, and personal growth. As an
introvert, it was a boundary-expanded endeavor: pair programming every day. I
learned the value of tests which is evident to most of the major open source
work I&amp;rsquo;ve contributed to. I&amp;rsquo;ve sharpened my mind by the discussions I&amp;rsquo;ve had
there.&lt;/p></description></item><item><title>Generative Testing</title><link>https://www.jeffhui.net/2015/07-Generative-Testing.html</link><pubDate>Sat, 31 Jan 2015 00:00:00 +0000</pubDate><guid>https://www.jeffhui.net/2015/07-Generative-Testing.html</guid><description>&lt;p>It&amp;rsquo;s no secret that I&amp;rsquo;ve been interested in testing. Most of the &lt;a href="https://github.com/pivotal/cedar" title="Cedar - BDD for Objective-C">work&lt;/a>
&lt;a href="https://github.com/Quick/Quick" title="Quick - BDD for Swift and Objective-C">I&amp;rsquo;ve&lt;/a> &lt;a href="https://github.com/Nimble/Nimble" title="Nimble Matcher Library for Swift and Objective-C">done&lt;/a> are around example-based testing. While useful,
it&amp;rsquo;s interesting to look at other communities for inspiration. I&amp;rsquo;m specifically
fascinated in the functional programming community. Generative testing in
particular. It was popularized in the early 2000s by a famous implementation in
Haskell, &lt;a href="https://hackage.haskell.org/package/QuickCheck">QuickCheck&lt;/a>.&lt;/p>
&lt;p>In short, generative testing allows you to specify properties your software
should have. Then the testing library &lt;em>generates&lt;/em> test cases. It&amp;rsquo;s an
alternative path the functional community has taken when it comes to testing.
This becomes evident since testing functional code becomes mostly boilerplate
management:&lt;/p></description></item><item><title>Parsing JSON in Objective-C - Part 2</title><link>https://www.jeffhui.net/2014/06-Parsing-JSON-in-Objective-C-Part-2.html</link><pubDate>Sat, 08 Nov 2014 00:00:00 +0000</pubDate><guid>https://www.jeffhui.net/2014/06-Parsing-JSON-in-Objective-C-Part-2.html</guid><description>&lt;p>&lt;em>Note: This previously was on
&lt;a href="http://pivotallabs.com/parsing-json-objective-c-part-2/">Pivotal Labs blog&lt;/a>.&lt;/em>&lt;/p>
&lt;p>In the &lt;a href="05-parsing-json-in-objective-c-part-1">previous article&lt;/a>, we used TDD to
parse JSON into our &lt;code>Person&lt;/code> model and refactored the code under test. In part
2, we&amp;rsquo;re going to refactor the code further to be more reusable and extendable.
All the code in this article will also be in the
&lt;a href="https://github.com/jeffh/ParsingJSON/">same repository&lt;/a>.&lt;/p>
&lt;h1 id="redesign">Redesign&lt;/h1>
&lt;p>The refactorings in the previous article were fairly straightforward and
mechanical. Ultimately, we’ll need to break apart different concerns of this
code. One approach would be to start with some questions:&lt;/p></description></item><item><title>Parsing JSON in Objective-C - Part 1</title><link>https://www.jeffhui.net/2014/05-Parsing-JSON-in-Objective-C-Part-1.html</link><pubDate>Fri, 24 Oct 2014 00:00:00 -0700</pubDate><guid>https://www.jeffhui.net/2014/05-Parsing-JSON-in-Objective-C-Part-1.html</guid><description>&lt;p>&lt;em>This post was originally written on the
&lt;a href="http://pivotallabs.com/parsing-json-in-objective-c">Pivotal Labs Blog&lt;/a>.&lt;/em>&lt;/p>
&lt;p>JSON parsing is a frequent task for clients interfacing with any recent web API.
Those web services frequently vary in quality:&lt;/p>
&lt;ul>
&lt;li>Is the API following a RESTful design pattern?&lt;/li>
&lt;li>Is it providing an object graph or just a single/collection of objects in the
JSON response?&lt;/li>
&lt;li>What are the data types of the fields being returned? Can they be relied upon?&lt;/li>
&lt;li>How much work are clients duplicating to work around the server (e.g. -
Performance, Business Logic, etc.)?&lt;/li>
&lt;/ul>
&lt;p>If you have full control of the resulting API endpoints, then it is easy to
build or fix the API to your client’s specific needs. Controlling the incidental
complexity can be challenging for APIs you do not control, or which have to
support a variety of clients.&lt;/p></description></item><item><title>Reverse Engineering Objective-C</title><link>https://www.jeffhui.net/2014/03-reverse-engineering-objective-c.html</link><pubDate>Sat, 26 Jul 2014 00:00:00 -0700</pubDate><guid>https://www.jeffhui.net/2014/03-reverse-engineering-objective-c.html</guid><description>&lt;p>Languages that have dynamic introspection provide powerful meta-programming
capabilities. This is generally done at runtime with additional memory used for
storing metadata - such as types and method signatures. But they also provide
the same power for people reverse engineering your code.&lt;/p>
&lt;p>Let’s look at Objective-C, a simple code snippet:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-objc" data-lang="objc">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">@interface&lt;/span> &lt;span style="color:#a6e22e">MyObject&lt;/span> : &lt;span style="color:#a6e22e">NSObject&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">@end&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">@implementation&lt;/span> &lt;span style="color:#a6e22e">MyObject&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> NSInteger _number;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>- (&lt;span style="color:#66d9ef">void&lt;/span>)&lt;span style="color:#a6e22e">doSomething&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> _number&lt;span style="color:#f92672">++&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> NSLog(&lt;span style="color:#e6db74">@&amp;#34;The %@&amp;#34;&lt;/span>, [self _doSomethingSpecial:_number]);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>- (NSString &lt;span style="color:#f92672">*&lt;/span>)&lt;span style="color:#a6e22e">_doSomethingSpecial:&lt;/span>(NSInteger)number
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> [NSString stringWithFormat:&lt;span style="color:#e6db74">@&amp;#34;Number: %d&amp;#34;&lt;/span>, number];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">@end&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Simple enough, but what if we don’t have the source? Let’s step back to how
Objective-C works…&lt;/p></description></item><item><title>Adapting Binary Search</title><link>https://www.jeffhui.net/2014/02-adapting-binary-search.html</link><pubDate>Fri, 25 Jul 2014 00:00:00 -0700</pubDate><guid>https://www.jeffhui.net/2014/02-adapting-binary-search.html</guid><description>&lt;p>It’s great to use classic algorithms to solve problems at hand. Take this
problem of ellipsis:&lt;/p>
&lt;blockquote>
&lt;p>For a given text. Fit the maximum number of words that fits in the given size,
append “… More” if there was truncation.&lt;/p>
&lt;/blockquote>
&lt;p>No, &lt;code>NSLineBreakModeTailTruncation&lt;/code> will not work. We need different text.&lt;/p>
&lt;p>The näive solution would simply to cut a word one-by-one until it fits with a
custom ellipsis text:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-objc" data-lang="objc">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">@implementation&lt;/span> &lt;span style="color:#a6e22e">NSString&lt;/span> (CustomEllipsis)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>- (NSString &lt;span style="color:#f92672">*&lt;/span>)&lt;span style="color:#a6e22e">textThatFitsSize:&lt;/span>(CGSize)size &lt;span style="color:#a6e22e">ellipsisText:&lt;/span>(NSString &lt;span style="color:#f92672">*&lt;/span>)text
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> CGSize infiniteSize &lt;span style="color:#f92672">=&lt;/span> CGSizeMake(size.width, INFINITY);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> CGSize fullSize &lt;span style="color:#f92672">=&lt;/span> [text boundingRectWithSize:infiniteSize options:NSStringDrawingUsesFontLeading&lt;span style="color:#f92672">|&lt;/span>NSStringDrawingUsesLineFragmentOrigin
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> context:nil].size;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// if text fits
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> (fullSize.height &lt;span style="color:#f92672">&amp;lt;=&lt;/span> size.height) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> text;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> NSString &lt;span style="color:#f92672">*&lt;/span>finalString &lt;span style="color:#f92672">=&lt;/span> nil;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// if text doesn&amp;#39;t fit
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> NSMutableArray &lt;span style="color:#f92672">*&lt;/span>words &lt;span style="color:#f92672">=&lt;/span> [[text componentsSeparatedByString:&lt;span style="color:#e6db74">@&amp;#34; &amp;#34;&lt;/span>] mutableCopy];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">while&lt;/span> (fullSize.height &lt;span style="color:#f92672">&amp;gt;&lt;/span> size.height) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> [words removeLastObject];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> finalString &lt;span style="color:#f92672">=&lt;/span> [words componentsJoinByString:&lt;span style="color:#e6db74">@&amp;#34; &amp;#34;&lt;/span>];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> finalString &lt;span style="color:#f92672">=&lt;/span> [finalString stringByAppendString:&lt;span style="color:#e6db74">@&amp;#34;... MORE&amp;#34;&lt;/span>];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> fullSize &lt;span style="color:#f92672">=&lt;/span> [modifiedString boundingRectWithSize:infiniteSize options:NSStringDrawingUsesFontLeading&lt;span style="color:#f92672">|&lt;/span>NSStringDrawingUsesLineFragmentOrigin context:nil].size;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> finalString;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">@end&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Run that in a table cell and you’ve got performance problems!&lt;/p></description></item><item><title>Evaluating New Techonologies</title><link>https://www.jeffhui.net/2014/01-evaluating-technologies.html</link><pubDate>Thu, 24 Jul 2014 00:00:00 -0700</pubDate><guid>https://www.jeffhui.net/2014/01-evaluating-technologies.html</guid><description>&lt;p>Every time you look at a new (or familiar) technology, you should ask: What are
the tradeoffs?&lt;/p>
&lt;p>It&amp;rsquo;s obvious to see the benefits of something - it&amp;rsquo;s generally advertised
everywhere. Everyone is always shouting the pros of X.&lt;/p>
&lt;ul>
&lt;li>&amp;ldquo;X does Y easier&amp;rdquo;&lt;/li>
&lt;li>&amp;ldquo;X does Y faster&amp;rdquo;&lt;/li>
&lt;li>&amp;ldquo;X integrates with Y&amp;rdquo;&lt;/li>
&lt;/ul>
&lt;p>Pros tend to flood the internet way more than cons:&lt;/p>
&lt;ul>
&lt;li>X makes Z harder&lt;/li>
&lt;li>X makes Z slower&lt;/li>
&lt;li>X locks you into Y&lt;/li>
&lt;li>X does Y, at the expense of Z&lt;/li>
&lt;/ul>
&lt;p>These are harder to find. Especially when the library is relatively new. But you
can imagine based on how critical it is on your software stack.&lt;/p></description></item><item><title>Objective-C: Lazy Sequences</title><link>https://www.jeffhui.net/2014/04-objective-c-lazy-sequences.html</link><pubDate>Mon, 07 Jul 2014 00:00:00 -0700</pubDate><guid>https://www.jeffhui.net/2014/04-objective-c-lazy-sequences.html</guid><description>&lt;p>Lazy data structures are a powerful abstraction can increase the readability of
your program while encouraging separation of concerns.&lt;/p>
&lt;p>What are they? Simply put, they are data structures that &amp;ldquo;realize&amp;rdquo; what they
contain when they&amp;rsquo;re needed (or right before they&amp;rsquo;re needed).&lt;/p>
&lt;p>What can you do with lazy data structures? How about a page-scraper that
paginates as needed:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-ruby" data-lang="ruby">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># pseudocode&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>seed_url &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;http://example.com/page/&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># generate a lazy list of urls:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># - http://example.com/page/1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># - http://example.com/page/2&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># - etc.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>urls &lt;span style="color:#f92672">=&lt;/span> lazy {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> (i &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>; i &lt;span style="color:#f92672">&amp;lt;&lt;/span> &lt;span style="color:#ae81ff">100&lt;/span>; i&lt;span style="color:#f92672">++&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">yield&lt;/span> seed_url &lt;span style="color:#f92672">+&lt;/span> string(i)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># a lazy list of html pages&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>pages &lt;span style="color:#f92672">=&lt;/span> map(urls, fetchURLPageContents)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># a lazy list of list of links&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>links_per_page &lt;span style="color:#f92672">=&lt;/span> map(pages, extractLinksFromHTML)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># flatten to just a lazy list of links&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>links &lt;span style="color:#f92672">=&lt;/span> join(links_per_page)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># do stuff with links&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">for&lt;/span> link &lt;span style="color:#66d9ef">in&lt;/span> links {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> record(link)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This creates a powerful abstraction that separates tasks your program needs to get
done behind an implicit interface. The ending for loop doesn&amp;rsquo;t need to know that
those links came from multiple page fetches or the file system. If the loop
short-circuited, then it minimizes the number of unnecessary fetches.&lt;/p></description></item><item><title>Hi there, I'm Jeff!</title><link>https://www.jeffhui.net/about/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.jeffhui.net/about/</guid><description>&lt;p>&lt;picture>
&lt;source srcset="https://www.jeffhui.net/about/profile2_hu14524567662534211677.webp 480w" type="image/webp">
&lt;source srcset="https://www.jeffhui.net/about/profile2_hu1806372968952627248.jpg 480w" type="image/jpeg">
&lt;img loading="lazy" src="https://www.jeffhui.net/about/profile2.png" alt="Photo" >
&lt;/picture>&lt;/p>
&lt;p>I&amp;rsquo;m a software engineer passionate about software engineering - which is the
never-ending challenge of balance of perfection and shipping.&lt;/p>
&lt;p>In the past, I was a &lt;a href="https://pivotal.io/labs">consultant&lt;/a> working on iOS
applications using the C-family of languages and Swift. Clients ranged from
early stealth startups to Fortune 500 companies. In iOS, I&amp;rsquo;m probably best known
for work on &lt;a href="https://github.com/quick/nimble">Nimble&lt;/a> or
&lt;a href="https://github.com/pivotal/cedar">Cedar&lt;/a> or giving some talks in the early days
of Swift. Although, I&amp;rsquo;ve personally learned the most while making
&lt;a href="https://github.com/jeffh/Hydrant">Hydrant&lt;/a>.&lt;/p></description></item><item><title>Resume</title><link>https://www.jeffhui.net/resume/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.jeffhui.net/resume/</guid><description>&lt;p>&lt;em>There&amp;rsquo;s also a &lt;a href="jeffhui.pdf">PDF version&lt;/a> of my resume. Engineers may be interested
in &lt;a href="https://github.com/jeffh">my Github profile&lt;/a>.&lt;/em>&lt;/p>
&lt;h2 id="goals">Goals&lt;/h2>
&lt;p>My professional goal is continuous growth and learning. This can be as broad as
handling financial audits. Or as narrow as using a new technology. I revel in
collaborating with my peers or other roles. Communicating is not just
enunciating one&amp;rsquo;s intent, but to make sure terminology used by different
professions are aligned.&lt;/p>
&lt;p>&lt;strong>Note&lt;/strong>: I&amp;rsquo;m not looking for a managerial role at this time. I want to
refocus based on technical skills.&lt;/p></description></item></channel></rss>