tag:noclevercode.svbtle.com,2014:/feedNo Clever Code2023-12-05T21:39:27-08:00Richard Havenhttps://noclevercode.svbtle.comSvbtle.comtag:noclevercode.svbtle.com,2014:Post/we-can-afford-to-buy-vowels-now2023-12-05T21:39:27-08:002023-12-05T21:39:27-08:00We Can Afford To Buy Vowels<p>TL;DR Programs must be written for people to read, and only incidentally for machines to execute —Harold Abelson</p>
<p>In the old days <eyeroll/>, we had 26 variables: the letters of the alphabet. The next leap in programming, we could add one digit after the letter. That was not good enough for development then, and it surely is not now</p>
<p>With no restriction on the length of names, the vestigial traditions of opaque naming cannot hide behind brevity or idiom, and certainly not consistency<sup id="fnref1"><a href="#fn1">1</a></sup>. The only measure for names is their utility in communication</p>
<p>A line of code like <code class="prettyprint">r.Get(true)</code> is opaque. While IDEs can help decode what the <code class="prettyprint">r</code> and the <code class="prettyprint">true</code> mean, using descriptive names allows the code to speak for itself: <code class="prettyprint">orderReader.Get(CacheDataOk)</code></p>
<p>Multi-letter abbreviations harken back to Hungarian notation: abjad<sup id="fnref2"><a href="#fn2">2</a></sup> type names prefixed or suffixed to a (presumably) descriptive name (e.g. submitBtn). Or they presume screens are fixed at 80 x 40 characters (e.g. DTE for “Date”). While names <em>can</em> be too long<sup id="fnref3"><a href="#fn3">3</a></sup>, unabbreviated names are easier and more accurate for humans to read; code readers should be free to focus on the <em>why</em> of the code, not the <em>what does this <u>mean</u>‽</em> of the code</p>
<blockquote class="short">
<p>Good code reads like well-written prose —Grady Booch</p>
</blockquote>
<div class="footnotes">
<hr>
<ol>
<li id="fn1">
<p>emerson <a href="#fnref1">↩</a></p>
</li>
<li id="fn2">
<p>abjad: a writing style omitting vowels (e.g. Semitic) <a href="#fnref2">↩</a></p>
</li>
<li id="fn3">
<p>my coworkers won’t believe I said this <a href="#fnref3">↩</a></p>
</li>
</ol>
</div>
tag:noclevercode.svbtle.com,2014:Post/a-function-s-interface-is-it-s-bond2023-12-05T21:16:05-08:002023-12-05T21:16:05-08:00A Function's Interface Is It's Bond<p>TL;DR: A function must respect all arguments or return an error</p>
<h1 id="the-arguments_1">The Arguments <a class="head_anchor" href="#the-arguments_1">#</a>
</h1>
<p>The only realistic way a function can fail its interface is how it treats arguments as mis-typed arguments or return values are usually caught by a framework</p>
<h1 id="all-the-arguments_1">All The Arguments <a class="head_anchor" href="#all-the-arguments_1">#</a>
</h1>
<p>Be they required or optional arguments that are present, functions must respect all the arguments; they cannot ignore some because they are inconvenient or contradictory</p>
<h2 id="quoti39d-like-a-number-four-with-no-cheesequo_2">“I’d like a number four with no cheese” <a class="head_anchor" href="#quoti39d-like-a-number-four-with-no-cheesequo_2">#</a>
</h2>
<p>One cannot stop paying attention just because we know what a #4 is. Functions and especially REST endpoints often accept resource ids or primary key values, which implicitly identify specific resources. Tempting as this easy lookup is, the function must apply <em>all</em> the arguments even if they are additional criteria. With a key value in hand, the function does not <em>need</em> additional criteria, but it cannot ignore them</p>
<p>A function could optimize<sup id="fnref1"><a href="#fn1">1</a></sup> by having a dedicated code path retrieving data via the key and testing that data against any additional criteria while having another code path to query by criteria without a key value, but that is unlikely to be a good decision. Datastores usually<sup id="fnref2"><a href="#fn2">2</a></sup> are perfectly capable of making this sort of optimization</p>
<h2 id="no-one-would-ask-for-that_2">No One Would Ask For That <a class="head_anchor" href="#no-one-would-ask-for-that_2">#</a>
</h2>
<p>The function cannot make assumptions about what the caller wants; it must provide what the caller actually asked for, even if that seems nonsensical</p>
<p>While a USA address’ state is implicit in its zip code<sup id="fnref3"><a href="#fn3">3</a></sup>, if a function accepts both state and zip code, it must ensure that its results meet both requirements: if the supplied state does not match the implicit state from the zip code, then it must return no addresses</p>
<h1 id="and-nothing-but-the-arguments_1">And Nothing But the Arguments <a class="head_anchor" href="#and-nothing-but-the-arguments_1">#</a>
</h1>
<p>If a function abides by all the arguments it receives, then receiving an unknown argument must be an error condition. For compiled languages, spurious arguments are impossible. For other languages, they might be allowed. Take the time to detect and report them</p>
<p>HTTP is a line format: a text message where the contents have semantic meaning depending on what part of the message one looks at. One can often translate the HTTP method (verb) and path into a function call and required parameter (with the query-string acting as additional, usually optional, parameters). While HTTP frameworks can often detect extra and missing parameters an error (404 or 422), it is usually an option</p>
<div class="footnotes">
<hr>
<ol>
<li id="fn1">
<p>“…; premature optimization is the root of all evil (or at least most of it) in programming.” - Donald Knuth <a href="#fnref1">↩</a></p>
</li>
<li id="fn2">
<p>always? <a href="#fnref2">↩</a></p>
</li>
<li id="fn3">
<p>a business rule of the USPS <a href="#fnref3">↩</a></p>
</li>
</ol>
</div>
tag:noclevercode.svbtle.com,2014:Post/walk-don-t-race2023-08-28T21:42:39-07:002023-08-28T21:42:39-07:00Walk, Don't Race<h1 id="tldr_1">TL;DR <a class="head_anchor" href="#tldr_1">#</a>
</h1>
<p><a href="https://svbtleusercontent.com/xcwSGd3UgL8PZoMX6oBuHp0xspap.png"><img src="https://svbtleusercontent.com/xcwSGd3UgL8PZoMX6oBuHp0xspap_small.png" alt="Don't Race.png"></a></p>
<h1 id="chachachanges_1">Cha-Cha-Changes <a class="head_anchor" href="#chachachanges_1">#</a>
</h1>
<p>Breaking changes happen, and the breaking occurs between the layers (e.g. UI and API, API and database). Rather than trying to release new layers simultaneously (especially with edge distribution), commit the time and effort to a four or five-step pattern that ensures the layers work perfectly at all times, losing no data</p>
<h2 id="1-create-the-change-you-want-to-be_2">1. Create the Change You Want To Be <a class="head_anchor" href="#1-create-the-change-you-want-to-be_2">#</a>
</h2>
<p>Create the goal: the new schema; the new endpoint; the new protocol. Test it, benchmark it, and be happy with it. Copy and translate the old system’s data to the new system (handle the subsequent data changes in step 4)<br>
For example, instead of changing the data type of a column, create a new column of the desired type</p>
<h2 id="2-embrace-the-new-while-respecting-the-old_2">2. Embrace the New While Respecting the Old <a class="head_anchor" href="#2-embrace-the-new-while-respecting-the-old_2">#</a>
</h2><h3 id="the-problem-with-data_3">The Problem With Data <a class="head_anchor" href="#the-problem-with-data_3">#</a>
</h3>
<p>It’s always the data</p>
<p>The transition depends on how the old and new systems share data</p>
<ul>
<li>Type A: if the clients are making read-only calls (e.g. calculations), then both systems run independently; updated clients choose to call the new system in step 4</li>
<li>Type B: If the clients modify data, then clients must update <u>both</u> datastores (or the datastores must synchronize with each other — e.g. two-way database synchronization) or both the original and the replacement columns. Wait until Step 3 to ensure that the old and new data sets match before depending on the new datastore</li>
</ul>
<h2 id="3-what-is-old-is-new-again_2">3. What Is Old Is New Again <a class="head_anchor" href="#3-what-is-old-is-new-again_2">#</a>
</h2>
<p>For Types B once <em>all</em> of the clients update the new dataset/column, synchronize the data from old to new to catch any missing data (e.g. data updated since step 1)</p>
<h2 id="4-when-choosing-between-two-evils-choose-the_2">4. When Choosing Between Two Evils, Choose the Lesser One <a class="head_anchor" href="#4-when-choosing-between-two-evils-choose-the_2">#</a>
</h2>
<p>All the clients stop depending on the old datastore, columns, APIs, etc.</p>
<h2 id="5-i-hope-no-one-is-using-this_2">5. I Hope No One Is Using This … <a class="head_anchor" href="#5-i-hope-no-one-is-using-this_2">#</a>
</h2>
<p>Once all the clients stop using the old datastore, remove it</p>
<h1 id="make-it-invisible-with-a-proxy_1">Make it invisible with a Proxy <a class="head_anchor" href="#make-it-invisible-with-a-proxy_1">#</a>
</h1>
<p>If one cannot influence one’s clients to participate in the hijinks described above, create a proxy or facade with the old system’s interface that will do the double-updates to the new system and, when ready, use the new system for getting data</p>
<p>This proxy can remain as a translation layer or deprecate as clients lose the option of the old interface</p>
tag:noclevercode.svbtle.com,2014:Post/you-don-t-know-why-i-ve-called-you2023-08-28T11:06:05-07:002023-08-28T11:06:05-07:00You Don't Know Why I've Called You<p>An advantage of functions (or methods or subroutines) is boxing up a part of a process so it does not clutter up the code that calls it. Like telling one’s spouse to “take out the trash”, it reduces all an operation’s steps into a single name. The code in a function needs only to perform a single task<sup id="fnref1"><a href="#fn1">1</a></sup> according to all the arguments the caller passed in<sup id="fnref2"><a href="#fn2">2</a></sup> or signalling the caller of an error</p>
<p>As the function does not know who called it or why, it does not have the context to know how to react to errors. It does not know if it should log them (and if so, the logging level), retry an operation, terminate the entire process, or ignore the error. The only thing it can do is notify its caller of the error. The caller might have enough information to know what to do; if it does not, it passes the error to <em>its</em> caller</p>
<p>By acknowledging the limitations of its tiny perspective, a function does not try to force its protocols onto any application that uses it, and so avoids the almost comical hacks and workarounds needed to prevent third-party libraries from swamping error logs with uninteresting entries</p>
<p>In a top-down hierarchy of functions, it encourages decision-making at a specific level, and it makes error logging consistent (because all the logging code tends to be next to each other)</p>
<div class="footnotes">
<hr>
<ol>
<li id="fn1">
<p>Which might entail calling other functions, to which the same rules apply <a href="#fnref1">↩</a></p>
</li>
<li id="fn2">
<p>No ignoring inconvenient ones <a href="#fnref2">↩</a></p>
</li>
</ol>
</div>
tag:noclevercode.svbtle.com,2014:Post/a-simple-caching-pattern-in-go2023-03-17T13:49:47-07:002023-03-17T13:49:47-07:00A Simple Caching Pattern in Go<p>One might use it like this:</p>
<pre><code class="prettyprint lang-go">var myCache = NewOurCache(0, calculateTimestamp)
// ...
var myValue time.Time = myCache.Open(dateText, timeText, Location)
</code></pre>
<p><code class="prettyprint">OurCacheType</code> is an alias for the actual data cached. It can be <em>any</em> type including a structure or pointer. <code class="prettyprint">composeKey()</code> is an example how to consistently create a string key from whatever identifies the data. These parameters usually match the parameters of the <code class="prettyprint">createAValue</code> function (if used)</p>
<p>Use the cache by Write() values if the Read() cannot find them, or you can use something like the <code class="prettyprint">Open()</code> function, which returns the cached value if found in the cache or it generates the value (using the createAValue function), caches it, and returns it<sup id="fnref1"><a href="#fn1">1</a></sup></p>
<p>If a cache is disabled, Read() always returns found == false (even if it has the desired key already in data) and Write() does nothing. Open() will call the generation function every time</p>
<pre><code class="prettyprint lang-go">import (
"sync"
"sync/atomic"
)
// OurCacheType is not necessarily an int; whatever the cache holds, e.g. structures
type OurCacheType = int
type ourCacheData map[string]OurCacheType
// the function that does the work
type getItemFunc func(partOfKey, OtherPartOfKey string) OurCacheType
type OurCache struct {
capacity int
data ourCacheData
createAValue getItemFunc
hitCount int32
missCount int32
overCapacityCount int32
semaphore *sync.RWMutex
enabled bool
}
type ourCacheDatum struct {
key string
value OurCacheType
}
// NewOurCache correctly initializes a cache isntance
func NewOurCache(capacity int, createFunc getItemFunc,
data ...ourCacheDatum) OurCache {
result := OurCache{capacity: capacity, createAValue: createFunc,
semaphore: &sync.RWMutex{}, data: ourCacheData{},
enabled: true} // or start it disabled (e.g. to test without cached values)
// initializing the cache is useful for testing
for _, datum := range data {
result.data[datum.key] = datum.value
}
return result
}
func (cache *OurCache) Open(partOfKey, otherPartOfKey string,
) OurCacheType {
key := composeKey(partOfKey, otherPartOfKey)
value, found := cache.Read(key)
if !found {
value = cache.createAValue(partOfKey, otherPartOfKey)
cache.Write(key, value)
}
return value
}
func (cache *OurCache) Read(key string) (result OurCacheType, found bool) {
cache.semaphore.RLock()
defer cache.semaphore.RUnlock() // activates three lines down
if !cache.enabled {
return result, false
}
result, found = cache.data[key]
if found {
atomic.AddInt32(&(cache.hitCount), 1)
} else {
atomic.AddInt32(&(cache.missCount), 1)
}
return result, found
}
func (cache *OurCache) Write(key string, value OurCacheType) {
cache.semaphore.Lock()
defer cache.semaphore.Unlock()
if cache.enabled {
cache.checkCapacity()
cache.data[key] = value
}
}
// called from Write(), which has a write-lock
func (cache *OurCache) checkCapacity() {
if cache.capacity > 0 && (len(cache.data) >= cache.capacity) {
cache.data = ourCacheData{}
atomic.AddInt32(&(cache.overCapacityCount), 1)
}
}
func (cache *OurCache) Size() int {
cache.semaphore.RLock()
defer cache.semaphore.RUnlock()
result := len(cache.data)
return result
}
func (cache *OurCache) HitCount() int {
result := atomic.LoadInt32(&cache.hitCount)
return int(result)
}
func (cache *OurCache) MissCount() int {
result := atomic.LoadInt32(&cache.missCount)
return int(result)
}
func (cache *OurCache) OverCapacityCount() int {
result := atomic.LoadInt32(&cache.overCapacityCount)
return int(result)
}
func (cache *OurCache) Abled() bool {
cache.semaphore.RLock()
defer cache.semaphore.RUnlock()
return cache.enabled
}
func (cache *OurCache) Enable) {
cache.semaphore.Lock()
defer cache.semaphore.Unlock()
cache.enabled = true
}
func (cache *OurCache) Disable() {
cache.semaphore.Lock()
defer cache.semaphore.Unlock()
cache.enabled = false
}
// Clear when the source of data changes
func (cache *OurCache) Clear() {
cache.semaphore.Lock()
defer cache.semaphore.Unlock()
cache.data = ourCacheData{}
}
func (cache *OurCache) Reset() {
cache.semaphore.Lock()
defer cache.semaphore.Unlock()
cache.data = ourCacheData{}
cache.hitCount = 0
cache.missCount = 0
cache.overCapacityCount = 0
}
func (cache *OurCache) Statistics() (size, capacity, hit, miss, over int, enabled bool) {
cache.semaphore.RLock()
defer cache.semaphore.RUnlock()
return cache.Size(), cache.capacity, cache.HitCount(),
cache.MissCount(), cache.OverCapacityCount(), cache.Abled()
}
// an example of a deterministic way of generating a unique string key for a cachable value
// e.g. a consistent string representation of a Time
func composeKey(partOfKey, otherPartOfKey string) string {
return partOfKey + "|" + otherPartOfKey
}
</code></pre>
<p>A generic version is possible but requires a lot of sacrifices like exposing and delegating the format of the key strings to the caller and losing the variable parameters in NewOurCache(). I could not figure out a way to define a function type that returned the type of the cache, but that critical piece might be possible</p>
<p>One hundred lines of code is a small price to pay for type safety</p>
<div class="footnotes">
<hr>
<ol>
<li id="fn1">
<p>My naming convention is:<br><code class="prettyprint">find("key")</code> returns the value and a boolean (like <code class="prettyprint">aMap["key"]</code>)<br><code class="prettyprint">get("key")</code> excepts/panics if it cannot return the value<br><code class="prettyprint">open("key")</code> returns an existing instance or creates the value <a href="#fnref1">↩</a></p>
</li>
</ol>
</div>
tag:noclevercode.svbtle.com,2014:Post/single-responsibility-lines2022-07-14T22:22:35-07:002022-07-14T22:22:35-07:00Single Responsibility Lines‽<p>From Wikipedia:</p>
<blockquote>
<p>The Single Responsibility Principle (SRP) is a computer programming idea: every module or class should have responsibility for a single functionality. All its services should be narrowly aligned with that responsibility. I leave the discussion about SRP in modules and classes to the plethora of sources addressing them</p>
</blockquote><h1 id="yeah-but-every-line_1">Yeah, But Every Line? <a class="head_anchor" href="#yeah-but-every-line_1">#</a>
</h1>
<p>Yes, every line should perform a single<sup id="fnref1"><a href="#fn1">1</a></sup> task. Even if you are using Perl, every line should have one specific goal. Complex expressions are ¡very impressive¡, but such preening makes the code hard to understand<sup id="fnref2"><a href="#fn2">2</a></sup>. Breaking complex expressions and commands into informational variables and steps makes them easier to read<sup id="fnref3"><a href="#fn3">3</a></sup>, easier to debug, and easier to refactor</p>
<blockquote>
<p>There are two ways of constructing a software design. One way is to make it so simple that there are obviously no deficiencies. And the other way is to make it so complicated that there are no obvious deficiencies. — Charles Hoare</p>
</blockquote><h2 id="good-names-help_2">Good Names Help <a class="head_anchor" href="#good-names-help_2">#</a>
</h2>
<p>Proper naming, as well as intermediate and informational variables, reduce the need for comments<sup id="fnref4"><a href="#fn4">4</a></sup> by making the code communicate well. They make debugging and logging easy and consistent. Intermediate variables do not make code slower (or faster). Interpreters and compilers break the source down to the operator level; a little whitespace and a local token are not going to phase them<sup id="fnref5"><a href="#fn5">5</a></sup></p>
<p>Do not confuse a <u>compound</u> expression with an overly complex one, although length is a consideration. <code class="prettyprint">(x > 2) && (x < 14)</code> is a single test, and if it fits neatly on one line, is a perfectly nice expression</p>
<p>This monstrosity</p>
<pre><code class="prettyprint">state_of_being.find("walk to school", False) ||
state_of_being.find("take your lunch", False) ||
are_tautologies_welcome_here
</code></pre>
<p>even with the descriptive names, is not readable</p>
<h2 id="emgettingem-data-is-not-the-same-as-emusingem_2">
<em>Getting</em> Data Is Not the Same as <em>Using</em> Data <a class="head_anchor" href="#emgettingem-data-is-not-the-same-as-emusingem_2">#</a>
</h2>
<pre><code class="prettyprint">my_data_bag[thingie1][wet_sproket == 4 ? "subkey1" : "subkey2"] =
calculate_important_data(wet_sproket != 4 ? source2 : source1.child)
</code></pre>
<p>As with complex mathematical expressions<sup id="fnref6"><a href="#fn6">6</a></sup>, the inner-most expression evaluates first. Unlike mathematics, <em>we don’t have to do it like this</em>. Figure out the input parameters, then use them to get data, then apply the data</p>
<pre><code class="prettyprint">if wet_sproket == 4
param = source1.child
else
param = source2
important_data = calculate_important_data(param)
if thingie not in my_data_bag
my_data_bag[thingie] = {}
if wet_sproket == 4
my_data_bag[thingie]["subkey1"] = important_data
else
my_data_bag[thingie]["subkey2"] = important_data
</code></pre>
<p>I’ve “wasted” ten lines of code (not counting whitespace) making the assignment readable, understandable, testable, debuggable, and robust</p>
<h2 id="returning-is-a-thing_2">Returning Is a Thing <a class="head_anchor" href="#returning-is-a-thing_2">#</a>
</h2>
<p>Even short examples can have embedded complexity</p>
<pre><code class="prettyprint">func handle(queue chan *Request) {
for req := range queue {
req.resultChan <- req.f(req.args)
}
}
</code></pre>
<p>should be more like</p>
<pre><code class="prettyprint">func handle(queue chan *Request) {
for req := range queue {
result = req.f(req.args)
req.resultChan <- result
}
}
</code></pre>
<p>Again, clever expressions holding lots of business rules and operations are bad; combining them with a control structure is worse</p>
<pre><code class="prettyprint">return this_too() ? "shall" : "pass".strip()
</code></pre>
<p>should be more like</p>
<pre><code class="prettyprint">result = this_too() ? "shall" : "pass".strip()
return result
</code></pre>
<p>or</p>
<pre><code class="prettyprint">if this_too():
result = "shall"
else:
result = "pass".strip()
return result
</code></pre>
<h1 id="don39t-confuse-clarity-with_1">Don’t Confuse Clarity with … <a class="head_anchor" href="#don39t-confuse-clarity-with_1">#</a>
</h1><h2 id="brevity_2">Brevity <a class="head_anchor" href="#brevity_2">#</a>
</h2>
<p>A common mantra<sup id="fnref7"><a href="#fn7">7</a></sup> in business and marketing speak (although that is rarely succinct). We do not pay by the character anymore: we can afford good naming, vowels, and vertical whitespace</p>
<h2 id="loquation_2">Loquation <a class="head_anchor" href="#loquation_2">#</a>
</h2>
<p>Artificially long names don’t help any more than commenting every line. If good code reads like prose, “Never use a long word where a short one will do” (George Orwell). See also “Homeopathic naming” from Kevlin Henney</p>
<h2 id="efficiency_2">Efficiency <a class="head_anchor" href="#efficiency_2">#</a>
</h2>
<p>A seemingly straight-forward line like this</p>
<pre><code class="prettyprint">for i, value in enumerate(data[::2]):
value2 = data [i + 1]
</code></pre>
<p>tries to do two things at once. Slicing data is a operation which returns a new slice of alternate elements. The author intended to iterate the original slice, skipping alternate members, but the code iterates through every item in an array of the odd-indexed elements of the data[]<br>
This code implements the desired behaviour clearly</p>
<pre><code class="prettyprint">oddElements = data[::2]
evenElements = data[1::2]
for I, value1 in enumerate(oddElements):
value2 = evenElements[i]
</code></pre>
<p><em>Iterating over an array is a separate responsibility from modifying the array</em></p>
<p>Look at how seemingly straight-forward code can hide intent<br>
<code class="prettyprint">for i, value in range(value * 4):</code><br>
Even this is not too simple to expand to separate lines. This code does not tell us <em>why</em> it is multiplying by four (e.g. quarterly to annual). Using a constant might tell us more, and looking at it as two different operations, iteration and modification, will tell us everything</p>
<p>Breaking the alternating array into two parallel arrays (as above) makes using them easy. Clever (worse) code might look like</p>
<pre><code class="prettyprint"> # this is clever code. don't do this
oddElements = data[::2]
for i, value1 in enumerate(oddElements):
value2 = data[i * 2 - 1]
</code></pre>
<p>This code has a bug in it<sup id="fnref8"><a href="#fn8">8</a></sup>, but it’s not obvious. Breaking the second index into its own line might make the bug more obvious</p>
<h1 id="examples_1">Examples <a class="head_anchor" href="#examples_1">#</a>
</h1><h2 id="do-one-conceptual-thing_2">Do one conceptual thing <a class="head_anchor" href="#do-one-conceptual-thing_2">#</a>
</h2>
<p>The compound operations are both easy to understand and fit the operation</p>
<p><code class="prettyprint">log.info("user name: ${user.name.lower.trim}")</code></p>
<h2 id="does-one-thing-operates-a-loop_2">Does one thing: operates a loop <a class="head_anchor" href="#does-one-thing-operates-a-loop_2">#</a>
</h2>
<p><code class="prettyprint">for (i = array_length - 1; i >= 0; i--)</code></p>
<h2 id="does-one-thing-records-and-operates-on-the-re_2">Does one thing: records and operates on the result of a call <a class="head_anchor" href="#does-one-thing-records-and-operates-on-the-re_2">#</a>
</h2>
<p><code class="prettyprint">if (value, err := DoThatThingYouDo(47); err == nil)</code></p>
<h2 id="does-several-things_2">Does several things <a class="head_anchor" href="#does-several-things_2">#</a>
</h2>
<p>Forcing code onto one line does no one any favours<br>Many, many comments might make this understandable (if they stayed up-to-date)</p>
<pre><code class="prettyprint">return transylvania_6_5000(total_value < MEDIAN_LIMIT ? total_value + extras(total_value, previous_value) : total_value * 1.2)`
</code></pre>
<p>Rather, break the expression down into separate lines. These arithmetic additions are easy to see and understand because the names are clear if they are on separate lines</p>
<pre><code class="prettyprint">if total_value < MEDIAN_LIMIT
total_extras = extras(total_value, previous_value)
result = calculate_total_extras(total_value + total_extras)
else
result = calculate_total_extras(total_value * ABOVE_MEDIAN_MARKUP)
return result
</code></pre>
<p>or even</p>
<pre><code class="prettyprint">if total_value < MEDIAN_LIMIT
total_extras = extras(total_value, previous_value)
extras_and_values = total_value + total_extras
result = calculate_total_extras(extras_and_values)
else
marked_up_value = total_value * ABOVE_MEDIAN_MARKUP
result = calculate_total_extras(marked_u-_value)
return result
</code></pre>
<p>Our goal is clarity; Do What’s Indicated<sup id="fnref9"><a href="#fn9">9</a></sup></p>
<h2 id="does-two-things_2">Does two things <a class="head_anchor" href="#does-two-things_2">#</a>
</h2>
<p>This operates a loop by making an evaluation unrelated to the loop itself</p>
<pre><code class="prettyprint">// DOES TOO MUCH
for (i = array_length;
i >= 0 && array[i] > 14 && array[i] < max_val * 1.12;
i--)
</code></pre>
<p>Managing the loop is one thing; testing the data is something else. Testing for a null-terminator might be simple enough to include in the loop-control expression</p>
<pre><code class="prettyprint">lowest_allowed_value = 14
highest_allowed_valule = max_val * 1.12
for i = 0; i < array_length; i++)
if (array[i] <= lowest_allowed_value ) || (array[i] >= highest_allowd_value)
break
</code></pre>
<p>or break the calculation into a function with readable code. If the function name is good, readers will never have to look at that code</p>
<pre><code class="prettyprint">for i = 0; i < array_length && value_within_range(array[i]); i++)
</code></pre>
<h1 id="smells-and-tells_1">Smells and Tells <a class="head_anchor" href="#smells-and-tells_1">#</a>
</h1><h2 id="ternaries_2">Ternaries <a class="head_anchor" href="#ternaries_2">#</a>
</h2>
<p>Ternary expressions are a common violation of doing one thing. They are best used to fill in default values, make plurals, select the correct indefinite article, and include or omit small bits of text. Apart from trivial formatting operations, <em>don’t call functions in ternaries</em>. Nesting ternaries is Right Out</p>
<h2 id="line-length_2">Line Length <a class="head_anchor" href="#line-length_2">#</a>
</h2>
<p>Line length is a broad metric, and often a good one. If a non-string line is wrapping, breaking it into separate lines is usually better than wrapping it. Compilers and interpreters are very good at optimizing code; the number of lines source code spans, even with intermediate variables, is never going to affect performance or object size</p>
<h2 id="indentation_2">Indentation <a class="head_anchor" href="#indentation_2">#</a>
</h2>
<p>I like four-space indentation because it’s easier to read and makes it obvious when one has nested structures too deeply. Find a block of code starting at a shallow depth and move it to its own function where reasonable</p>
<h2 id="comments_2">Comments <a class="head_anchor" href="#comments_2">#</a>
</h2>
<p>Comments cannot compensate for obtuse code. They decay and, in the words of Kevlin Henney, someone who writes obtuse code rarely has the ability to write clear comments</p>
<h2 id="code-reviews_2">Code Reviews <a class="head_anchor" href="#code-reviews_2">#</a>
</h2>
<p>If any code reviewer does not understand what a line does, refactor the code instead of just telling them or, at worst, adding a comment. They represent the code-readers of the future (maybe even Future You). Their confusion indicates that the code does not express its purpose. Don’t argue that it is obvious or what a “reasonable” coder would think; take it as evidence that your code failed to communicate with another person<sup id="fnref10"><a href="#fn10">10</a></sup></p>
<h2 id="see-also_2">See Also <a class="head_anchor" href="#see-also_2">#</a>
</h2>
<ul>
<li><a href="https://medium.com/@kevlinhenney/comment-only-what-the-code-cannot-say-dfdb7b8595ac">Comment Only What The Code Cannot Say, <em>Kevlin Henney</em></a></li>
<li><a href="https://en.wikipedia.org/wiki/Code_Complete">Code Complete, <em>Steve McConnell</em></a></li>
<li><a href="https://blog.codinghorror.com/code-tells-you-how-comments-tell-you-why/">Code Tells You How; Comments Tell You Why <em>Jeff Atwood</em></a></li>
</ul>
<div class="footnotes">
<hr>
<ol>
<li id="fn1">
<p>for large values of one <a href="#fnref1">↩</a></p>
</li>
<li id="fn2">
<p>and leads to the pseudo-hazing ritual of “Just Read the Code” because “everyone has to go through it” <a href="#fnref2">↩</a></p>
</li>
<li id="fn3">
<p>Programs must be written for people to read, and only incidentally for machines to execute — Harold Abelson <a href="#fnref3">↩</a></p>
</li>
<li id="fn4">
<p><a href="https://medium.com/@kevlinhenney/comment-only-what-the-code-cannot-say-dfdb7b8595ac">Comment Only What the Code Cannot Say, Kevlin Henney</a> <a href="#fnref4">↩</a></p>
</li>
<li id="fn5">
<p>Trying to outsmart a compiler defeats much of the purpose of using one. — Kernighan & Plauger <a href="#fnref5">↩</a></p>
</li>
<li id="fn6">
<p>nested and embedded ternaries are a code smell <a href="#fnref6">↩</a></p>
</li>
<li id="fn7">
<p>which is usually followed by buzzwords, sadly enough. See <a href="https://docs.google.com/document/d/1xU4OlBvIyfelUamOn1MBp8U5Espzdi-BsNvVlZSkrHk/edit?usp=sharing">Leverging Our Synergies</a> <a href="#fnref7">↩</a></p>
</li>
<li id="fn8">
<p>the first iteration will try and access <code class="prettyprint">data[-1]</code> <a href="#fnref8">↩</a></p>
</li>
<li id="fn9">
<p>Elihu King, 1992 <a href="#fnref9">↩</a></p>
</li>
<li id="fn10">
<p>To self-examine, consider an exercise: Explain to Me Like I’m Five. Not only will it help focus on the most important parts, it helps with descriptive naming <a href="#fnref10">↩</a></p>
</li>
</ol>
</div>
tag:noclevercode.svbtle.com,2014:Post/don-t-worry-about-anything-just-call-us2022-07-13T00:08:56-07:002022-07-13T00:08:56-07:00Don't Worry About Anything, Just Call Us<p>Callbacks are great and always have been. Long ago, we didn’t know we were injecting control or inverting dependencies; we just used them. When closures appeared, I did not see a huge difference: a little state here, a little context there. I have found my Closures Killer App: remote cleanup</p>
<p>Here is an example in Go:</p>
<p>In the calling code (with dependencies on DataDog, Redis, etc.)</p>
<pre><code class="prettyprint">type cleanupSignature func(aName, aType string) func()
cleanupFactory := func(aName, aType string) func() {
if _, found := SpanFromContext(context); !found {
span, _ := datadog.SpanFromContext(context, aName, aType)
return func() {
span.Finish()
}
} else {
return func(){}
}
}
baz := foo(cleanupFactory, bar)
// ...
</code></pre>
<p>In the called code (with no dependencies on context, DataDog, etc.)</p>
<pre><code class="prettyprint">func foo(cleanupFactory cleanupSignature, zap int) string {
cleanupFunction := cleanupFactory("my name", "my type")
// this is like a `finally`, but lives at the top of a function
defer cleanupFunction()
// ...
</code></pre>
<p>The cleanupFactory is more than a factory: in the example, it might create and start a DataDog Span. It closes (encapsulates) the caller’s context and the reference to DataDog. It decides what cleanup its actions need, possibly being no actions at all. If the factory creates and starts a Span, the function it returns encapsulates the Span reference needed to clean up. The host function has no knowledge or access to this value</p>
<p>Rather than the function <code class="prettyprint">foo()</code> holding extra values returned from the factory to control if and how the cleanup function works, the factory always returns only a simple function which <code class="prettyprint">foo()</code> blindly calls. If nothing needs doing, the cleanup function is a nop. If it needs to do things, the cleanup function has encapsulated the values it needs to do them rather than requiring <code class="prettyprint">foo()</code> to pass arguments</p>
<p><em>from a story by Nick Potts</em></p>
tag:noclevercode.svbtle.com,2014:Post/don-t-mock-it-hack-it2021-11-21T10:22:07-08:002021-11-21T10:22:07-08:00Don't Mock It: Hack It<p>Python holds a deep, dark secret: it can be as unpredictable as Ruby if we let it. Even with the new typing<sup id="fnref1"><a href="#fn1">1</a></sup>, the staggering flexibility of Python at runtime remains. We can change individual instances of classes to anything we want, and nothing can stop us</p>
<h3 id="but-it-would-be-wrong_3">But It Would Be Wrong <a class="head_anchor" href="#but-it-would-be-wrong_3">#</a>
</h3>
<p>The whole point of classes and instances is that they are predictable: every instance should act the same; every subclass should do the same things, perhaps in slightly different ways<sup id="fnref2"><a href="#fn2">2</a></sup>. Cleverly<sup id="fnref3"><a href="#fn3">3</a></sup> changing instance 47 to get around some restrictive class design might feel good, but it is a land-mine you planted waiting for the next developer to come along</p>
<h2 id="except_2">Except <a class="head_anchor" href="#except_2">#</a>
</h2>
<p>Except for testing. Testing less than end-to-end involves making some code think that it’s in the real world when it is not. Be it mocks,, stubs, composition, or references to services, tests need to simulate other code to simplify, isolate, and control the inputs and environment of the code under test. A common way is to create a simulacrum or stub of the other code that will dutifully return specified values and record how the code under test called it. Python’s MagicMock is a great example. It automatically creates methods on-demand and allows explicit return values and side-effects</p>
<p>Patching allows one to mock a reference that the test under code will use. For example, if one wants to test a configuration subsystem, one can patch the <code class="prettyprint">getenv</code> reference to simulate different environmental variable values without having to actually change the environment. And the patch will automatically remove itself at the end of a test so as not to affect anything else</p>
<p>However, mocking an instance is sometimes overkill. If one is testing the behaviour within an instance and the instance does not do much on initialization, one can hack a real instance for testing by changing some of the methods themselves. Not only is this simpler, but it avoids the danger that a mock might grow apart from the thing it is mocking</p>
<pre><code class="prettyprint lang-python">from typing import Dict
class FooDog:
def am_i_ready(self) -> bool:
return self._external_reference is not None and \
self._external_reference.is_connected()
def _that_thing(self, key: str) -> Dict:
return self._external_reference.get_this_thing(key)
def get_value_proposition(self, prefix: str) -> Dict:
if not self.am_i_ready():
raise Exception("I'm not ready")
data = self._that_thing(prefix)
return {prefix: data}
test_foo = FooDog()
test_foo.am_i_ready = lambda : True
test_foo._that_thing = lambda key : {"data": key}
result = test_foo.get_value_proposition("prefix")
expected = {"prefix": {"data": "prefix"}}
print(result == expected)
</code></pre>
<p>This looks a lot like code with mocking except we are using an instance of the real class as the scaffolding to hold our “mock” functions. One can even return instances of MagicMock using these simple lambdas. With loosely-coupled and specialized methods, hacking allows most test scenarios, however some things argue against it:</p>
<ul>
<li>If the instance creates connections, other complex objects, or otherwise has overhead on creation</li>
<li>If the methods are not granular or hierarchical enough to find good hacking-points within large and multi-method process<sup id="fnref4"><a href="#fn4">4</a></sup>
</li>
<li>If the class has class variables that affect instance behaviour. These are built-in race-conditions</li>
</ul>
<div class="footnotes">
<hr>
<ol>
<li id="fn1">
<p>which I <em>love</em> <a href="#fnref1">↩</a></p>
</li>
<li id="fn2">
<p>i.e. virtual methods <a href="#fnref2">↩</a></p>
</li>
<li id="fn3">
<p>check the blog name again. I’ll wait <a href="#fnref3">↩</a></p>
</li>
<li id="fn4">
<p>which makes it a good candidate for refactoring towards a top-down design <a href="#fnref4">↩</a></p>
</li>
</ol>
</div>
tag:noclevercode.svbtle.com,2014:Post/the-magic-full-stack-developer2021-07-24T20:59:41-07:002021-07-24T20:59:41-07:00The Magical, Full‑Stack Developer
or The Intellectual Shmoo<p>Software, at least traditionally, was made in layers and parts, and each part has its own domain and its own technology. Developers know multiple languages and multiple domains, i.e. their skills gained from training and experience, but no developer knows <em>every</em> language and domain, however inconvenient this is for managers, and therefore recruiters. A team would have members who brought different skills and experiences. <br>
A recent innovation is the invention of the Full‑Stack Developer to get <em>exactly</em> the skills needed in one engineer</p>
<p>“Stack” is a description of technologies that interact with each other. Originally, the stack extended down to the operating system and the binary network protocol and the physical electronic connections, and now the most common range of the stack is the data store (e.g. Redis, SQL) to servers (e.g. APIs) using communications protocols (e.g. REST, Thrift, Protobuf, Kafka, etc), towards the user interface, usually as a browser application or mobile app (e.g. React, Flutter)</p>
<p>As the examples in the description above indicate, each part of a stack can use completely different technologies from another, which makes the term “full‑stack” as meaningless as “can fix vehicles”. While one person might know a particular stack’s technologies, they are unlikely to know all of them well simply because no one has time to use all those technologies regularly. Recruiters, managers, and training vendors, however, happily weald the term to mean “whatever <strong>the employer</strong> needs at the moment”. Woe betide the FSD who does not also have every specific technology their employer might use in the future as well</p>
<p>The market is ready for a new type of software developer training: Shmoo Training. <a href="https://en.wikipedia.org/wiki/Shmoo">Shmoos</a> were an imaginary animal in the <a href="https://en.wikipedia.org/wiki/Li%27l_Abner">Lil’ Abner</a> comic strip started in the 1930s</p>
<blockquote>
<p>Shmoos are delicious to eat, and are eager to be eaten. If a human looks at one hungrily, it will happily immolate itself—either by jumping into a frying pan, after which they taste like chicken, or into a broiling pan, after which they taste like steak. When roasted they taste like pork, and when baked they taste like catfish. Raw, they taste like oysters on the half-shell.<br>
They also produce eggs (neatly packaged), milk (bottled, grade-A), and butter—no churning required. Their pelts make perfect bootleather or house timbers, depending on how thick one slices them.<br>
– <a href="https://en.wikipedia.org/wiki/Shmoo#Description">Wikipedia</a></p>
</blockquote>
<p>And that is what a perfect Full‑Stack Developer is: a completely fungible solution without overhead, applicable to any problem or task, swappable without complaint or cost, and selflessly devoted to their ultimate contribution to their consumer</p>
tag:noclevercode.svbtle.com,2014:Post/the-futures-of-python2021-04-26T10:03:00-07:002021-04-26T10:03:00-07:00The Futures of Python<p><a href="https://docs.python.org/3/library/concurrent.futures.html#future-objects">Futures</a> defer execution of code. They can allow code to wait for external resources like file reads, network calls, and database access, and then automatically continue without stopping every other operation. They allow the definition (i.e. coding) of entire sequences of work in one place rather than having one function hand-off to another (presumably coordinated) function</p>
<p>Python’s syntax for Futures (and coroutines) is simple and, for me, surprisingly confusing at first. I have concluded that Futures in Python boil down to three (3) rules:</p>
<ol>
<li><p>Functions prefixed with <code class="prettyprint">async</code> return a Future<sup id="fnref1"><a href="#fn1">1</a></sup> when called even if the function itself does not return a result. The code inside the function does not execute until something resolves the Future</p></li>
<li>
<p>The ways to resolve a Future are</p>
<ul>
<li><code class="prettyprint">await <Future></code></li>
<li>
<code class="prettyprint">asyncio.get_event_loop().run_until_complete(<Future>)</code> or <code class="prettyprint">ayncio.run(<Future>)</code><sup id="fnref2"><a href="#fn2">2</a></sup>
</li>
</ul>
</li>
<li><p>Use <code class="prettyprint">await</code> inside <code class="prettyprint">async</code> functions only</p></li>
</ol>
<p>That’s really all the mechanics</p>
<h1 id="example_1">Example <a class="head_anchor" href="#example_1">#</a>
</h1>
<pre><code class="prettyprint lang-python">import asyncio
async def ensure_grapes() -> None:
pass
async def do_grapes_exist() -> bool:
get_grapes = ensure_grapes() # even though the function -> None
print("one second")
await get_grapes
return True
async def does_future_me_like_grapes() -> bool:
grapes_ok = await do_grapes_exist()
return grapes_ok
i_am_a_future = does_future_me_like_grapes()
assert(asyncio.iscoroutinefunction(i_am_a_future))
i_will_like_grapes : bool = asyncio.run(i_am_a_future)
</code></pre>
<h1 id="unit-tests_1">Unit Tests <a class="head_anchor" href="#unit-tests_1">#</a>
</h1>
<p>To test async functions, one can descend one’s test case class from <code class="prettyprint">unittest.IsolatedAsycioTestCase</code> (instead of <code class="prettyprint">TestCase</code>) and make the testing functions <code class="prettyprint">async def</code> + <code class="prettyprint">await i_am_an_async_function()</code>. Alternatively, one can decorate an <code class="prettyprint">async</code> test function with <code class="prettyprint">@pytest.mark.asyncio</code></p>
<h1 id="simultainous-processing_1">Simultainous Processing <a class="head_anchor" href="#simultainous-processing_1">#</a>
</h1>
<p>Note that asynchronous does <em>not</em> mean parallel or threaded; it only means the code will run later (when resolved). One might get pseudo-parallel processing if several Futures resolve and await at the same time (e.g. on IO); Python has several libraries for these cases</p>
<h1 id="closures_1">Closures <a class="head_anchor" href="#closures_1">#</a>
</h1>
<p>Futures are not closures: they store call-syntax only. They are more like a function pointer than a closure. They do <em>not</em> make a copy of the function or its environment at the moment of their creation (the call to the <code class="prettyprint">async</code> function). When resolved, the Future calls whatever object the function-name points to at that moment, and that function will use any globals or instance field values it finds at that time</p>
<h1 id="troubleshooting_1">Troubleshooting <a class="head_anchor" href="#troubleshooting_1">#</a>
</h1>
<table>
<thead>
<tr>
<th>Symptom</th>
<th>Explanation</th>
</tr>
</thead>
<tbody>
<tr>
<td>TypeError: cannot unpack a non-iterable coroutine object</td>
<td>Calling an <code class="prettyprint">async</code> function without an <code class="prettyprint">await</code><br>The result is a Future, and nothing else knows how to deal with a Future</td>
</tr>
<tr>
<td>RuntimeWarning: coroutine ‘async’ was never awaited</td>
<td>Calling an <code class="prettyprint">async</code> function without an <code class="prettyprint">await</code><br>Even if code does not try and use the result of an <code class="prettyprint">async</code> function, Python knows that the resulting Future never got resolved; something called the function and the code never executed</td>
</tr>
<tr>
<td>TypeError: object <type> can’t be used in ‘await’ expression</td>
<td>Passing something that is not and does not return a Future to an<code class="prettyprint">await</code>
</td>
</tr>
<tr>
<td>SyntaxError: ‘await’ outside async function</td>
<td>See #3 above</td>
</tr>
<tr>
<td>RuntimeError: cannot reuse already awaited coroutine</td>
<td>Futures are a pointer to a function <u>call</u>, not a function. Once that call resolves, it’s done</td>
</tr>
</tbody>
</table>
<div class="footnotes">
<hr>
<ol>
<li id="fn1">
<p>yes, it is really a coroutine, but, as noted in the documentation, it uses this term inconsistently <a href="#fnref1">↩</a></p>
</li>
<li id="fn2">
<p>which can have awkward side-effects if more than one strand of code uses this <a href="#fnref2">↩</a></p>
</li>
</ol>
</div>