<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>13brane</title>
    <link>https://13brane.net/</link>
    <description>Recent content on 13brane</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Mon, 09 May 2022 12:00:00 -0400</lastBuildDate>
    <atom:link href="https://13brane.net/" rel="self" type="application/rss+xml" />
    
    <item>
      <title>GSF is required to extend battery life, and other lies we&#39;re told while our data is slurped</title>
      <link>https://13brane.net/rants/smartphone-lies/</link>
      <pubDate>Mon, 09 May 2022 12:00:00 -0400</pubDate>
      
      <guid>https://13brane.net/rants/smartphone-lies/</guid>
      <description>&lt;p&gt;The path to complete digital sovereignty is lonely, long and difficult.
Sometimes, it is also fraught with improper signage.&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://13brane.net/images/a5batt.png&#34; alt=&#34;Samsung A5 2017 battery usage over a week&#34; /&gt;&lt;/p&gt;

&lt;p&gt;Exhibit A, shown above, is a screenshot. It was taken on my recently
degoogled 2017 Samsung A5. A decent device at a decent price, acquired from
a refurbisher to replace my old and worn S5 Mini Duos.
The only shortcoming that cannot be overlooked on the A5 is the lack of
a user removable battery. Otherwise, it fits my current needs, and it runs well
with LOS 18.1.&lt;/p&gt;

&lt;p&gt;In fact, it runs so well that I see no need for setting the performance profile
to anything other than &amp;ldquo;Power save&amp;rdquo;. In this setting, as seen above, it is
possible to obtain up to a week of standby with this device (though 5-6 days is
more common).&lt;/p&gt;

&lt;p&gt;You&amp;rsquo;ll be forgiven for thinking that I have published a rant for the sole
and explicit purpose of bragging about battery life on a used Android phone.
Impressive as it is without resorting to Samsung&amp;rsquo;s Ultra Power Saving, the
reality is that I don&amp;rsquo;t use my smartphone very much these days. When I said
standby, I really meant standby. The thing mostly just sits there waiting for
calls and Signal messages. For a mobile phone, it is quite fixed. For a
smartphone, it feels quite dumb.&lt;/p&gt;

&lt;p&gt;Back on topic. The &lt;em&gt;real&lt;/em&gt; purpose of this rant is to
&lt;em&gt;alert the readers to the fact that they are being lied to&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;This phone has no GSF installed on it. It cannot run anything from the Google
Play Store. It cannot use the Push Notification APIs. Both instant messaging
apps, and both email apps which run on this device run &lt;em&gt;in the background
constantly&lt;/em&gt;. You would think, judging by Google and Samsung&amp;rsquo;s propaganda, that
battery life on this device, in it&amp;rsquo;s present configuration, would be miserable.
Far from it. I&amp;rsquo;m fetching a chair so I can
wait comfortably for a screenshot of a similar device with better battery life
running GSF. Or more specifically, a screenshot of another A5 2017 with stock
ROM or LOS+Gapps,
in any power profile other than Ultra Power Saving, which lasts &amp;gt;6 days standing
by without any special tomfoolery beyond selecting which apps run in the
background and which apps don&amp;rsquo;t.&lt;/p&gt;

&lt;p&gt;You have been bamboozled. Requiring apps to go through GSF rather than allowing
them to
occasionally run in the background is not about energy efficiency.
It&amp;rsquo;s about money. It&amp;rsquo;s
about having all your apps funnel that cherry sweet unique device identifier
through someone&amp;rsquo;s servers so that your personal profile can be more effectively
sold to advertisers. It is about &lt;em&gt;having&lt;/em&gt; GSF on the phone so that it can
call back home to it&amp;rsquo;s masters with data points which are exceedingly hard to
harvest otherwise. The hilarious part is as follows: spyware needs energy to
call back home.&lt;/p&gt;

&lt;p&gt;You have three choices right now. Accept that your smartphone will never be
yours and that it will always serve another master first, compromising your
privacy at every chance it gets; put in absurd amounts
of work to obtain a device that&amp;rsquo;s only close enough to the ideal of a machine
which serves you and only you; or forego this sociopathic hellscape and ditch
the monitoring device altogether.&lt;/p&gt;

&lt;p&gt;I have no intention of repeating the process
required to bring a smartphone in line with my privacy and general usage tastes.
As such, I have decided that this device will not have a replacement. When this
A5 dies (or I decide to decommission it, whichever comes first), I will not
have another smartphone. These devices are currently built under the assumption
that information about your life is fuel for the ad machine. My interest in
being an active participant of this contraption dwindles.&lt;/p&gt;

&lt;p&gt;A suggestion to the readers
is to consider the trade-offs that come with
owning a smartphone (or not) and make a decision right now, as you may not be
able to decide for yourself past a certain point. For my current situation, the
optimal spot seems to gravitate around the concept of a &amp;ldquo;Landline++&amp;rdquo;, where I
am reachable in more than one way through the same device, and I can definitely
make full use of the smartphone&amp;rsquo;s capabilities if I so choose, including
the ability to temporarily take it somewhere else or use it as a small
computer, but it&amp;rsquo;s been a long time
since I was under the illusion that I &lt;em&gt;need&lt;/em&gt; to carry this thing all the time
or be within two arm lengths of the rectangle to stave off the impromptu visits
from the &lt;em&gt;void&lt;/em&gt;.&lt;sup class=&#34;footnote-ref&#34; id=&#34;fnref:209c8872a1ddd36b2037db01ca2cb356:try-this-remove&#34;&gt;&lt;a rel=&#34;footnote&#34; href=&#34;#fn:209c8872a1ddd36b2037db01ca2cb356:try-this-remove&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;In a slightly unrelated note, keep in mind that if Google, Apple
and Microsoft have their way, you will not be able to log in to anything, even
through your web browser, &lt;a href=&#34;https://www.wired.com/story/fido-alliance-passwordless-login-browser-support/&#34;&gt;without having your tracker next to you&lt;/a&gt;.
When
the time comes, we&amp;rsquo;ll need enough people saying &amp;ldquo;I don&amp;rsquo;t own a smartphone&amp;rdquo; to
justify the pushback against this &amp;ldquo;more secure&amp;rdquo; standard of authentication and
prevent this type of nonsense from becoming the new normal. Remember when
telephones were optional? Yeah, good luck going back to that if you don&amp;rsquo;t want
to be bothered about it.&lt;/p&gt;

&lt;p&gt;Your devices should serve you, not the other way around. And they certainly
shouldn&amp;rsquo;t serve anyone else. Refuse mediocre solutions for problems which did
not need to be solved in the first place.&lt;/p&gt;
&lt;div class=&#34;footnotes&#34;&gt;

&lt;hr /&gt;

&lt;ol&gt;
&lt;li id=&#34;fn:209c8872a1ddd36b2037db01ca2cb356:try-this-remove&#34;&gt;try this: remove all purely for-entertainment apps (games, tubes/streaming, and any other time-killers) from your smartphone, and you&amp;rsquo;ll be amazed both at how addicted you are to the thing, and how little you&amp;rsquo;ll automatically reach for it a few days after the removal. &lt;a class=&#34;footnote-return&#34; href=&#34;#fnref:209c8872a1ddd36b2037db01ca2cb356:try-this-remove&#34;&gt;&lt;sup&gt;[return]&lt;/sup&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>On the matter of libera.chat</title>
      <link>https://13brane.net/rants/libera/</link>
      <pubDate>Sun, 30 May 2021 17:52:01 -0400</pubDate>
      
      <guid>https://13brane.net/rants/libera/</guid>
      <description>&lt;p&gt;Or, &lt;em&gt;how healthy and sane distributed organisms reject the transplantation of
stupid&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;You&amp;rsquo;ve heard of EEE: &amp;ldquo;embrace, extend, extinguish&amp;rdquo;. Today we&amp;rsquo;re going to look at
some of its lesser known variations, starting with &amp;ldquo;embrace, smother,
repurpose&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;This is what happened to CentOS. RedHat takes it under its wing, and all goes
well for a while. More resources for CentOS, all pumped to deliver version 8
with support until the second coming. Except, that doesn&amp;rsquo;t actually help
acquire new RedHat subscriptions, at least not directly.&lt;/p&gt;

&lt;p&gt;Along comes CentOS Stream, which nobody needed or wanted, as the main selling
point of CentOS/RHEL is its extremely long support cycle. No other free
(both as in &lt;em&gt;freedom&lt;/em&gt; and &lt;em&gt;cost&lt;/em&gt;) distro
has a support cycle of that length. A rolling release version of CentOS
is as useful as wings on an elephant. Flap all you want, no takeoff will occur.&lt;/p&gt;

&lt;p&gt;RedHat eventually pulled the plug on regular old LTS CentOS, in favor of
keeping the new, RHEL-beta under a different but very well known, &lt;em&gt;FOSSy&lt;/em&gt; brand.
Which we can only suppose to be much more useful for business. One less distro
to maintain, the remaining one possibly funneling stability prioritizing admins
towards a cushy yearly subscription.&lt;/p&gt;

&lt;p&gt;However, the &lt;em&gt;organism rejected the stupid&lt;/em&gt;. Distributed organisms do this by
disassembly and reassembly. CentOS is but an empty shell, something with the
same name but no other resemblance to its former self. Its personality though,
lives on, &lt;a href=&#34;https://rockylinux.org/&#34;&gt;under&lt;/a&gt; &lt;a href=&#34;http://springdale.math.ias.edu/&#34;&gt;other&lt;/a&gt; &lt;a href=&#34;https://almalinux.org/&#34;&gt;names&lt;/a&gt; but with the same
&lt;em&gt;substance&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Up next: &amp;ldquo;embrace, inject, override&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;Lee&amp;rsquo;s embrace of freenode occurred a long time ago. As for the injection,
I&amp;rsquo;m not entirely sure. I avoid reading drama these days. This rant is not about
the drama, but the &lt;em&gt;effect&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Libera.chat is an interesting situation because the rejection of the stupid
happened not at the end of the third phase but at the beginning. At the
faintest smell of override, freenode (the substance, not the name), immediately
disassembled. And, as any distributed organism of stature does, quickly
reassembled under a different shell almost unscathed, with barely any change
to its substance. The (unpaid) admins left, and one by one the channels, and
thus the users, followed.&lt;/p&gt;

&lt;p&gt;Another interesting difference between this case and the former is that unlike
ex-CentOS, which is a prime example of higher level Darwinism in the sense that
the new generation of spawn is inoculated against the ills that caused its
parent&amp;rsquo;s untimely demise, libera.chat is more an example of a type of osmotic
skin shedding, one where the skin is left behind, intact and unbroken, and most
of the substance leaves the shell through the pores rather than any other large
opening, eventually forming another shell for itself.&lt;/p&gt;

&lt;p&gt;After this process is complete, all the &lt;em&gt;injector&lt;/em&gt; can do is to keep the
empty shell. To what purpose, we will see.&lt;/p&gt;

&lt;p&gt;I would now like to draw your attention to the fact that these EEE attempts,
or variations thereof, are going on &lt;em&gt;all the time&lt;/em&gt;. The main goal
of these attempts is usually consumption, and transplanted parts are almost
invariably less healthy than the target organism (otherwise, there would be
no upside). The corporate is hungry
and these distributed organisms have juicy, healthy livers.&lt;/p&gt;

&lt;p&gt;Or, as is the case with the FSF, they&amp;rsquo;re also in the way and being pesky.
The FSF&amp;rsquo;s situation is rather curious because RMS&amp;rsquo;s ideological (and bodily, it
seems) aroma makes this organism unfit for corporate consumption &lt;em&gt;as is&lt;/em&gt;.
But it has the healthiest, juiciest liver. So the main purpose of an injection
here is first and foremost not to transplant, but to &lt;em&gt;amputate&lt;/em&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;There is much talk these days about RMS, the founder of FSF returning to the
board of FSF and IBM refusing to have him, popular demand, vote, or otherwise.&lt;/p&gt;

&lt;p&gt;I could list countless articles here as a detailed research on the matter,
but the plethora of them TOTALLY MISS THE ISSUE.&lt;/p&gt;

&lt;p&gt;Who decides and how is a decision made?  Is it influence by rational arguments
or is it a choke-hold maneuver that even his (RMS’s) dearest of friends can’t
escape?&lt;/p&gt;

&lt;p&gt;The rational argument by IBM, and their fellow mutually interested global
giant corporations, is “YOU DO AS WE SAY, OR NO MONEY COMING TO YOU“.&lt;/p&gt;

&lt;p&gt;This is what every democracy in the planet has been reduced to, every
democratic process that “tolerated” money/funding to be part of the decision
making process.&lt;/p&gt;

&lt;p&gt;(from &lt;a href=&#34;https://sysdfree.wordpress.com/2021/04/05/341/&#34;&gt;sysdfree.wordpress.com&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The corporate overplayed its injection in this case.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The FSF does not depend on large single sources of funding. It accepts and
appreciates support from corporations who want to give back by contributing to
the development and advocacy for free software,
&lt;strong&gt;but direct corporate support accounted for less than 3% of FSF revenue in its most recently audited fiscal year.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;(from &lt;a href=&#34;https://www.fsf.org/news/fsf-board-frequently-asked-questions-faq#FSFfinancialstatus&#34;&gt;the FSF itself&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In addition to having the healthiest liver, this organization&amp;rsquo;s immune system
ended up &lt;em&gt;reversing&lt;/em&gt; the amputation, hinting at the presence of a stellar
spleen. A reversal not without consequence, but still impressive.&lt;/p&gt;

&lt;p&gt;The issue with corporate is that it is always centralized. As such, it doesn&amp;rsquo;t
quite get the nature and world of the distributed organism it seeks to consume.&lt;/p&gt;

&lt;p&gt;It puzzles and wonders how it functions with multiple bodies, sometimes without
a head, sometimes with many, and is able to appear in multiple places at a time.&lt;/p&gt;

&lt;p&gt;It scratches its head, bewildered, wondering why the organism doesn&amp;rsquo;t readily
amputate its many members which are flailing about uncontrollably, bereft of
acceptance of central authority.&lt;/p&gt;

&lt;p&gt;It gasps in awe and shock when half of the body of a recently consumed
distributed organism suddenly leaves its stomach to form yet another
distributed organism with an uncanny resemblance to the one which was just
consumed, but with an unrecognizable name.&lt;/p&gt;

&lt;p&gt;Nowhere is corporate&amp;rsquo;s true lack of understanding of the distributed
organism more apparent than in its treatment of names.
To corporate, its name is everything. All the value of a corporate is in its
name.&lt;/p&gt;

&lt;p&gt;It exerts its influence and impact in the world through its name. When the name
dies, corporate almost always dies with it. So, when attempting to consume
a distributed organism, it will always start with the name, assuming that is
the location of the juicy innards.&lt;/p&gt;

&lt;p&gt;But for a distributed organism, a name is but a tether point around which its
parts gravitate. It will ditch its name for survival, for preference, for
compliance, for shits and giggles or because it&amp;rsquo;s Tuesday.&lt;/p&gt;

&lt;p&gt;Corporate consumes the name, and stays hungry. Please, continue. We are very
much enjoying this season of
&lt;em&gt;Organizational Geographic: Distributed Darwinian Mechanics&lt;/em&gt;.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Increasing entropy</title>
      <link>https://13brane.net/rants/increasing-entropy/</link>
      <pubDate>Sat, 05 Sep 2020 17:00:00 -0400</pubDate>
      
      <guid>https://13brane.net/rants/increasing-entropy/</guid>
      <description>&lt;p&gt;Hello again, &lt;em&gt;braneswalkers&lt;/em&gt;. It&amp;rsquo;s been a while, hasn&amp;rsquo;t it?&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m sorry to have kept you all deprived of large braned &lt;em&gt;rantiness&lt;/em&gt; for such a
long time. I know how absolutely crucial this is for your general well
being.&lt;sup class=&#34;footnote-ref&#34; id=&#34;fnref:c32a0cebd3c18411309b59952479ed76:tempted-to-take&#34;&gt;&lt;a rel=&#34;footnote&#34; href=&#34;#fn:c32a0cebd3c18411309b59952479ed76:tempted-to-take&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;I promise more brany nastiness in the very near future, but this one
rant will be shorter than usual. It&amp;rsquo;s only purpose is to draw attention to the
fact that &lt;a href=&#34;https://13brane.net/rss.xml&#34;&gt;the branes are now accessible via good old RSS 2.0&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I only know of two things which are inherently anti-entropic: the world&amp;rsquo;s
money supply, and internet social media. These also happen to
share two other characteristics: they are man-made and quite dysfunctional
in their current state.&lt;/p&gt;

&lt;p&gt;In the interest of simplicity and accessibility, I&amp;rsquo;m extremely reluctant to
add features to this site. Yet, I&amp;rsquo;m even more reluctant to be part of the
unnatural, depressing &lt;em&gt;morass of corporate-vetted groupthink&lt;/em&gt; that gets
passed around for world and democracy
enhancing&lt;sup class=&#34;footnote-ref&#34; id=&#34;fnref:c32a0cebd3c18411309b59952479ed76:or-kind-or-compa&#34;&gt;&lt;a rel=&#34;footnote&#34; href=&#34;#fn:c32a0cebd3c18411309b59952479ed76:or-kind-or-compa&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;
discourse these days.&lt;/p&gt;

&lt;p&gt;As the grip of big tech and governments alike around what we can find and
express online tightens, and my usage of the common platforms decreases to a
point near non-existence as a result, it becomes imperative to allow for other,
more &lt;em&gt;cosmologically aligned&lt;/em&gt; methods of information distribution.&lt;/p&gt;

&lt;p&gt;Freedom of speech online isn&amp;rsquo;t dead yet, but if we&amp;rsquo;re not careful, it might
need to be rushed to the ICU
soon.&lt;sup class=&#34;footnote-ref&#34; id=&#34;fnref:c32a0cebd3c18411309b59952479ed76:recall-that-Free&#34;&gt;&lt;a rel=&#34;footnote&#34; href=&#34;#fn:c32a0cebd3c18411309b59952479ed76:recall-that-Free&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;The problem is simple: when you rent, you need to ask permission to drill holes
in the walls. When you own, you don&amp;rsquo;t. This is a pretty sensible arrangement,
and it&amp;rsquo;s motivations are very easily understood.
Yet, what makes up most of the tubes today is neither renters nor owners, but
&lt;em&gt;couchsurfers&lt;/em&gt;. And in this condition, complaining is not just futile, it&amp;rsquo;s
downright &lt;em&gt;stupid&lt;/em&gt;. Don&amp;rsquo;t complain about not being able to hang stuff on the
walls if the arrangement is that you sleep, for free, on the couch or the
floor.&lt;sup class=&#34;footnote-ref&#34; id=&#34;fnref:c32a0cebd3c18411309b59952479ed76:and-don-t-forget&#34;&gt;&lt;a rel=&#34;footnote&#34; href=&#34;#fn:c32a0cebd3c18411309b59952479ed76:and-don-t-forget&#34;&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;There is a pill for this ailment, and it is made solely of natural ingredients.
&lt;em&gt;We must allow the entropy of the Internet to increase&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The real reason freedom of speech is being threatened online is the same as the
reason privacy is gone: we
took all our traffic, all our info, and now even close to &lt;em&gt;all our lives&lt;/em&gt;
to about two handfuls of sites or apps, which provide their services for free
on the condition that &lt;em&gt;we are the product&lt;/em&gt;. The hosts can&amp;rsquo;t have the products
deciding to change their features all willy-nilly, so we must conform to the
specifications provided by the host&amp;rsquo;s costumers. Specifications which will be
dully enforced, even if it means &amp;ldquo;negligible&amp;rdquo; sacrifices on the part of the
&lt;em&gt;product&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;There are many ways to stave off online censorship, but I happen to think the
best ones are to &lt;em&gt;decentralize&lt;/em&gt; and &lt;em&gt;own&lt;/em&gt; (or at very least, &lt;em&gt;rent&lt;/em&gt;) as much of
the internet as possible. To that effect, this will be the last rant which will
be &lt;em&gt;tweeted&lt;/em&gt; (or shared by the author on any social network), and the search
for a &lt;em&gt;paid&lt;/em&gt; hosting solution which does not engage arbitrary censorship will
continue.&lt;sup class=&#34;footnote-ref&#34; id=&#34;fnref:c32a0cebd3c18411309b59952479ed76:while-decentrali&#34;&gt;&lt;a rel=&#34;footnote&#34; href=&#34;#fn:c32a0cebd3c18411309b59952479ed76:while-decentrali&#34;&gt;5&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;So what is this to you, dear reader? For now, nothing more than a friendly
invitation to continue thinking for yourself, and reading and searching for the
things that matter to you, hopefully a bit freer from monitoring
and censorship. To that effect, consider subscribing to the RSS feed,
optionally setting the auto-refresh to the vicinity of &amp;ldquo;every week&amp;rdquo;
(13brane.net doesn&amp;rsquo;t spam). Oh, and log the fuck out, while you still can.&lt;/p&gt;

&lt;p&gt;That&amp;rsquo;s it for today. We&amp;rsquo;ll keep in touch.&lt;/p&gt;
&lt;div class=&#34;footnotes&#34;&gt;

&lt;hr /&gt;

&lt;ol&gt;
&lt;li id=&#34;fn:c32a0cebd3c18411309b59952479ed76:tempted-to-take&#34;&gt;tempted to take this paragraph seriously? Please remember the part that ends with &amp;ldquo;shot of tequilla.&amp;rdquo; &lt;a class=&#34;footnote-return&#34; href=&#34;#fnref:c32a0cebd3c18411309b59952479ed76:tempted-to-take&#34;&gt;&lt;sup&gt;[return]&lt;/sup&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li id=&#34;fn:c32a0cebd3c18411309b59952479ed76:or-kind-or-compa&#34;&gt;or &amp;ldquo;kind&amp;rdquo;, or &amp;ldquo;compassionate&amp;rdquo;. The most vocal people peddling this crock are also some of the most rage and hate filled bunch you&amp;rsquo;ll ever meet. &lt;a class=&#34;footnote-return&#34; href=&#34;#fnref:c32a0cebd3c18411309b59952479ed76:or-kind-or-compa&#34;&gt;&lt;sup&gt;[return]&lt;/sup&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li id=&#34;fn:c32a0cebd3c18411309b59952479ed76:recall-that-Free&#34;&gt;recall that Freedom of Speech&amp;rsquo;s more reclusive sibling, Privacy, is still in a coma. &lt;a class=&#34;footnote-return&#34; href=&#34;#fnref:c32a0cebd3c18411309b59952479ed76:recall-that-Free&#34;&gt;&lt;sup&gt;[return]&lt;/sup&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li id=&#34;fn:c32a0cebd3c18411309b59952479ed76:and-don-t-forget&#34;&gt;and don&amp;rsquo;t forget to check for hidden cameras. &lt;a class=&#34;footnote-return&#34; href=&#34;#fnref:c32a0cebd3c18411309b59952479ed76:and-don-t-forget&#34;&gt;&lt;sup&gt;[return]&lt;/sup&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li id=&#34;fn:c32a0cebd3c18411309b59952479ed76:while-decentrali&#34;&gt;while decentralization is a low hanging fruit, ownership isn&amp;rsquo;t. It&amp;rsquo;s a particularly hard problem to tackle, especially if you are aware of all the operational, jurisdictional, privacy and monetary aspects. This is readily apparent should you try to find a freedom and privacy respecting hosting provider which is also inexpensive and run by people who aren&amp;rsquo;t complete wackaloons. &lt;a class=&#34;footnote-return&#34; href=&#34;#fnref:c32a0cebd3c18411309b59952479ed76:while-decentrali&#34;&gt;&lt;sup&gt;[return]&lt;/sup&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>13brane&#39;s holidazed cavalcade of code shenanigans: the flavors of FizzBuzz - Days 17-24</title>
      <link>https://13brane.net/rants/holidazed-cavalcade-2018-day-17-24/</link>
      <pubDate>Sun, 23 Dec 2018 12:00:00 -0500</pubDate>
      
      <guid>https://13brane.net/rants/holidazed-cavalcade-2018-day-17-24/</guid>
      <description>

&lt;p&gt;&lt;em&gt;(Full source code for the entire series will be progressively published
&lt;a href=&#34;https://gitlab.com/carlosdavidepto/cavalcade-2018&#34;&gt;here&lt;/a&gt;, and the other days of the cavalcade are here: &lt;a href=&#34;https://13brane.net/rants/holidazed-cavalcade-2018-day-0/&#34;&gt;day 0&lt;/a&gt;,
&lt;a href=&#34;https://13brane.net/rants/holidazed-cavalcade-2018-day-1-8/&#34;&gt;1-8&lt;/a&gt;, &lt;a href=&#34;https://13brane.net/rants/holidazed-cavalcade-2018-day-9-16/&#34;&gt;9-16&lt;/a&gt;)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Welcome back to the last instalment of the cavalcade. This week we are going
to do something evil. Something forbidden. Something so egregiously deranged
it might cause uproar with religious leaders.&lt;/p&gt;

&lt;p&gt;Lo and behold, object oriented fizzbuzzing.&lt;/p&gt;

&lt;h4 id=&#34;day-17:0eee349fcbb2bb6aa93e7c8599ca1fb3&#34;&gt;Day 17&lt;/h4&gt;

&lt;p&gt;New tech lead is hired. Asks junior dev to convert the previous implementation
of Fizzbuzz to OOP. Junior dev, puzzled by this request, asks as politely as
possible, why the hell would someone do that. Tech lead answers with some badly
strung together argument about DI and logging. Junior dev does not understand
why FizzBuzz needs DI (or logging, for that matter) and continues to ask
questions. Conversation abruptly ends with &amp;ldquo;Just put it in an object.&amp;rdquo;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;package day17

import &amp;quot;fmt&amp;quot;

// default implementation, for acceptance test
var FizzBuzz func(int) string = NewFizzBuzzer().FizzBuzz

type FizzBuzzer struct{}

func NewFizzBuzzer() *FizzBuzzer {
	return &amp;amp;FizzBuzzer{}
}

func (fb *FizzBuzzer) FizzBuzz(n int) string {
	if n%3 == 0 &amp;amp;&amp;amp; n%5 == 0 {
		return &amp;quot;fizzbuzz&amp;quot;
	} else if n%3 == 0 {
		return &amp;quot;fizz&amp;quot;
	} else if n%5 == 0 {
		return &amp;quot;buzz&amp;quot;
	} else {
		return fmt.Sprint(n)
	}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Junior dev obliges. Goes home that night, starts reading Lambda The Ultimate.&lt;/p&gt;

&lt;p&gt;This is how we create anti-OOP fundamentalists. Tech leads, take note.&lt;/p&gt;

&lt;h4 id=&#34;day-18:0eee349fcbb2bb6aa93e7c8599ca1fb3&#34;&gt;Day 18&lt;/h4&gt;

&lt;p&gt;A hip new web startup decides to create an entirely new segment of the
market: FBaaS, FizzBuzz as a Service.&lt;/p&gt;

&lt;p&gt;An MVP is launched. Seed and Series A rounds are a massive success due to the
disruptive potential to the FizzBuzzing industry. We are not entirely sure how
much disruption can occur to a market segment that doesn&amp;rsquo;t exist, or if it&amp;rsquo;s
actually good or necessary, but it&amp;rsquo;s in the business plan, so it must be true.&lt;/p&gt;

&lt;p&gt;In order to future proof the
solution and prepare for the &amp;ldquo;exponential&amp;rdquo; growth that is expected, the core of
the service is implemented as a sort of routing engine library,
but for integers.&lt;/p&gt;

&lt;p&gt;A new Silicon Valley unicorn is clearly in the making here.
They have issued only 3 API keys so far, and one of those
is for the CI server, but hey, who am I to give investment advice.&lt;/p&gt;

&lt;p&gt;Hustle to your heart&amp;rsquo;s content.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;package day18

import &amp;quot;fmt&amp;quot;

var FizzBuzz func(int) string = InitFizzBuzz()

func InitFizzBuzz() func(int) string {
	c := NewNumberConverter()

	c.AddRule(15, &amp;quot;fizzbuzz&amp;quot;)
	c.AddRule(3, &amp;quot;fizz&amp;quot;)
	c.AddRule(5, &amp;quot;buzz&amp;quot;)

	c.SetDefaultRule(func(n int) string {
		return fmt.Sprint(n)
	})

	return c.ApplyRules
}

// Implementation of NumberConverter Engine

type rule struct {
	i int
	s string
}

type NumberConverter struct {
	rules       []rule
	defaultRule func(int) string
}

func NewNumberConverter() *NumberConverter {
	return &amp;amp;NumberConverter{}
}

func (c *NumberConverter) AddRule(i int, s string) {
	c.rules = append(c.rules, rule{i, s})
}

func (c *NumberConverter) SetDefaultRule(f func(int) string) {
	c.defaultRule = f
}

func (c *NumberConverter) ApplyRules(n int) string {
	for _, r := range c.rules {
		if n%r.i == 0 {
			return r.s
		}
	}

	return c.defaultRule(n)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id=&#34;day-19:0eee349fcbb2bb6aa93e7c8599ca1fb3&#34;&gt;Day 19&lt;/h4&gt;

&lt;p&gt;Established FBaaS solution. As the company grew, the scarcity of Go programmers
led them to hire expats from other environments. Slowly but surely, the codebase
begins to OOssify with Javaisms, and &lt;code&gt;*er&lt;/code&gt; classes, factories, interfaces and
implementations start to appear. All the things, encapsulate.&lt;/p&gt;

&lt;p&gt;Thank you Griesemer, Pike and Thompson, for leaving
inheritance out. At least that bullet was dodged.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// day19/buzzer.go
package day19

type BuzzerImpl struct{}

func (f *BuzzerImpl) Buzz(fb FBState) {
	if fb.Number()%5 == 0 {
		fb.SetState(fb.Number(), fb.String()+&amp;quot;buzz&amp;quot;)
	}
}

// ----------------------------------------------
// day19/factories.go
package day19

func NewFBState(n int) *FBStateImpl {
	return &amp;amp;FBStateImpl{n, &amp;quot;&amp;quot;}
}

func NewFormater() *FormaterImpl {
	return &amp;amp;FormaterImpl{}
}

func NewFizzer() *FizzerImpl {
	return &amp;amp;FizzerImpl{}
}

func NewBuzzer() *BuzzerImpl {
	return &amp;amp;BuzzerImpl{}
}

func NewFizzBuzzManager() *FizzBuzzManagerImpl {
	return &amp;amp;FizzBuzzManagerImpl{
		NewFizzer(),
		NewBuzzer(),
		NewFormater(),
	}
}

// ----------------------------------------------
// day19/fbstate.go
package day19

type FBStateImpl struct {
	i int
	s string
}

func (f *FBStateImpl) SetState(i int, s string) {
	f.i = i
	f.s = s
}

func (f *FBStateImpl) Number() int {
	return f.i
}

func (f *FBStateImpl) String() string {
	return f.s
}

// ----------------------------------------------
// day19/fizzer.go
package day19

type FizzerImpl struct{}

func (f *FizzerImpl) Fizz(fb FBState) {
	if fb.Number()%3 == 0 {
		fb.SetState(fb.Number(), fb.String()+&amp;quot;fizz&amp;quot;)
	}
}

// ----------------------------------------------
// day19/formatter.go
package day19

import &amp;quot;fmt&amp;quot;

type FormaterImpl struct{}

func (_ *FormaterImpl) Format(f FBState) string {
	if len(f.String()) == 0 {
		return fmt.Sprint(f.Number())
	} else {
		return f.String()
	}
}

// ----------------------------------------------
// day19/interfaces.go
package day19

// adapter for test harness
var FizzBuzz func(int) string = NewFizzBuzzManager().Manage

type FBState interface {
	SetState(int, string)
	Number() int
	String() string
}

type Fizzer interface {
	Fizz(FBState)
}

type Buzzer interface {
	Buzz(FBState)
}

type Formater interface {
	Format(FBState) string
}

// ----------------------------------------------
// day19/manager.go
package day19

type FizzBuzzManagerImpl struct {
	f Fizzer
	b Buzzer
	m Formater
}

func (i *FizzBuzzManagerImpl) Manage(n int) string {
	s := NewFBState(n)
	i.f.Fizz(s)
	i.b.Buzz(s)
	return i.m.Format(s)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id=&#34;day-20:0eee349fcbb2bb6aa93e7c8599ca1fb3&#34;&gt;Day 20&lt;/h4&gt;

&lt;p&gt;This one is special. Code will not be pasted inline: I&amp;rsquo;d need a new rant just
for it. See it &lt;a href=&#34;https://gitlab.com/carlosdavidepto/cavalcade-2018/tree/master/day20&#34;&gt;here&lt;/a&gt; instead.&lt;/p&gt;

&lt;p&gt;After 12 years of operation in the FBaaS market, many developers that came and
went and the realization that &amp;ldquo;exponential&amp;rdquo; means different things for
mathematicians than it does for the rest of the world,
the company&amp;rsquo;s codebase is fully OOssified.&lt;/p&gt;

&lt;p&gt;There are interfaces for everything, implementations for everything,
factories for some things, a manager object that does pretty much all
the business logic, a DI library refactoring that someone started but clearly
couldn&amp;rsquo;t finish, and even stale code that is no longer used but people are
afraid to delete because of Justin Case and their selective ignorance about
source control. Glorious.&lt;/p&gt;

&lt;p&gt;This codebase has clearly reached it&amp;rsquo;s maturity and enlightenment, the peak
of it&amp;rsquo;s existence. From this point on maintenance efforts will continue to
increase, adding new features will become next to impossible, and there will
be louder and louder calls for a rewrite. Its light will slowly dim over time,
waiting for the inevitable. The much sought rewrite, or the scrapping of the
entire project.&lt;/p&gt;

&lt;p&gt;The cycle of software life. Unstoppable, unending.&lt;/p&gt;

&lt;h4 id=&#34;day-21:0eee349fcbb2bb6aa93e7c8599ca1fb3&#34;&gt;Day 21&lt;/h4&gt;

&lt;p&gt;Unless you do it correctly.&lt;/p&gt;

&lt;p&gt;Here it is, the generalized &lt;code&gt;([a-y][a-y]zz){n}&lt;/code&gt; algorithm, as implemented by
someone
extremely competent in the arts and sciences of computer bending. The type of
person that refactors relentlessly until that last unneeded line of code
can be removed. The type of person that reads SICP for relaxation, Clean Code
for fun, and 13brane.net for a laugh.&lt;/p&gt;

&lt;p&gt;This started out as OO code. There was a &lt;code&gt;Rules(...).Apply&lt;/code&gt; there. Seriously.
There was even a type Rules and another type Rule, of all things. But the
continuous massaging of the code eventually made it shed all the extra fat,
culminating in the following masterpiece.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;package day21

import &amp;quot;fmt&amp;quot;

var FizzBuzz func(n int) string = Apply(
	Rule{3, &amp;quot;fizz&amp;quot;},
	Rule{5, &amp;quot;buzz&amp;quot;},
)

// DSL implementation ---

func Apply(rules ...Rule) func(int) string {
	return func(n int) string {
		s := &amp;quot;&amp;quot;

		for _, r := range rules {
			if n%r.divisor == 0 {
				s = s + r.part
			}
		}

		if s == &amp;quot;&amp;quot; {
			return fmt.Sprint(n)
		}

		return s
	}
}

type Rule struct {
	divisor int
	part    string
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id=&#34;day-22:0eee349fcbb2bb6aa93e7c8599ca1fb3&#34;&gt;Day 22&lt;/h4&gt;

&lt;p&gt;The company referred to in Day 20 was eventually acquired by a larger and older
competitor. Mostly for the IP (which turned out to be next to worthless) and
domain knowledge. It is decided that the FBaaS solution will finally be
retired in favor of a more traditional software delivery method and a more
familiar business model.&lt;/p&gt;

&lt;p&gt;Since a rewrite is due, the OSS code from Day 21 is pilfered with no attribution
whatsoever, to build the next product with optimal time-to-market.&lt;/p&gt;

&lt;p&gt;So, without further ado, we present, SmarTazz: all-in-one, XML configurable,
abstract enterprise rules engine for all your on-prem FizzBuzzBazzing needs.&lt;/p&gt;

&lt;p&gt;Licensing starts at $5000/yr, per node. Optional round-the-clock support
contract and mass discounts
available (contact sales for a quote). And of course, it crashes with
a cryptic error if you feed it bad configuration, like any respectable
enterprise grade software.&lt;/p&gt;

&lt;p&gt;The rules engine:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;package day22

import (
	&amp;quot;encoding/xml&amp;quot;
	&amp;quot;fmt&amp;quot;
	&amp;quot;io/ioutil&amp;quot;
	&amp;quot;os&amp;quot;
)

const CONFIG_PATH_ENV_VAR = &amp;quot;DAY22_CONFIG_PATH&amp;quot;

// FizzBuzz needs to be lazily initialized due to the use of `os.Env`.
// See test harness.
// var FizzBuzz func(n int) string = MakeXMLRulesApplicator()

func MakeXMLRulesApplicator() func(int) string {

	path := os.Getenv(CONFIG_PATH_ENV_VAR)
	config := LoadConfig(LoadConfigFileBytes(path))
	rules := config.Rules

	return func(n int) string {
		s := &amp;quot;&amp;quot;

		for _, r := range rules {
			if n%r.Divisor == 0 {
				s = s + r.Part
			}
		}

		if s == &amp;quot;&amp;quot; {
			return fmt.Sprint(n)
		}

		return s
	}
}

func LoadConfig(configBytes []byte) Config {
	config := Config{}

	err := xml.Unmarshal(configBytes, &amp;amp;config)
	if err != nil {
		panic(err)
	}

	return config
}

func LoadConfigFileBytes(path string) []byte {
	configBytes, err := ioutil.ReadFile(path)
	if err != nil {
		panic(err)
	}

	return configBytes
}

type Config struct {
	XMLName xml.Name `xml:&amp;quot;config&amp;quot;`
	Rules   []Rule   `xml:&amp;quot;rules&amp;gt;rule&amp;quot;`
}

type Rule struct {
	Divisor int    `xml:&amp;quot;divisor,attr&amp;quot;`
	Part    string `xml:&amp;quot;part,attr&amp;quot;`
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Standard FizzBuzz configuration:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;
&amp;lt;config&amp;gt;
	&amp;lt;rules&amp;gt;
		&amp;lt;rule divisor=&amp;quot;3&amp;quot; part=&amp;quot;fizz&amp;quot; /&amp;gt;
		&amp;lt;rule divisor=&amp;quot;5&amp;quot; part=&amp;quot;buzz&amp;quot; /&amp;gt;
	&amp;lt;/rules&amp;gt;
&amp;lt;/config&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id=&#34;day-23:0eee349fcbb2bb6aa93e7c8599ca1fb3&#34;&gt;Day 23&lt;/h4&gt;

&lt;p&gt;@carlosdavidepto, trying to showoff Go prowess by one-upping the l33ts, using
a purely declarative approach which exploits maps instead of slices. No
helper functions or &lt;code&gt;if&lt;/code&gt; statements needed.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;package day23

import &amp;quot;fmt&amp;quot;

func FizzBuzz(n int) string {
	return map[bool]map[bool]string{
		true:  {true: &amp;quot;fizzbuzz&amp;quot;, false: &amp;quot;fizz&amp;quot;},
		false: {true: &amp;quot;buzz&amp;quot;, false: fmt.Sprint(n)},
	}[n%3 == 0][n%5 == 0]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id=&#34;day-24:0eee349fcbb2bb6aa93e7c8599ca1fb3&#34;&gt;Day 24&lt;/h4&gt;

&lt;p&gt;@carlosdavidepto, solving FizzBuzz in job interviews with recruiters who clearly
did not read the resume, while trying to wrap up quickly to go home for the
holidays.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;package day24

import &amp;quot;fmt&amp;quot;

func FizzBuzz(n int) string {
	if n%3 == 0 {
		if n%5 == 0 {
			return &amp;quot;fizzbuzz&amp;quot;
		} else {
			return &amp;quot;fizz&amp;quot;
		}
	} else {
		if n%5 == 0 {
			return &amp;quot;buzz&amp;quot;
		} else {
			return fmt.Sprint(n)
		}
	}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This solution is probably the simplest and dumbest (and therefore maybe the
easiest to understand), but it has the interesting
properties of being purely functional (no internal state) and executing
exactly two branches per function call for the core
logic. Except maybe on Intel CPUs. We aren&amp;rsquo;t sure what executes on
those anymore.&lt;/p&gt;

&lt;h5 id=&#34;final-reflections:0eee349fcbb2bb6aa93e7c8599ca1fb3&#34;&gt;Final Reflections&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;I had way too much fun doing this series.&lt;/li&gt;
&lt;li&gt;Sometimes, doing (close to) nothing is the best course of action.
The simplest change is more often than not the correct change.&lt;/li&gt;
&lt;li&gt;Things can ALWAYS be made more complicated.&lt;/li&gt;
&lt;li&gt;Simplicity on the other hand, has at least one limit. Unlike rational numbers,
however, code may have more than one irreducible form.&lt;/li&gt;
&lt;li&gt;Unrefactoring can be as difficult as refactoring.&lt;/li&gt;
&lt;li&gt;Making good use of Functional Programming doesn&amp;rsquo;t require a Math PhD.&lt;/li&gt;
&lt;li&gt;FP has a vast array of tools in it&amp;rsquo;s belt, but there&amp;rsquo;s no need to use every
single one of them every time. Belt grinders are not meant for tightening
screws. Use a screwdriver instead.&lt;/li&gt;
&lt;li&gt;You can build DSLs without access to macros, hygienic or not. An XML
configuration file is, in a way, a DSL.&lt;/li&gt;
&lt;li&gt;Not everything needs a DSL, though. And there is nothing that really needs
XML.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;encoding/xml&lt;/code&gt; is so good, it almost makes you think XML was
a good idea. It might even be dangerous.&lt;/li&gt;
&lt;li&gt;Automated acceptance tests cut development time in half. Use them.&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>13brane&#39;s holidazed cavalcade of code shenanigans: the flavors of FizzBuzz - Days 9-16</title>
      <link>https://13brane.net/rants/holidazed-cavalcade-2018-day-9-16/</link>
      <pubDate>Sun, 16 Dec 2018 12:00:00 -0500</pubDate>
      
      <guid>https://13brane.net/rants/holidazed-cavalcade-2018-day-9-16/</guid>
      <description>

&lt;p&gt;&lt;em&gt;(Full source code for the entire series will be progressively published
&lt;a href=&#34;https://gitlab.com/carlosdavidepto/cavalcade-2018&#34;&gt;here&lt;/a&gt;, and the other days of the cavalcade are here: &lt;a href=&#34;https://13brane.net/rants/holidazed-cavalcade-2018-day-0/&#34;&gt;day 0&lt;/a&gt;,
&lt;a href=&#34;https://13brane.net/rants/holidazed-cavalcade-2018-day-1-8/&#34;&gt;1-8&lt;/a&gt;, &lt;a href=&#34;https://13brane.net/rants/holidazed-cavalcade-2018-day-17-24/&#34;&gt;17-24&lt;/a&gt;)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;FizzBuzz is a problem that maps rather well into functional programming (at
least as long as you don&amp;rsquo;t try to overcomplicate things), so
it is completely appropriate that we forego all state manipulations and refuse
to do anything with variables that could not be mapped directly to a
&lt;code&gt;let ... in ...&lt;/code&gt; construct.&lt;/p&gt;

&lt;p&gt;In other words: what would happen if you got a bunch of Haskell academics and
force fed them Go with a large spoon?&lt;/p&gt;

&lt;p&gt;Answer: Much wailing and gnashing of teeth.&lt;/p&gt;

&lt;h4 id=&#34;day-9:7345271d073e14cce97de1b3f05d7854&#34;&gt;Day 9&lt;/h4&gt;

&lt;p&gt;CompSci 232, Programming Paradigms. Data transformations only. Student is
a bit puzzled about the hype around FP, but managed to come up with something
which works and is not extra contrived.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;package day09

import &amp;quot;fmt&amp;quot;

type IntString struct {
	i int
	s string
}

func FizzBuzz(i int) string {
	return stringOf(buzzOf(fizzOf(IntString{i, &amp;quot;&amp;quot;})))
}

func fizzOf(a IntString) IntString {
	if a.i%3 == 0 {
		return IntString{a.i, a.s + &amp;quot;fizz&amp;quot;}
	} else {
		return a
	}
}

func buzzOf(a IntString) IntString {
	if a.i%5 == 0 {
		return IntString{a.i, a.s + &amp;quot;buzz&amp;quot;}
	} else {
		return a
	}
}

func stringOf(a IntString) string {
	if len(a.s) == 0 {
		return fmt.Sprint(a.i)
	} else {
		return a.s
	}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;em&gt;Note: any similarities with Day 2 are purely coincidental.&lt;/em&gt;&lt;/p&gt;

&lt;h4 id=&#34;day-10:7345271d073e14cce97de1b3f05d7854&#34;&gt;Day 10&lt;/h4&gt;

&lt;p&gt;Finalist undergrad student. Already has a thing for Haskell. Clearly wants
to pursue an academic career (the poor soul). Actually solved the problem in
Haskell first, then transpiled the code by hand with minor modifications.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;package day10

import &amp;quot;fmt&amp;quot;

// tuple, (int, string)
type IntString struct {
	i int
	s string
}

// FizzBuzz :: int -&amp;gt; string
func FizzBuzz(i int) string {
	return stringOf(buzzOf(fizzOf(IntString{i, &amp;quot;&amp;quot;})))
}

// fizzOf :: (int, string) -&amp;gt; (int, string)
func fizzOf(x IntString) IntString {
	return xof(divisibleBy(3), &amp;quot;fizz&amp;quot;)(x)
}

// buzzOf :: (int, string) -&amp;gt; (int, string)
func buzzOf(x IntString) IntString {
	return xof(divisibleBy(5), &amp;quot;buzz&amp;quot;)(x)
}

// xof :: (int -&amp;gt; bool) -&amp;gt; string -&amp;gt; ((int, string) -&amp;gt; (int, string))
func xof(check func(int) bool, rule string) func(IntString) IntString {
	return func(a IntString) IntString {
		if check(a.i) {
			return IntString{a.i, a.s + rule}
		} else {
			return a
		}
	}
}

// stringOf :: (int, string) -&amp;gt; string
func stringOf(a IntString) string {
	if len(a.s) == 0 {
		return fmt.Sprint(a.i)
	} else {
		return a.s
	}
}

// divisibleBy :: int -&amp;gt; (int -&amp;gt; bool)
func divisibleBy(n int) func(int) bool {
	return func(i int) bool {
		return i%n == 0
	}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id=&#34;day-11:7345271d073e14cce97de1b3f05d7854&#34;&gt;Day 11&lt;/h4&gt;

&lt;p&gt;Master&amp;rsquo;s student. Totally at ease with FP. Desperately wants to curry. Is
starting to question life choices.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;package day11

import &amp;quot;fmt&amp;quot;

// Why aren&#39;t we doing this in Haskell, again?

// (int, string) tuple
type IntString struct {
	i int
	s string
}

// simulate deriving Show for IntString
func (x IntString) String() string {
	if len(x.s) == 0 {
		return fmt.Sprint(x.i)
	} else {
		return x.s
	}
}

// FizzBuzz :: int -&amp;gt; string
func FizzBuzz(n int) string {

	// looks rather stupid without `let`

	// divisibleBy :: int -&amp;gt; (int -&amp;gt; bool)
	divisibleBy := func(n int) func(int) bool {
		return func(i int) bool {
			return i%n == 0
		}
	}

	// xof :: (int -&amp;gt; bool) -&amp;gt; string -&amp;gt; ((int, string) -&amp;gt; (int, string))
	xof := func(check func(int) bool, rule string) func(IntString) IntString {
		return func(x IntString) IntString {
			if check(x.i) {
				return IntString{x.i, x.s + rule}
			} else {
				return x
			}
		}
	}

	// currying? Would if I could.

	// fizzOf :: (int, string) -&amp;gt; (int, string)
	fizzOf := xof(divisibleBy(3), &amp;quot;fizz&amp;quot;)

	// buzzOf :: (int, string) -&amp;gt; (int, string)
	buzzOf := xof(divisibleBy(5), &amp;quot;buzz&amp;quot;)

	return buzzOf(fizzOf(IntString{n, &amp;quot;&amp;quot;})).String()
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id=&#34;day-12:7345271d073e14cce97de1b3f05d7854&#34;&gt;Day 12&lt;/h4&gt;

&lt;p&gt;PhD student. Wants to bring in the big Algebraic Data Type guns, and shoots
himself in the foot doing so. Is &lt;em&gt;really&lt;/em&gt; questioning some life choices.
Can&amp;rsquo;t even find time to curry, much less anyone to do it with.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;package day12

import &amp;quot;fmt&amp;quot;

// This is just silly. We could have used Rust.

// Let&#39;s pretend we have monads, destructuring, pattern matching
// and data constructors.

// data FB = AFizz a | ABuzz a | AFizzBuzz a | APlain a
type FB interface {
	Plain() int
	String() string
}

type APlain struct {
	p int
}

func (p APlain) Plain() int {
	return p.p
}
func (p APlain) String() string {
	return fmt.Sprint(p.p)
}

type AFizz struct {
	APlain
}

func (f AFizz) String() string {
	return &amp;quot;fizz&amp;quot;
}

type ABuzz struct {
	APlain
}

func (b ABuzz) String() string {
	return &amp;quot;buzz&amp;quot;
}

type AFizzBuzz struct {
	APlain
}

func (f AFizzBuzz) String() string {
	return &amp;quot;fizzbuzz&amp;quot;
}

func FizzBuzz(i int) string {
	return buzz(fizz(APlain{i})).String()
}

// really, I&#39;m going to ask my advisor why he&#39;s an idiot.

func fizz(x FB) FB {
	mod3 := x.Plain()%3 == 0

	if mod3 {
		switch x.(type) {
		case APlain:
			return AFizz{APlain{x.Plain()}}
		case ABuzz:
			return AFizzBuzz{APlain{x.Plain()}}
		default:
			return x
		}
	} else {
		return x
	}
}

func buzz(x FB) FB {
	mod5 := x.Plain()%5 == 0

	if mod5 {
		switch x.(type) {
		case APlain:
			return ABuzz{APlain{x.Plain()}}
		case AFizz:
			return AFizzBuzz{APlain{x.Plain()}}
		default:
			return x
		}
	} else {
		return x
	}
}

// oh god, kill me now.
&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id=&#34;day-13:7345271d073e14cce97de1b3f05d7854&#34;&gt;Day 13&lt;/h4&gt;

&lt;p&gt;PhD advisor. The kind that berates students for not knowing subjects he is
paid to teach. Fervent believer of the &amp;ldquo;hair-shirt approach&amp;rdquo;. Is considering
asking next year&amp;rsquo;s students to implement a purely functional virtual machine.
Someone should tell him about &lt;a href=&#34;https://github.com/urbit/&#34;&gt;this&lt;/a&gt;. And remind him that &lt;code&gt;decrement&lt;/code&gt; is
not a good primitive in terms of CPU cycle usage.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;package day13

import &amp;quot;fmt&amp;quot;

// my master&#39;s and phd students are dense. It&#39;s just one of those batches. If
// they got off imgur I&#39;m sure their output would improve, but cat pictures
// are a good use of student loans in 2018... The point of the exercise was
// to understand exactly how much effort is required to translate functional
// features to a non functional language. Translating Haskell to Haskell is
// not a good use of grants. Nimrods.

type (
	// data FB = Fizz FB | Buzz FB | Just a
	FB interface {
		Value() int
	}

	Just struct {
		i int
	}

	Buzz struct {
		fb FB
	}

	Fizz struct {
		fb FB
	}
)

// make constructors part of data class
func (j Just) Value() int { return j.i }
func (b Buzz) Value() int { return b.fb.Value() }
func (f Fizz) Value() int { return f.fb.Value() }

// buzz :: int -&amp;gt; FB
func buzz(n int) FB {
	if n%5 == 0 {
		return Buzz{Just{n}}
	} else {
		return Just{n}
	}
}

// fizz :: FB -&amp;gt; FB
func fizz(fb FB) FB {
	if fb.Value()%3 == 0 {
		return Fizz{fb}
	} else {
		return fb
	}
}

// show :: FB -&amp;gt; string -&amp;gt; string
func show(fb FB, prev string) string {
	switch v := fb.(type) {
	case Just:
		if len(prev) != 0 {
			return prev
		} else {
			return fmt.Sprint(v.i)
		}
	case Fizz:
		return show(v.fb, prev+&amp;quot;fizz&amp;quot;)
	case Buzz:
		return show(v.fb, prev+&amp;quot;buzz&amp;quot;)
	default:
		return &amp;quot;&amp;quot; // never happens, only makes compiler happy
	}
}

func FizzBuzz(n int) string {
	return show(fizz(buzz(n)), &amp;quot;&amp;quot;)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id=&#34;day-14:7345271d073e14cce97de1b3f05d7854&#34;&gt;Day 14&lt;/h4&gt;

&lt;p&gt;Tenured professor. The kind that berates other professors for berating students.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;package day14

import &amp;quot;fmt&amp;quot;

// Note to Dr. Ethelbert:
// I am not sure the students are the problem.

func FizzBuzz(n int) string {
	return IfThenElse(
		Cond(n%3 == 0),
		IfThenElse(
			Cond(n%5 == 0),
			Value(&amp;quot;fizzbuzz&amp;quot;),
			Value(&amp;quot;fizz&amp;quot;),
		),
		IfThenElse(
			Cond(n%5 == 0),
			Value(&amp;quot;buzz&amp;quot;),
			ToString(n),
		),
	).Solve()
}

// Haskell is for wimps. For a true hair-shirt experience, you should
// implement a (crude) lambda calculus interpreter instead.
type Calc struct {
	f func() string
}

func (c Calc) Solve() string {
	return c.f()
}

func True(x, _ Calc) Calc {
	return x
}

func False(_, y Calc) Calc {
	return y
}

func IfThenElse(c func(Calc, Calc) Calc, t, f Calc) Calc {
	return c(t, f)
}

// Go-&amp;gt;Lambda and Lambda-&amp;gt;Go transformations

func Cond(b bool) func(Calc, Calc) Calc {
	return map[bool]func(Calc, Calc) Calc{true: True, false: False}[b]
}

func Value(s string) Calc {
	return Calc{func() string {
		return s
	}}
}

func ToString(n int) Calc {
	return Calc{func() string {
		return fmt.Sprint(n)
	}}
}

// Oh, and we need to talk about grant allocations...
&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id=&#34;day-15:7345271d073e14cce97de1b3f05d7854&#34;&gt;Day 15&lt;/h4&gt;

&lt;p&gt;Self taught l33t h4x0r. Is into cryptography and applied math. Noticed that the
outputs of &lt;code&gt;FizzBuzz(n)&lt;/code&gt; are cyclical with a period of 15 over the input
integers, and proceeded to abuse Go arrays on that basis.&lt;/p&gt;

&lt;p&gt;Also wants to remind us not to use &lt;code&gt;(3,5)&lt;/code&gt; as the semiprimes for an RSA private
key.&lt;/p&gt;

&lt;p&gt;Got it.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Fun fact: at the time of this writing, &lt;a href=&#34;http://phuctor.nosuchlabs.com/factors&#34;&gt;there were at least 36 RSA Moduli all
over the web with &lt;code&gt;3&lt;/code&gt; as a prime factor&lt;/a&gt;. No need for anti-encryption
laws, people.&lt;/em&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;package day15

import &amp;quot;fmt&amp;quot;

func FizzBuzz(n int) string {
	x := [15]string{
		&amp;quot;fizzbuzz&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;fizz&amp;quot;, &amp;quot;&amp;quot;,
		&amp;quot;buzz&amp;quot;, &amp;quot;fizz&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;fizz&amp;quot;,
		&amp;quot;buzz&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;fizz&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;&amp;quot;,
	}[n%15]

	if x == &amp;quot;&amp;quot; {
		return fmt.Sprint(n)
	} else {
		return x
	}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id=&#34;day-16:7345271d073e14cce97de1b3f05d7854&#34;&gt;Day 16&lt;/h4&gt;

&lt;p&gt;Another, more experient, uber-l33t h4x0r. Is into all sorts of things,
including your home router. Thinks flow control is for sissies and prefers
to abuse first class functions and arrays in order to avoid
writing one &lt;code&gt;if&lt;/code&gt; statement. Likes to code-golf in APL, swap variables
without a tempvar and mine various
cryptocurrencies via JS snippets distributed through your niche WordPress blog.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;package day16

import &amp;quot;fmt&amp;quot;

func fb(_ int) string { return &amp;quot;fizzbuzz&amp;quot; }
func f(_ int) string  { return &amp;quot;fizz&amp;quot; }
func b(_ int) string  { return &amp;quot;buzz&amp;quot; }
func s(n int) string  { return fmt.Sprint(n) }

func FizzBuzz(n int) string {
	return [15]func(int) string{
		fb, s, s, f, s,
		b, f, s, s, f,
		b, s, f, s, s,
	}[n%15](n)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Tune in next week for the ultimate sacrilege: Object Oriented FizzBuzzes, and
a couple of extras.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>13brane&#39;s holidazed cavalcade of code shenanigans: the flavors of FizzBuzz - Days 1-8</title>
      <link>https://13brane.net/rants/holidazed-cavalcade-2018-day-1-8/</link>
      <pubDate>Sat, 08 Dec 2018 12:00:00 -0500</pubDate>
      
      <guid>https://13brane.net/rants/holidazed-cavalcade-2018-day-1-8/</guid>
      <description>

&lt;p&gt;&lt;em&gt;(Full source code for the entire series will be progressively published
&lt;a href=&#34;https://gitlab.com/carlosdavidepto/cavalcade-2018&#34;&gt;here&lt;/a&gt;, and the other days of the cavalcade are here: &lt;a href=&#34;https://13brane.net/rants/holidazed-cavalcade-2018-day-0/&#34;&gt;day 0&lt;/a&gt;,
&lt;a href=&#34;https://13brane.net/rants/holidazed-cavalcade-2018-day-9-16/&#34;&gt;9-16&lt;/a&gt;, &lt;a href=&#34;https://13brane.net/rants/holidazed-cavalcade-2018-day-17-24/&#34;&gt;17-24&lt;/a&gt;)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The FizzBuzz cavalcade started with eight procedural solutions to the problem.
In none of these does the code make use of anything you wouldn&amp;rsquo;t be able to
code with relative ease in C or even Assembly.&lt;/p&gt;

&lt;p&gt;Simple, &amp;ldquo;straight out of college&amp;rdquo; level procedural code.&lt;/p&gt;

&lt;h4 id=&#34;day-1:ddd6bd19545f5c8f744b99132db16c8a&#34;&gt;Day 1&lt;/h4&gt;

&lt;p&gt;The no BS, competent junior dev approach.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;package day01

import &amp;quot;fmt&amp;quot;

func FizzBuzz(n int) string {
	if n%3 == 0 &amp;amp;&amp;amp; n%5 == 0 {
		return &amp;quot;fizzbuzz&amp;quot;
	} else if n%3 == 0 {
		return &amp;quot;fizz&amp;quot;
	} else if n%5 == 0 {
		return &amp;quot;buzz&amp;quot;
	} else {
		return fmt.Sprint(n)
	}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is what you would write on your first class about flow control. Nothing
special about this, just honest, straightforward code. There are a couple of
ways in which this can improve, but in college you&amp;rsquo;ll still get a good grade
for it. In corporate, no one cares as long as the spec validates it (and
the profiler says this code is not running 90% of the execution time).&lt;/p&gt;

&lt;p&gt;It does translate the spec directly, though, so this is one of the more
&amp;ldquo;understandable&amp;rdquo; versions.&lt;/p&gt;

&lt;h4 id=&#34;day-2:ddd6bd19545f5c8f744b99132db16c8a&#34;&gt;Day 2&lt;/h4&gt;

&lt;p&gt;CompSci 101: Structured Programming (Good student version).&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;package day02

import &amp;quot;fmt&amp;quot;

func FizzBuzz(n int) string {
	var divBy3 bool = n%3 == 0
	var divBy5 bool = n%5 == 0
	var out string = &amp;quot;&amp;quot;

	if divBy3 {
		out = out + &amp;quot;fizz&amp;quot;
	}

	if divBy5 {
		out = out + &amp;quot;buzz&amp;quot;
	}

	if len(out) == 0 {
		out = fmt.Sprint(n)
	}

	return out
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Single entry point: check.&lt;br /&gt;
Single exit point: check.&lt;br /&gt;
No use of &lt;code&gt;goto&lt;/code&gt;: check.&lt;/p&gt;

&lt;p&gt;Bonus points for setting up all variables and constraints right at the start.
It&amp;rsquo;s still not optimal from an execution standpoint, as it uses 3 conditions
(the problem can be solved &amp;ldquo;normally&amp;rdquo; with only two per execution path),
but it&amp;rsquo;s still better than the previous version in that sense.&lt;/p&gt;

&lt;p&gt;Spec translation is not as direct here, but it is still very easy to grok
because the code path doesn&amp;rsquo;t branch in crazy ways. The state checking at
the end is kind of lame, though (and it&amp;rsquo;s the extra, unneeded &lt;code&gt;if&lt;/code&gt;).&lt;/p&gt;

&lt;h4 id=&#34;day-3:ddd6bd19545f5c8f744b99132db16c8a&#34;&gt;Day 3&lt;/h4&gt;

&lt;p&gt;CompSci 101: (Un)Structured Programming (Bad student version).&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;package day03

import &amp;quot;fmt&amp;quot;

var divBy3 bool
var by5 bool
var out string
var flag bool

func FizzBuzz(n int) string {
	// clean variable
	divBy3 = false
	by5 = false
	out = &amp;quot;&amp;quot;
	flag = false

	divBy3 = n%3 == 0
	by5 = n%5 == 0

	if divBy3 {
		out = out + &amp;quot;fizz&amp;quot;
		flag = true
	}

	if by5 {
		out = out + &amp;quot;buzz&amp;quot;
		flag = true
	}

	if !flag {
		out = fmt.Sprint(n)
	}

	return out
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This was clearly pilfered from the good student, with some things jumbled around
and deliberately muffled for plausible deniability.&lt;/p&gt;

&lt;p&gt;The TA wonders how this even compiles, then remembers that the tests were
given as part of the statement of the assignment. The true ode to BDD.
Wants to grade it a at zero,
but plausible deniability is too strong. It even has typos in the only comment
it got. No worries, this person will
eventually switch majors to something more in line with their level of
competence. Probably business administration or project management.&lt;/p&gt;

&lt;h4 id=&#34;day-4:ddd6bd19545f5c8f744b99132db16c8a&#34;&gt;Day 4&lt;/h4&gt;

&lt;p&gt;Advanced student. Understands separation of concerns and subroutines.
Wants to learn C++ one day, and will use every single fucking feature the
language has to offer, making trivial code non trivial because &amp;ldquo;juniors need
to be exposed to a wide variety of programming styles to become proficient&amp;rdquo;.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;package day04

import &amp;quot;fmt&amp;quot;

func FizzBuzz(n int) string {
	var out string = &amp;quot;&amp;quot;

	if divBy3(n) {
		out = out + &amp;quot;fizz&amp;quot;
	}

	if divBy5(n) {
		out = out + &amp;quot;buzz&amp;quot;
	}

	if len(out) == 0 {
		out = fmt.Sprint(n)
	}

	return out
}

func divBy3(n int) bool {
	return n%3 == 0
}

func divBy5(n int) bool {
	return n%5 == 0
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Could be worse.&lt;/p&gt;

&lt;h4 id=&#34;day-5:ddd6bd19545f5c8f744b99132db16c8a&#34;&gt;Day 5&lt;/h4&gt;

&lt;p&gt;&amp;ldquo;Advanceder&amp;rdquo; student. &lt;em&gt;Really&lt;/em&gt; understands subroutines and uses this
knowledge to stay DRY. At the obvious cost of readability, of course.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;package day05

import &amp;quot;fmt&amp;quot;

func FizzBuzz(n int) string {
	var out string = &amp;quot;&amp;quot;

	if divBy(n, 3) {
		out = out + &amp;quot;fizz&amp;quot;
	}

	if divBy(n, 5) {
		out = out + &amp;quot;buzz&amp;quot;
	}

	if len(out) == 0 {
		out = fmt.Sprint(n)
	}

	return out
}

func divBy(n, d int) bool {
	return n%d == 0
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id=&#34;day-6:ddd6bd19545f5c8f744b99132db16c8a&#34;&gt;Day 6&lt;/h4&gt;

&lt;p&gt;Sophomore student. Basics of programming forever engraved in neocortex.
Fully grasps SP, but has grown past that. Once read an article online called
&amp;ldquo;Else considered harmful&amp;rdquo;. Only writes code in &amp;ldquo;early-exit&amp;rdquo;
style since. Reads cat-v.org, uses VoidLinux and suckless tools as much
as possible.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;package day06

import &amp;quot;fmt&amp;quot;

func FizzBuzz(n int) string {
	if n%3 == 0 &amp;amp;&amp;amp; n%5 == 0 {
		return &amp;quot;fizzbuzz&amp;quot;
	}

	if n%3 == 0 {
		return &amp;quot;fizz&amp;quot;
	}

	if n%5 == 0 {
		return &amp;quot;buzz&amp;quot;
	}

	return fmt.Sprint(n)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id=&#34;day-7:ddd6bd19545f5c8f744b99132db16c8a&#34;&gt;Day 7&lt;/h4&gt;

&lt;p&gt;Girlfriend of previous student. They study together, but she&amp;rsquo;s not been
brainwashed yet. Cares more about code performance and good grades.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;package day07

import &amp;quot;fmt&amp;quot;

func FizzBuzz(n int) string {
	if n%3 == 0 {

		if n%5 == 0 {
			return &amp;quot;fizzbuzz&amp;quot;
		}

		return &amp;quot;fizz&amp;quot;
	}

	if n%5 == 0 {
		return &amp;quot;buzz&amp;quot;
	}

	return fmt.Sprint(n)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id=&#34;day-8:ddd6bd19545f5c8f744b99132db16c8a&#34;&gt;Day 8&lt;/h4&gt;

&lt;p&gt;&amp;ldquo;I can&amp;rsquo;t go out, I have a test three weeks from now&amp;rdquo; student. Also
friends with above couple, but a bit more reclusive. Really wants that A+.
Strives to write code so perfectly commented that he ends up generating line
noise. Diet consists of pizza, diet-coke, coffee and
whatever energy drink is nearest.&lt;/p&gt;

&lt;p&gt;Will have a meltdown if he ever leaves academia, especially if integrated into
a &amp;ldquo;fast-paced, multitasking&amp;rdquo; environment with lots of legacy projects.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;package day08

// import the &amp;quot;fmt&amp;quot; package, we&#39;ll need fmt.Sprint to convert integers to
// strings.
import &amp;quot;fmt&amp;quot;

// FizzBuzz takes a positive integer and returns a string. If the passed in
// integer is divisible by 3, the output is &amp;quot;fizz&amp;quot;. If it is divisible by 5,
// the output is &amp;quot;buzz&amp;quot;. If it is divisible by 3 and 5, the output is
// &amp;quot;FizzBuzz&amp;quot;. Otherwise, the output is the number itself, converted to its
// decimal string representation.
func FizzBuzz(n int) string {

	// all numbers need to be tested for divisibility by both factors.
	// therefore, we optimize the program by performing these divisions only
	// once
	divisibleby3 := n%3 == 0
	divisibleby5 := n%5 == 0

	if divisibleby3 {
		// number is divisible by 3

		// each number must be tested for both factors
		if divisibleby5 {
			// number is divisible by 3 and 5.
			return &amp;quot;fizzbuzz&amp;quot;
		}

		// number is not divisible by 5, only by 3
		return &amp;quot;fizz&amp;quot;
	}

	// number is not divisible by 3 from this point on

	if divisibleby5 {
		// number is divisible by 5
		return &amp;quot;buzz&amp;quot;
	}

	// number does not have 3 or 5 as prime factors
	return fmt.Sprint(n)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Good luck kid. You&amp;rsquo;ll need a lot of it.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>13brane&#39;s holidazed cavalcade of code shenanigans: the flavors of FizzBuzz - Day 0</title>
      <link>https://13brane.net/rants/holidazed-cavalcade-2018-day-0/</link>
      <pubDate>Fri, 30 Nov 2018 09:42:16 -0500</pubDate>
      
      <guid>https://13brane.net/rants/holidazed-cavalcade-2018-day-0/</guid>
      <description>

&lt;p&gt;&lt;em&gt;(Full source code for the entire series will be progressively published
&lt;a href=&#34;https://gitlab.com/carlosdavidepto/cavalcade-2018&#34;&gt;here&lt;/a&gt;, and the other days of the cavalcade are here: &lt;a href=&#34;https://13brane.net/rants/holidazed-cavalcade-2018-day-1-8/&#34;&gt;1-8&lt;/a&gt;,
&lt;a href=&#34;https://13brane.net/rants/holidazed-cavalcade-2018-day-9-16/&#34;&gt;9-16&lt;/a&gt;, &lt;a href=&#34;https://13brane.net/rants/holidazed-cavalcade-2018-day-17-24/&#34;&gt;17-24&lt;/a&gt;)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Hello intertubes! It&amp;rsquo;s that time of the year again. The time of ugly sweaters,
sun washed decorations you forgot to remove last year (after February 1st there
is no excuse, really), and that awkward hibernation HR departments and
LinkedIn recruiters alike go into because of some thing which relates to fiscal
years and budgets or what is it.&lt;/p&gt;

&lt;p&gt;Nothing fundamentally wrong with that, but then you don&amp;rsquo;t get to berate us
&lt;em&gt;unprofessionals&lt;/em&gt; for not being available to start a new position in say, July
or August. Just sayin&amp;rsquo;.&lt;/p&gt;

&lt;p&gt;The hibernation period will eventually, like all things periodical, come to an
end and the hordes of talent seekers will come out of the dungeons,
ready to ask you to complete a 40h+ coding assignment or worse, trying to assess
your programming might with FizzBuzzian techniques.&lt;/p&gt;

&lt;p&gt;So how do you prepare for this apocalypse?&lt;/p&gt;

&lt;p&gt;In the case of the forty hour idiocy, best is to ignore or tell the recruiters
to get some sense. Especially if you have a full time job already. If you are
currently in between jobs, you may opt for a different approach: perform the
coding assignment if you feel like it, but make the code available under the
following license:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Copyright &amp;copy; YEAR AUTHOR. All rights reserved.&lt;/p&gt;

&lt;p&gt;A non-transferable, non-exclusive license is hereby being granted to COMPANY,
hereafter referred to as THE LICENSEE, to peruse and scrutinize the code but
only for the porpoises (LOL) of assessing the viability of a potential
work partnership opportunity, which is, at this point, pretty low, since you
guys have no respect for anyone&amp;rsquo;s time. THE LICENSEE must not attempt run
the code in any way, including, but not limited to, feeding the code into an
interpreter, compiling into an executable or otherwise producing object or
runnable machine code. This includes static and dynamic linking.
In other words, you are going to read this, fuckers. Tests and everything.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For the twist after the stab, add:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For all other entities, the conditions of the MIT License apply.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;IANAL, you do this at your own risk. This approach is totally untested, so don&amp;rsquo;t
be surprised if you can&amp;rsquo;t reenter the industry after you hit send. You&amp;rsquo;ve been
warned.&lt;/p&gt;

&lt;p&gt;What about The Fizz? What do we do with that?&lt;/p&gt;

&lt;p&gt;We double down. You ask for &amp;ldquo;an implementation of FizzBuzz&amp;rdquo; and I say
&amp;ldquo;which variant&amp;rdquo;?&lt;/p&gt;

&lt;p&gt;Of course, there is no point in solving the same problem over and over again.
So my obviously flawless plan is as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Implement as many versions of FizzBuzz as I can preemptively, for shits and
giggles.&lt;/li&gt;
&lt;li&gt;Receive request to implement FizzBuzz.&lt;/li&gt;
&lt;li&gt;Deflect request Matrix style by directing requester to code repository.&lt;/li&gt;
&lt;li&gt;Be a smug prick.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And this is the whole point of the cavalcade. Is it possible to do 24 versions
of The Fizz and turn it into a sort of deranged advent calendar thing? Or will
my meager software developing capacity falter before the third sunset?&lt;/p&gt;

&lt;h4 id=&#34;day-0-spec-and-test-harness:6be05a1a8eb6ecba200b2740565b0b31&#34;&gt;Day 0: spec and test harness&lt;/h4&gt;

&lt;p&gt;The uninitiated to the software development practice would probably commit some
or all of the following three unforgivable offenses:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Not having a clear spec before starting development;&lt;/li&gt;
&lt;li&gt;Not having acceptance tests reflecting the spec;&lt;/li&gt;
&lt;li&gt;Starting at 1. We do not allow heresy here.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, without further ado, here they are. The common version of the spec:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Write a program that prints the numbers from 1 to 100. But for multiples of
three print &amp;ldquo;Fizz&amp;rdquo; instead of the number and for the multiples of five print
&amp;ldquo;Buzz&amp;rdquo;. For numbers which are multiples of both three and five print &amp;ldquo;FizzBuzz&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;&amp;ndash; &lt;a href=&#34;http://wiki.c2.com/?FizzBuzzTest&#34;&gt;C2Wiki&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A revised, more formal, but functionally equivalent and test friendly spec:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The function &lt;code&gt;FizzBuzz&lt;/code&gt;&lt;br /&gt;
takes in a &lt;em&gt;positive integer&lt;/em&gt; &lt;code&gt;n&lt;/code&gt;&lt;br /&gt;
and returns a &lt;em&gt;string&lt;/em&gt; &lt;code&gt;s&lt;/code&gt;&lt;br /&gt;
where &lt;code&gt;s&lt;/code&gt; is&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the &lt;em&gt;string&lt;/em&gt; &amp;ldquo;FizzBuzz&amp;rdquo;, when &lt;code&gt;n&lt;/code&gt; is both a multiple of 3 and a multiple of 5&lt;/li&gt;
&lt;li&gt;the &lt;em&gt;string&lt;/em&gt; &amp;ldquo;Fizz&amp;rdquo;, when &lt;code&gt;n&lt;/code&gt; is a multiple of 3 but not a multiple of 5&lt;/li&gt;
&lt;li&gt;the &lt;em&gt;string&lt;/em&gt; &amp;ldquo;Buzz&amp;rdquo;, when &lt;code&gt;n&lt;/code&gt; is a multiple of 5 but not a multiple of 3&lt;/li&gt;
&lt;li&gt;the decimal representation of the number &lt;code&gt;n&lt;/code&gt; in all other cases&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;Instead of doing the normal iterate and print in the main program, as that would
be trivial anyway, we are going to test if our implementations produce correct
outputs for all input values in the range 1-100 instead.&lt;/p&gt;

&lt;p&gt;In this case, the acceptance test is the following:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;package day00_test

import (
	&amp;quot;fmt&amp;quot;
	&amp;quot;testing&amp;quot;

	// we&#39;ll add the implementations here...
	&amp;quot;gitlab.com/carlosdavidepto/cavalcade-2018/day01&amp;quot;
)

func TestAllImplementations(t *testing.T) {
	implementations := []func(int) string{
		// ... and here.
		day01.FizzBuzz,
	}

	for _, FizzBuzzImpl := range implementations {
		testMultiplesOf3and5OutputFizzBuzz(t, FizzBuzzImpl)
		testMultiplesOf3OutputFizz(t, FizzBuzzImpl)
		testMultiplesOf5OutputBuzz(t, FizzBuzzImpl)
		testEveryOtherValueOutputsInputConvertedToString(t, FizzBuzzImpl)
	}
}

func testMultiplesOf3and5OutputFizzBuzz(t *testing.T, FizzBuzz func(int) string) {
	for i := 15; i &amp;lt;= 100; i = i + 15 {
		// 3 and 5 are the only prime factors of 15
		// therefore, all multiples of 3 and 5 are also multiples of 15
		if FizzBuzz(i) != &amp;quot;fizzbuzz&amp;quot; {
			t.Errorf(&amp;quot;Expected %v, got %v in FizzBuzz(%v)&amp;quot;, &amp;quot;fizzbuzz&amp;quot;, FizzBuzz(i), i)
		}
	}
}

func testMultiplesOf3OutputFizz(t *testing.T, FizzBuzz func(int) string) {
	for i := 3; i &amp;lt;= 100; i = i + 3 {
		if i%5 != 0 {
			// ignore multiples of 3 which are also multiples of 5 here
			// they are tested in the first case
			if FizzBuzz(i) != &amp;quot;fizz&amp;quot; {
				t.Errorf(&amp;quot;Expected %v, got %v in FizzBuzz(%v)&amp;quot;, &amp;quot;fizz&amp;quot;, FizzBuzz(i), i)
			}
		}
	}
}

func testMultiplesOf5OutputBuzz(t *testing.T, FizzBuzz func(int) string) {
	for i := 5; i &amp;lt;= 100; i = i + 5 {
		if i%3 != 0 {
			// ignore multiples of 5 which are also multiples of 3 here
			// they are tested in the first case
			if FizzBuzz(i) != &amp;quot;buzz&amp;quot; {
				t.Errorf(&amp;quot;Expected %v, got %v in FizzBuzz(%v)&amp;quot;, &amp;quot;buzz&amp;quot;, FizzBuzz(i), i)
			}
		}
	}
}

func testEveryOtherValueOutputsInputConvertedToString(t *testing.T, FizzBuzz func(int) string) {
	for i := 1; i &amp;lt;= 100; i++ {
		if i%3 != 0 &amp;amp;&amp;amp; i%5 != 0 {
			// ignore multiples of 5 and multiples of 3 here
			// they are tested in the other cases
			if FizzBuzz(i) != fmt.Sprint(i) {
				t.Errorf(&amp;quot;Expected %v, got %v in FizzBuzz(%v)&amp;quot;, fmt.Sprint(i), FizzBuzz(i), i)
			}
		}
	}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Tune in in a few days for more Fizz, this time with actual working
Buzzes. Tomorrow is day 1.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>De-facto closed source: the case for understandable software</title>
      <link>https://13brane.net/rants/de-facto-closed-source/</link>
      <pubDate>Wed, 28 Nov 2018 11:44:36 -0500</pubDate>
      
      <guid>https://13brane.net/rants/de-facto-closed-source/</guid>
      <description>

&lt;p&gt;For someone who has been a strong supporter of FOSS for a very long time,
watching what has been happening to the various FOSS communities over the past
half decade or so is kind of depressing (with some exceptions, of course).&lt;/p&gt;

&lt;p&gt;Let us consider one of the latest episodes in the saga of the
industry that has no idea what it is doing as a whole:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Hey everyone - this is not just a one off thing, there are likely to be many
other modules in your dependency trees that are now a burden to their authors.
I didn&amp;rsquo;t create this code for altruistic motivations, I created it for fun. I
was learning, and learning is fun. I gave it away because it was easy to do so,
and because sharing helps learning too. I think most of the small modules on
npm were created for reasons like this. However, that was a long time ago. I&amp;rsquo;ve
since moved on from this module and moved on from that thing too and in the
process of moving on from that as well. I&amp;rsquo;ve written way better modules than
this, the internet just hasn&amp;rsquo;t fully caught up.&lt;/p&gt;

&lt;p&gt;&amp;ndash; @dominictarr, in &lt;a href=&#34;https://gist.github.com/dominictarr/9fd9c1024c94592bc7268d36b8d83b3a&#34;&gt;statement on event-stream compromise&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;TL;DR: Tarr is no longer maintaining a node.js package that everyone and their
dog uses. No legitimate users step up to maintain said package, even though they
depend on it. Tarr hands over said package to a &amp;ldquo;helpful&amp;rdquo; stranger, who
immediately decides to monetize it via cryptocurrency pilfering.
Internet polarization ensues.&lt;/p&gt;

&lt;p&gt;Boy, that must have been a good day for this &amp;ldquo;helpful&amp;rdquo; person. Not so much for
Tarr, though, who got the crap end of the Internet for handing over the package
without properly vetting the stranger. How Tarr would have been able to do so
in a way that is 100% safe is not clear to me at this stage, but lets roll for
a bit with the assumption that a small amount of extra care on Tarr&amp;rsquo;s part
could have avoided this mess.&lt;/p&gt;

&lt;p&gt;This would mean that the original author of any FOSS package or application, by
publishing it, would have to accept as fact that any misuse of said software
would forever be their responsibility, or at least until that responsibility
is, diligently and ceremoniously, transferred to someone else, hot potato style.&lt;/p&gt;

&lt;p&gt;You know, like we do in the corporate world.&lt;/p&gt;

&lt;p&gt;This line of reasoning quickly leads us to a dead end where there is no
possible positive cost-benefit analysis on the matter of ownership of a part,
however small, of the FOSS ecosystem.&lt;/p&gt;

&lt;p&gt;Here&amp;rsquo;s a thought experiment: suppose it was Tarr himself who decided to add a
new crypto miner &amp;ldquo;feature&amp;rdquo; to his own package. Hell, it&amp;rsquo;s just one of the many
ways of
monetizing FOSS, after all. Though I will concede that it would not look good
in his rap sheet, the most interesting thing about this possibility is that it
is entirely legal. It is also possible that, if done correctly, no one would
have noticed for a long time.&lt;/p&gt;

&lt;p&gt;So what does this mean? It means that at any point in time any one FOSS
maintainer may entirely replace their code with anything they fancy, be it
crypto miners or &lt;code&gt;console.log(&amp;quot;ur mom, lol&amp;quot;)&lt;/code&gt;, make it unavailable permanently
or only on Tuesdays and full moons, and also, as with any property, transfer it
to anyone, without asking for your opinion.&lt;/p&gt;

&lt;p&gt;You on the other hand, the avid FOSS user, bestowed with the powers of binary
copying and the four essential freedoms of the GPL, get to say &amp;ldquo;yeah, maybe not
today&amp;rdquo;, and pull out your own, well behaved copy of the offended/offending
software, make the modifications you need, and proceed from there, optionally
publishing your own modified version of the codebase in question.&lt;/p&gt;

&lt;p&gt;But no one has time for that, right? We got some hip new webapps to ship.
No time to read all the code for the 40k dependencies they have, when we don&amp;rsquo;t
even have time to write unit tests. FOSS maintainers should be held to
higher standards so that we can better trust them! How dare they pull the
carpet on us like that?!&lt;/p&gt;

&lt;p&gt;Here&amp;rsquo;s the thing:&lt;/p&gt;

&lt;h5 id=&#34;foss-was-never-about-trust-in-software-owners:28341206f35492c957a7da73358de81f&#34;&gt;&lt;em&gt;FOSS was never about trust in software owners.&lt;/em&gt;&lt;/h5&gt;

&lt;p&gt;&lt;em&gt;It was about not needing to trust them to begin with.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Code is the only thing you can trust when you want to know what the software
is doing, when the company goes belly up, or when your system isn&amp;rsquo;t the same
system that the original authors were developing on.&lt;/p&gt;

&lt;p&gt;Code is the only thing you can trust, and by not reading it, you&amp;rsquo;ve forfeited
the most important benefit provided by this ecosystem: the choice of not
having to trust the authors regarding behavior or continuity.&lt;/p&gt;

&lt;p&gt;You want to download thousands of lines of useful, but random, code from the
internet, for free, run it in a
production web server, or worse, your user&amp;rsquo;s machine, trust it with your
paying users&amp;rsquo; data and reap that sweet dough. We all do. But then
you can&amp;rsquo;t be bothered to check the license, understand the software you are
running and still want to blame the people who make your business a possibility
when mistakes happen, while giving them nothing for it?
This is both incompetence and entitlement.&lt;/p&gt;

&lt;p&gt;Plus how is this any different from using proprietary software? If you&amp;rsquo;re not
going to take full advantage of FOSS, maybe you&amp;rsquo;re better off spending your
money on support contracts anyway. At least then, you are entitled to complain
until you&amp;rsquo;re blue in the mouth. Maybe you can even take someone to court!&lt;/p&gt;

&lt;p&gt;Your system is your responsibility and you owe your users that, especially
when they pay. This responsibility does not change when you choose to take
someone&amp;rsquo;s code so that you don&amp;rsquo;t have to write it yourself, especially since
you didn&amp;rsquo;t pay for that. This is not to say
that the FOSS ecosystem doesn&amp;rsquo;t benefit from a high degree of trust (it does),
however it can, and did, function without this new concept of trust by proxy,
because we used to do it the hard way: trust by check-modify-then-compile.&lt;/p&gt;

&lt;p&gt;I may be wrong, but in the millions of downloads of event-stream and it&amp;rsquo;s 1.5k
dependent packages, there should be at least 5 companies involved which, had
they spared 1 dev-hour per week each, should be more than enough to keep
event-stream kosher.&lt;/p&gt;

&lt;h5 id=&#34;de-facto-proprietary-software:28341206f35492c957a7da73358de81f&#34;&gt;De-facto proprietary software&lt;/h5&gt;

&lt;p&gt;Here&amp;rsquo;s the part that&amp;rsquo;s a bit depressing, at least for me.&lt;/p&gt;

&lt;p&gt;We may have reached a stage where FOSS doesn&amp;rsquo;t represent everything it used to
anymore, simply because there is too much of it. Too many lines of code, too
many competing solutions, too fast a rate of change. We want to keep those
security updates coming in straight from upstream, but how are we going to
do audits every week on our current constraints?&lt;/p&gt;

&lt;p&gt;The fact that some of the focus is being shifted to trust is no surprise in
this kind of environment. A FOSS ecosystem benefits tremendously from having
a solid trust base because it allows for more distributed work to happen.&lt;/p&gt;

&lt;p&gt;But it isn&amp;rsquo;t really trust. As it currently stands, it&amp;rsquo;s actually hope and
wishful thinking.&lt;/p&gt;

&lt;p&gt;I use many Linux distros here in this &lt;em&gt;haus&lt;/em&gt;. Of course I can&amp;rsquo;t audit the
entire kernel alone, much less all the code, patches and build scripts for all
the packages for all these distributions. What I do is I audit the parts that
I&amp;rsquo;m more interested in, and I hope that 1) the distro maintainers aren&amp;rsquo;t
malevolent, 2) that if they are, some one else will study the parts I haven&amp;rsquo;t
seen and 3) that someone else is also interested in the same parts I am, so
that they might catch things that slipped through my eye-comb.&lt;/p&gt;

&lt;p&gt;This paints a bleak picture of the future in the case where the growth of the
number of lines of code or number of patches per time period far outpaces the
growth of the number of developers and maintainers.&lt;/p&gt;

&lt;p&gt;So how do we avoid this?&lt;/p&gt;

&lt;h5 id=&#34;the-case-for-understandable-software:28341206f35492c957a7da73358de81f&#34;&gt;The case for understandable software&lt;/h5&gt;

&lt;p&gt;We must make software simpler. Much much simpler. And companies who base their
service offering on open source software must become more involved in
keeping this ecosystem alive in whichever capacity they can.&lt;/p&gt;

&lt;p&gt;Here is another thought experiment: is it possible for a new (but experienced)
developer to understand 80% of the part of the codebase they&amp;rsquo;ll be responsible
for within their first 2 weeks (80 hours)?&lt;/p&gt;

&lt;p&gt;If not, this person is overworked from day 1, because they will be, by
definition, unable to transfer their responsibilities
within the standard North-American notice period.
If they are fired or leave, no amount of jiggling can prepare a replacement
within the notice period, as guaranteed by fourth grade arithmetic. As a
consequence, no smooth transition can occur, and some domain knowledge will
inevitably be lost.&lt;/p&gt;

&lt;p&gt;You may want to adjust the above figures to your particular jurisdiction, but
the basic premise remains intact. In no other industry is it considered normal
for people to work with, let alone develop on, things they don&amp;rsquo;t understand at
least to a certain degree of confidence.&lt;/p&gt;

&lt;p&gt;Software must be made understandable. The essence of FOSS for me can be reduced
to one
fundamental computing right: &lt;em&gt;the right to refuse to run, on my machines, code
that I do not have the option to understand.&lt;/em&gt; That is it.&lt;/p&gt;

&lt;p&gt;Sure, there are
cybersecurity benefits, and economical benefits, and some others I can&amp;rsquo;t recall
right now. But when you try to argue with me that it is normal
for my government&amp;rsquo;s online tax submission system to require Adobe Flash and
the delivery of that overprivileged opaque blob to my browser, that&amp;rsquo;s when you
get the &amp;ldquo;public money, public source code&amp;rdquo; response, liberally
drizzled with the &amp;ldquo;holy fuck, how do you breathe&amp;rdquo; stare.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m not fundamentally opposed to closed source software, so as long as it runs
on someone else&amp;rsquo;s computer.&lt;/p&gt;

&lt;p&gt;However, as we&amp;rsquo;ve seen, having the source code is not enough to guarantee
understandability. It is therefore imperative that the software industry also
calms down a bit with this churning out of features, and more emphasis is given
to stability, cybersecurity, user privacy, and the understanding of one&amp;rsquo;s own
systems which underpins all of these. Because
that&amp;rsquo;s the bare minimum that any responsible entity can do, especially when
they happily take money from the masses for their &amp;ldquo;service&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;And if said service is based on FOSS from individual contributors, consider
supporting them. After all, they are supporting you. They don&amp;rsquo;t get to complain
when you don&amp;rsquo;t support them, but you don&amp;rsquo;t get to complain when things go wrong
either.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Darker</title>
      <link>https://13brane.net/rants/darker/</link>
      <pubDate>Fri, 16 Nov 2018 20:51:21 -0500</pubDate>
      
      <guid>https://13brane.net/rants/darker/</guid>
      <description>&lt;p&gt;The branes have worm-holled to a new hosting environment, to benefit from
Let&amp;rsquo;s Encrypt&amp;rsquo;s cybersecurity powers.&lt;/p&gt;

&lt;p&gt;But that&amp;rsquo;s not all. They have also received a bit of CSS makeup, so that the
site does not hurt anyone&amp;rsquo;s retinae, especially at night. Plus, it helps
to conserve energy, and we&amp;rsquo;ll need as much of it as we can find for the 2020
cryptocurrency rush. /s&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Battle lost: EME is a W3C recommendation</title>
      <link>https://13brane.net/rants/eme-battle-lost/</link>
      <pubDate>Sat, 23 Sep 2017 15:04:01 -0400</pubDate>
      
      <guid>https://13brane.net/rants/eme-battle-lost/</guid>
      <description>&lt;p&gt;A few months ago &lt;a href=&#34;https://13brane.net/rants/though-week-for-the-tubes-i/&#34;&gt;I wrote about this subject&lt;/a&gt;.
It turns out I was very, very
wrong. Not because EME is a good idea. It is not. It is in the same stupidity class
as putting a hornet&amp;rsquo;s nest inside your car as you are about to start a 2h summer
drive.&lt;/p&gt;

&lt;p&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=SPfdOOiuOHI&amp;amp;t=758s&#34;&gt;Bryan Lunduke brilliantly explains
why&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;No, I was wrong because I thought nobody would care enough to support Encrypted
Media Extensions as a standard feature in browsers (since it&amp;rsquo;s already available
in FF and Chrome as an option anyway), and because all the techs and
privacy orgs were against it. I honestly thought this would have been enough
to kill the proposal.&lt;/p&gt;

&lt;p&gt;Yet, 6 months later, money and lobbying have proven to speak louder than
reason and common sense. Against all odds, EME not only lives, &lt;a href=&#34;https://www.theverge.com/2017/7/8/15942238/web-drm-standard-eme-approved-controversy&#34;&gt;but is here to
stay&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I applaud the balls on the &lt;a href=&#34;https://www.eff.org/deeplinks/2017/09/open-letter-w3c-director-ceo-team-and-membership&#34;&gt;EFF to do the only right thing to
do&lt;/a&gt; in this regard,
which was to abandon the deaf clusterfuck of interests that plague the W3C. If
you are not there to be heard, best not to be there at all.&lt;/p&gt;

&lt;p&gt;The people who claim to defend the interests of the open web have demonstrated
that such openness is no longer a priority.&lt;/p&gt;

&lt;p&gt;Browsers are now recommended to include a closed piece of code that nobody can
verify, experiment with or otherwise validate from a cybersecurity perspective.
DRM laws make it illegal to do so. And history shows these things always work
as intended. &lt;a href=&#34;https://www.intel.com/content/www/us/en/architecture-and-technology/intel-amt-vulnerability-announcement.html&#34;&gt;Just ask
Intel&lt;/a&gt;.
They know.&lt;/p&gt;

&lt;p&gt;The world at large does not want to listen to the technical arguments, and
corporate interests just want them eliminated altogether. All because &amp;ldquo;users&amp;rdquo;,
all too eager to consume content,
while trusted to pay for things with their plastic, cannot possibly be trusted to
watch a movie without copying it. &lt;a href=&#34;https://thenextweb.com/eu/2017/09/21/eu-paid-report-concluded-piracy-isnt-harmful-tried-hide-findings/&#34;&gt;Or so we&amp;rsquo;re
told&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In any case, you can&amp;rsquo;t say we didn&amp;rsquo;t warn you. We, the ones who give a shit
about your machine being actually yours and acting as your attorney rather than
your parole officer, we actually warned everybody. We warned that all boundaries
would eventually be at risk.&lt;/p&gt;

&lt;p&gt;Browsers were a nice common ground, because they provided this boundary: there
were a ton of them and some of the relevant ones were open. For the longest time
browsers provided a nice compromise for content delivery: open and trusted, yet
found roughly everywhere. Millions of web applications were built, providing
information, services and functionality to whoever wanted it, in a cross-platform,
no-hassle way. We have now lost one side of this equation.&lt;/p&gt;

&lt;p&gt;&amp;ldquo;But Firefox and Chrome already had this. What&amp;rsquo;s the big deal?&amp;rdquo;&lt;/p&gt;

&lt;p&gt;The big deal is that FF and Chrome provided EME as an option. Other browsers
had a reasonable expectation that 99.99% of sites out there did not need this,
so EME was largely irrelevant except for a niche. Browsers will now be
&lt;em&gt;expected&lt;/em&gt; to implement EME, which means that browsers who want to remain 100%
open will basically not be implementing web standards correctly.&lt;/p&gt;

&lt;p&gt;A 100% open browser is essential for security on the open web, because once you
give up trusting the user agent, the privacy boundary is dead. The clean
separation between your computer and the untrusted code coming from the web is
compromised.&lt;/p&gt;

&lt;p&gt;But hey, why complain? Netflix is working well now.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>#equifux</title>
      <link>https://13brane.net/rants/equifux/</link>
      <pubDate>Sat, 23 Sep 2017 09:34:08 -0400</pubDate>
      
      <guid>https://13brane.net/rants/equifux/</guid>
      <description>&lt;p&gt;By now you probably heard about
&lt;a href=&#34;https://twitter.com/hashtag/equifux&#34;&gt;#Equifux&lt;/a&gt;.
Err, I mean Equifax.&lt;/p&gt;

&lt;p&gt;For those outside North America, that&amp;rsquo;s a consumer credit reporting agency.
What&amp;rsquo;s that, you ask? It&amp;rsquo;s a private entity that collects, maintains and
provides information about consumer credit to other entities (individuals,
but also public and private institutions).&lt;/p&gt;

&lt;p&gt;See, my European friends, here in the Great White North (and in the U. S. of A.)
we have this retarded
system where your ability to apply for a credit card or a loan does not
depend on sensible things like how much you&amp;rsquo;ve been making over the last 12
months, how long your work contract is, what collateral you can provide in
case of default, or what any of these elements are for your co-signer.&lt;/p&gt;

&lt;p&gt;Naaah, that would make way too much sense.&lt;/p&gt;

&lt;p&gt;So instead we have credit scores. Back in 2014 when I first arrived in Canada,
I was introduced to the concept in the following manner (conversation abridged
and paraphrased) while opening a bank account:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Bank: You&amp;rsquo;ll probably also want to have a credit card.&lt;/p&gt;

&lt;p&gt;Me: No, thanks. I already have one.&lt;/p&gt;

&lt;p&gt;Bank: Yes, but that is with a European bank. You&amp;rsquo;ll need one with a Canadian bank, otherwise you won&amp;rsquo;t have a credit score in Canada.&lt;/p&gt;

&lt;p&gt;Me: What is that and why do I need it?&lt;/p&gt;

&lt;p&gt;Bank: Well, you won&amp;rsquo;t be able to apply for loans without one.&lt;/p&gt;

&lt;p&gt;Me: That&amp;rsquo;s ok. I never had a loan and I don&amp;rsquo;t intend to have one.&lt;/p&gt;

&lt;p&gt;Bank: No, you don&amp;rsquo;t understand. You need a credit score, otherwise you won&amp;rsquo;t be able to have a mortgage or finance your car. You won&amp;rsquo;t be able to have any type of credit product, really, without building your credit score first.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At this point in the conversation, I am Jack&amp;rsquo;s puzzled neo-cortex. I thought
to myself, &amp;ldquo;Wait, I need to borrow money to be able to borrow more money&amp;rdquo;?&lt;/p&gt;

&lt;p&gt;A very sensible rationale, of course.&lt;/p&gt;

&lt;p&gt;By now it should be evident that this rant is not, in fact, about Equifax.
They&amp;rsquo;ve been beaten down enough already. They obviously
have the ITSec capacity of a tadpole drowning in ethanol, which was
made obvious when &lt;a href=&#34;https://arstechnica.com/information-technology/2017/09/equifax-directs-breach-victims-to-fake-notification-site/&#34;&gt;they made a separate site to handle the inquiries of people
affected by the breach with a domain name straight from a
Sakawa playbook, then proceeded to tweet out the URL for a spoof site that
a security researcher set up to prove the point above&lt;/a&gt;.
And there was that thing
with the &lt;a href=&#34;https://www.bloomberg.com/news/articles/2017-09-07/three-equifax-executives-sold-stock-before-revealing-cyber-hack&#34;&gt;executives supposedly selling stock after the
breach&lt;/a&gt;&amp;hellip;&lt;/p&gt;

&lt;p&gt;Just sigh and facepalm, people. Sigh and facepalm. The only competent department
in this company seems to be Public Relations. Hell of a job cleaning a mess of
these proportions the way they did it.&lt;/p&gt;

&lt;p&gt;No, this rant is about why these things are even allowed to exist to begin with.&lt;/p&gt;

&lt;p&gt;As stated above, I&amp;rsquo;m originally from Europe. Portugal to be exact. We do not
have credit scores there. Hell, we barely have credit cards accepted anywhere
except the major stores. Most merchants will only take debit or cash.&lt;/p&gt;

&lt;p&gt;Asking for a loan over there is something more involved and arcane than
checking a magic number on a sheet of paper provided by a company staffed by
tadpoles, but it does have it&amp;rsquo;s own set of merits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ability to pay for the loan is checked against current &amp;ndash; not past &amp;ndash;
information;&lt;/li&gt;
&lt;li&gt;there is no centralized source of credit information (read, no private
entity to hack).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&amp;ldquo;But Davide&amp;rdquo;, say the FICO luddites, &amp;ldquo;that is worse than a credit score because
some people just won&amp;rsquo;t have access to credit!&amp;rdquo;&lt;/p&gt;

&lt;p&gt;Of course not, &lt;em&gt;because they can&amp;rsquo;t pay it back&lt;/em&gt;. I have a magic number for you,
too: 2008. Remember that?&lt;/p&gt;

&lt;p&gt;&amp;ldquo;Well, you&amp;rsquo;re also forgetting that without credit scores you have to share
your information with any institution that you inquire for credit. That&amp;rsquo;s
actually more possibilities to hack.&amp;rdquo;&lt;/p&gt;

&lt;p&gt;Cute argument, but that is not the way it works. Unlike here in North America,
where the Social Security Number is sacred and must be kept safe and away
from prying eyes (yet all past employers and possibly your mobile phone provider
will ask for it, fuck logic&amp;hellip;), in Portugal at least our ID numbers are just
that: a number. They aren&amp;rsquo;t used for security anywhere relevant. You actually have to
provide your ID card (not any card with a photo, the actual, only ID card)
when your identity is to be verified. And usually you have to be at the bank
or store in person when applying for financing of any type.&lt;/p&gt;

&lt;p&gt;So, while in theory more institutions with my salary info and full name,
address, etc. is not exactly the best scenario ever, the fact is that even if
those data points were to be compromised, the identity thief&amp;rsquo;s options are
quite narrow. Identity theft is not something Europeans lose their
sleep over, because North America is the lowest hanging fruit in this case.&lt;/p&gt;

&lt;p&gt;Here&amp;rsquo;s a fun fact, though. I ended up getting a credit card in Canada and
canceling all others (for practical reasons). And, since I was told that using
the card consistently builds credit score, I thought &amp;ldquo;why not, it can&amp;rsquo;t hurt,
and I&amp;rsquo;m getting cashbacks anyway&amp;rdquo;. Fast forward 3 years, and our credit
monitoring friends cannot calculate my credit score. The reason is very simple:
I never borrowed money (I pay everything on the card immediately, so the
balance is always 0). According to the rules, if you pay all your invoices
within 30 days, you&amp;rsquo;ll have a top credit score. But pay them &lt;em&gt;before&lt;/em&gt;, and
the system cannot say that you have good credit.&lt;/p&gt;

&lt;p&gt;This system is broken beyond repair. None of it&amp;rsquo;s premises make any sense.&lt;/p&gt;

&lt;p&gt;Given recent events and the fact that credit scores aren&amp;rsquo;t actually needed,
what I&amp;rsquo;d really like to know is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;why are credit reporting companies allowed to collect this much information
without VERY explicit consent?&lt;/li&gt;
&lt;li&gt;why aren&amp;rsquo;t credit reporting bureaus a public institution, rather than private?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And for fuck&amp;rsquo;s sake, find a way to make the SSN a normal identifier, instead of
a magic-confidential-but-not-really predictable series of digits.&lt;/p&gt;

&lt;p&gt;At least the &lt;a href=&#34;http://www.cbc.ca/news/business/equifax-data-breach-privacy-commissioner-1.4292516&#34;&gt;OPC is launching a probe into the Equifax
hack&lt;/a&gt;.
Maybe something good will come out of this mess after all.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Though week for the tubes - What to know about CIA&#39;s leak (Vault 7).</title>
      <link>https://13brane.net/rants/though-week-for-the-tubes-ii/</link>
      <pubDate>Sat, 11 Mar 2017 12:01:00 -0500</pubDate>
      
      <guid>https://13brane.net/rants/though-week-for-the-tubes-ii/</guid>
      <description>

&lt;p&gt;(First part of this rant &lt;a href=&#34;https://13brane.net/rants/though-week-for-the-tubes-i&#34;&gt;here&lt;/a&gt;.)&lt;/p&gt;

&lt;p&gt;If there was ever a time to be skeptical about what software is doing in
your machine, this would be it.&lt;/p&gt;

&lt;p&gt;As referenced in our previous instalment, &lt;a href=&#34;https://wikileaks.org/ciav7p1/&#34;&gt;this&lt;/a&gt;
happened.&lt;/p&gt;

&lt;p&gt;Now, before anything else, it might be a good idea to untwist our panties.
And prune the misinformation that has been circulating a little bit.
Only after that can we try to really sort this mess out.&lt;/p&gt;

&lt;p&gt;Here&amp;rsquo;s the gist of it.&lt;/p&gt;

&lt;p&gt;First of all, the CIA is &lt;em&gt;not&lt;/em&gt; able to crack the encryption algorithms of apps
like WhatsApp, Telegram and Signal. Which is why they went for the easier
route of cracking the phones&amp;rsquo; OSes instead. This can be done remotely.&lt;/p&gt;

&lt;p&gt;Second, CIA has the ability to crack computers (Windows, MacOS and Linux)
and Samsung Smart TVs, although nothing I&amp;rsquo;ve read so far indicates that this
can be done in a purely remote fashion. Apparently, physical access to the
target device is required in one form or another (I&amp;rsquo;m still waiting to see more
details though).&lt;/p&gt;

&lt;p&gt;Third, it looks like these operations were not of the dragnet type (as the ones
referenced in the Snowden leaks), rather they were more the kind of targeted
operation.&lt;/p&gt;

&lt;p&gt;Fourth, the large number of vulnerabilities that existed in CIA&amp;rsquo;s catalog is
surprising, considering that the three letter folk are not supposed to hoard
vulnerabilities and keep them hidden from US companies, as set forth by the
&lt;a href=&#34;https://jia.sipa.columbia.edu/online-articles/healey_vulnerability_equities_process&#34;&gt;Vulnerability Equities Process&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Fifth, a large number of IP addresses corresponding to US locations were under
active CIA monitoring. This is surprising because, with few exceptions, the
&lt;a href=&#34;http://www.newsweek.com/cia-donald-trump-surveillance-monitoring-americans-544315&#34;&gt;CIA has jurisdiction only over foreign territories&lt;/a&gt;.&lt;/p&gt;

&lt;h5 id=&#34;what-this-means-to-the-regular-joe:8fb13c5fde649963ab401a58b1bf73de&#34;&gt;What this means to the regular Joe.&lt;/h5&gt;

&lt;p&gt;If said Joe is American, it means that Joe can now &amp;ldquo;initiate the debate&amp;rdquo;
about the possible overreach of the agency&amp;rsquo;s activities. He may also question
the agency&amp;rsquo;s attitude towards VEP and the US tech industry. There are &amp;ldquo;laws&amp;rdquo;
which these bodies are supposed to &amp;ldquo;follow&amp;rdquo;, and then the citizen, with the help
of the courts is supposed to make them accountable.&lt;/p&gt;

&lt;p&gt;If said Joe is not American&amp;hellip; Tough shit. As an awesome band once said,
&amp;ldquo;We&amp;rsquo;re all living in America&amp;rdquo;. But we are not all American, and there&amp;rsquo;s a big
difference.&lt;/p&gt;

&lt;p&gt;See Joe, if you are not American, the US of A has no responsibility to your
particular individual. None. You are a data point. And in this case, the more
interesting the data point is, the &lt;em&gt;worse off&lt;/em&gt; the data point is likely to be.&lt;/p&gt;

&lt;p&gt;In both cases, we can all see the pointlessness of this particular discussion.&lt;/p&gt;

&lt;p&gt;First, because the American taxpayer &lt;em&gt;is paying&lt;/em&gt; the CIA to do exactly what it
is doing. Whether the taxes are well spent or not is a totally different
discussion.  The CIA is an &lt;em&gt;intelligence&lt;/em&gt; agency, and as such, collects
intelligence. They are, in essence, doing their job and doing it in a very
successful fashion.&lt;/p&gt;

&lt;p&gt;Second, for citizens of other nations: what are you complaining about? You
bought the computer/phone/toaster knowing it was American. It can come with
a backdoor from the factory itself, for all you care. Or maybe the device is
Korean, but the OS most likely is not. Redmondites and Cupertinites cannot
complain about this: you put your hand in the lion&amp;rsquo;s mouth, &lt;em&gt;voluntarily&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s your rented, filthy kitchen, and you
&lt;a href=&#34;http://www.loper-os.org/?p=1299&#34;&gt;can&amp;rsquo;t blame the mice&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So just sit back, relax, enjoy your DRM&amp;rsquo;d content. If you are being spied on
by the CIA (you probably aren&amp;rsquo;t &amp;ndash; your bulk data is going to the NSA instead
and there is no budget to do targeted surveillance on everyone),
just rejoice in the fact that you are effectively not an interesting person,
and the CIA will find nothing on you because there is nothing to find.&lt;/p&gt;

&lt;h5 id=&#34;what-this-means-to-the-intelligent-non-it-joe:8fb13c5fde649963ab401a58b1bf73de&#34;&gt;What this means to the intelligent (non-IT) Joe.&lt;/h5&gt;

&lt;p&gt;It means a couple of bad things. The first bad thing is that your devices,
where you store your personal thoughts and private conversations can, under
certain conditions, reveal those private bits of information to parties you
do not necessarily trust.&lt;/p&gt;

&lt;p&gt;You might personally trust the CIA or the NSA (or not), but most of us would
agree that a stolen computer is, when stolen, in the hands of an untrusted
party. If you&amp;rsquo;re a journalist, a physician, a therapist or an attorney, this
is obviously a big problem. And the key facts about the list of vulnerabilities
in the CIA menu are that &lt;em&gt;they exist&lt;/em&gt; and &lt;em&gt;they are exploitable&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Vulnerabilities are not particularly selective about who exploits them. The
usual fallacy accompanying these debates is that &amp;ldquo;only the CIA knew about
said holes&amp;rdquo;. Which is unprovable at best, and false if we are really unlucky.&lt;/p&gt;

&lt;p&gt;The other bad thing is that you don&amp;rsquo;t really have anyone to fully trust right
now. Your device is not giving you an adequate amount of privacy protections,
and lets not talk about cloud services for brevity. Spy agencies broke their
promises of sharing the holes with the tech industry so they can be fixed, and
the tech industry continues to ship shitty software because &amp;ldquo;OMG quarterly
statement! New Seed Round! YAS!&amp;rdquo;&lt;/p&gt;

&lt;p&gt;Your options right now, are to refuse technology, which is extremely
inconvenient, or live with the risks (which to be fair are not all that bad
if your are already doing all the good practices, but are unnecessary and
could be avoided). In particular, for nationals of countries other than the
US, who have no good reason to trust the American spy agencies by default
(due to the lack of a bond, be it legal, patriotic or otherwise), it raises
the questions of &amp;ldquo;what is my own country doing to protect me in this case?&amp;rdquo;
And we all no what the answer to that question is.&lt;/p&gt;

&lt;h5 id=&#34;finally-a-word-to-my-fellow-members-of-the-tech-industry:8fb13c5fde649963ab401a58b1bf73de&#34;&gt;Finally, a word to my fellow members of the tech industry.&lt;/h5&gt;

&lt;p&gt;This one is mostly to the software engineers, developers and
programmers (sysadmins, you are in the clear, but only today).&lt;/p&gt;

&lt;p&gt;Here is a simple fact of life for us: We are writing crap software.
But not just any crap. Crap of the dangerously negligent persuasion. Don&amp;rsquo;t
give me the usual &amp;ldquo;all software has bugs&amp;rdquo; discourse, because this is not
entirely true. And worse than spreading a lie, is spreading one which creates in
software users the belief that it is ok if software has bugs because that&amp;rsquo;s
just the way things are. &lt;strong&gt;One software bug due to an honest programming mistake
is not the same as three compounded bugs, which can be combined in order to
get root on the machine, all of which can be traced back to errors your
compiler should be able to catch by itself&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;There are well known ways of writing software which does not
break (or at least, breaks in a predictable, non destructive way). There are,
for instance, languages which check array boundaries automatically to prevent
buffer overflows (and hence, arbitrary code execution).
&lt;a href=&#34;https://golang.org/&#34;&gt;Many&lt;/a&gt; of &lt;a href=&#34;https://www.python.org/&#34;&gt;them&lt;/a&gt;.
There are &lt;a href=&#34;https://www.haskell.org/&#34;&gt;languages&lt;/a&gt; &lt;a href=&#34;https://ocaml.org/&#34;&gt;which&lt;/a&gt;,
upon compilation, can prove, that a program or code unit is coherent
with its own specification.
&lt;a href=&#34;http://se.ethz.ch/~meyer/publications/online/eiffel/basic.html&#34;&gt;Languages&lt;/a&gt;
which have embedded continuous testing
constructs. &lt;a href=&#34;https://www.erlang.org/&#34;&gt;Languages&lt;/a&gt; which allow you to write a
massively scaled web service that is sane, secure,
and does not need to be restarted every 5 minutes (true story, google &amp;ldquo;ruby&amp;rdquo;
and &amp;ldquo;Zed Shaw&amp;rdquo; to get started).
&lt;a href=&#34;https://en.wikipedia.org/wiki/Lisp_%28programming_language%29&#34;&gt;Languages&lt;/a&gt;
&lt;a href=&#34;http://racket-lang.org/&#34;&gt;which&lt;/a&gt; allow you to, interactively,
inspect everything the program is doing and why (and I was told there are
machines that &lt;a href=&#34;http://www.loper-os.org/?p=932&#34;&gt;can&lt;/a&gt; do this
&lt;a href=&#34;http://www.magic-1.org/&#34;&gt;too&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;To top it all off there are methods of all sorts to avoid software development
pain, but the teaching institutions are terrible at forwarding this knowledge
because they lack real world experience and in general are too slow to pick up
on the changes. The industrial institutions on the other hand, have the
environment where this is needed and can be practiced, but because management
is more interested in bottom lines than in the morale of their &amp;ldquo;warriors&amp;rdquo;
(something I actually heard at one point) and they see software development as
just another kind of brick-laying, you are left to your own devices to figure
out what real software engineering is about.&lt;/p&gt;

&lt;p&gt;You read about these hotshots that could swap two locations in memory without a
temporary slot and can implement quicksort by heart (why?) and pretty soon you
are indoctrinated to think &amp;ldquo;garbage collectors are for pussies&amp;rdquo;, that all that
overhead will make your program slow and programming in C is the shit. If your
program is more than 5K SLOC of C, it probably is the shit.  Just not in the
way you think. Same applies to C++. A turd with class is still a turd. There&amp;rsquo;s
a reason the &lt;a href=&#34;http://suckless.org&#34;&gt;suckless&lt;/a&gt; crowd write software that small
with such a limited feature set: using these types of tools to build software,
particularly the ones which are hostile to modern testing practices due to
their nature, requires that the entire spec of the program can fit in ones head
while developing, lest the developer fall into a small distraction and create
another Heartbleed or Cloudbleed. Sane design, as they define it, calls for a
ruthless ability to refuse adding features.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;ll pause here a moment to semi-exclude embedded developers and those who
build real time systems from this, who obviously don&amp;rsquo;t have many choices in
terms of their tools. For now. Available memory and resources tend to go up. So
this will not be an excuse in the future. And obviously, the fact that you are
using C or C++ by necessity does not mean you are excused from producing
correct code which either works as intended, or not at all. It merely excuses
you from the choice of a better platform, because currently there isn&amp;rsquo;t one.
The IoT security mess is still there to be cleaned up. And the mop has your
name on it.&lt;/p&gt;

&lt;p&gt;For everyone else, there are no excuses at all. RAM is cheap, CPU is cheap,
disk is cheap and bandwidth is cheaper. We have all the elements needed to
build sane, humanly uncomplicated systems, which may be complicated for the
computer to deal with, but that is why we build them anyway (to deal with
complicated comptutations), and do what the user intended and nothing more.
They would perhaps lack a couple of &amp;ldquo;features&amp;rdquo;, but they wouldn&amp;rsquo;t put the
users&amp;rsquo; privacy at risk.&lt;/p&gt;

&lt;p&gt;But of course, in the &amp;ldquo;real world&amp;rdquo;, we can&amp;rsquo;t have that, because the user wants
content (or marketing says they do anyway) and a red squiggly mark beneath
their misspelled words. The content must be decrypted with a half tested
blob and toy ciphers that can&amp;rsquo;t be audited. The squiggly (which is in fact a
useful feature) must be implemented as a &amp;ldquo;temporary&amp;rdquo; hack because the previous
&amp;ldquo;engineers&amp;rdquo; (who are now VPs of Sales, go figure) fucked up the graphics
implementation, as they &amp;ldquo;were on a tight deadline&amp;rdquo;. As a result, the API
is terrible and the implementation is worse. And of course, the lump has no
testing framework whatsoever, so you&amp;rsquo;re afraid to do the much needed refactoring
because you fear it will just break everything. You are now forced
to write your own little lumps on top of this big lump because of &amp;ldquo;backwards
compatibility&amp;rdquo; (which is usually backwards only, and not compatible in any way).&lt;/p&gt;

&lt;p&gt;And before the holders of the &lt;em&gt;status quo&lt;/em&gt; flagstaff come to ask &amp;ldquo;Well, what
are you going to do? Come and fix all our security issues in our software
then&amp;rdquo;, let me remind you of the fact that such a proposition makes no sense. A
civil engineer pointing out a flaw in the development process of a couple
hundred buildings would never be asked to go in and fix the flaws themselves.
They would, probably, be asked for input, and thanked (or possibly paid) for it
instead.  Handling the flaws in the process is still the responsibility of
someone else (whoever signed for the particular building). &lt;strong&gt;The security
vulnerabilities introduced by your code are &lt;em&gt;your&lt;/em&gt; responsibility. No one
else&amp;rsquo;s.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The complete pill for this is, that we, as a profession, stop being spineless
minions and learn to say no&lt;/strong&gt;. I can&amp;rsquo;t account for how many times I&amp;rsquo;ve heard some
sort of responsibility dismissing comment along the lines of &amp;ldquo;management wants
it like that&amp;rdquo; or &amp;ldquo;I just write the code&amp;rdquo;. Well, as we&amp;rsquo;ve seen from the leaks,
management does not know (or doesn&amp;rsquo;t care, which is worse) about the consequences
and the code you &amp;ldquo;just wrote&amp;rdquo; is now putting millions of people at risk.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Next time refuse to write broken software from the start&lt;/strong&gt;. That&amp;rsquo;s how messes
like these eventually get cleaned up. Because doing it the other way around is
how we got to the mess in the first place. Especially, when the code you write
is used by millions of people every day.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Though week for the tubes - Ars tries to pull a Lazarus on browser EME standards.</title>
      <link>https://13brane.net/rants/though-week-for-the-tubes-i/</link>
      <pubDate>Sat, 11 Mar 2017 12:00:00 -0500</pubDate>
      
      <guid>https://13brane.net/rants/though-week-for-the-tubes-i/</guid>
      <description>&lt;p&gt;I had planned a different type of rant for today, but a couple of pressing
issues have taken precedence.&lt;/p&gt;

&lt;p&gt;So long story short,
&lt;a href=&#34;https://arstechnica.com/business/2017/03/drm-in-html5-is-a-victory-for-the-open-web-not-a-defeat/&#34;&gt;this&lt;/a&gt; and
&lt;a href=&#34;https://wikileaks.org/ciav7p1/&#34;&gt;this&lt;/a&gt; happened.&lt;/p&gt;

&lt;p&gt;(For the second part of this rant, about Wikileaks being in the process of
releasing Vault7,
a massive leak detailing the power and scope of CIA&amp;rsquo;s computer hacking
operations, see &lt;a href=&#34;https://13brane.net/rants/though-week-for-the-tubes-ii&#34;&gt;here&lt;/a&gt;.)&lt;/p&gt;

&lt;p&gt;For those who have not yet taken the course on link clicking and/or live under
a digital rock, ArsTechnica republished an old op-ed about enabling web
browsers&amp;rsquo; Encrypted Media Extensions, and this time around, highlighting the
fact that the EME W3C work group&amp;rsquo;s charter is about to expire, and how
important it is to keep this debate alive.&lt;/p&gt;

&lt;p&gt;At this point, it should be beyond clear that nobody cares about DRM in web
browsers. That an increasingly irrelevant
body such as the W3C is about to see a proposal expire due to inactivity,
especially one like this, is not surprising. Ars resurrecting the
&amp;ldquo;supporting view&amp;rdquo; in the hopes of keeping the zombie from disintegrating is,
though.&lt;/p&gt;

&lt;p&gt;To quote from Ars&amp;rsquo; article:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Last year, the working group asked for such an extension [to the EME group&amp;rsquo;s
charter], but the Advisory Committee could not come to any consensus on
whether to grant it. W3C director and inventor of the Web Tim Berners-Lee
last week voiced his support for the EME plan, but the future of EME and the
working group&amp;rsquo;s efforts are currently in limbo. Many of the arguments being
made today mirror those made in 2013 when the working group first set about
developing EME. And in light of this pending decision, we&amp;rsquo;re resurfacing the
op-ed below (from May 2013) that outlines the supporting view.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Which is an elaborate way of saying: &amp;ldquo;We know no one cares, but can we keep this
lobby alive? Pretty please?&amp;rdquo;&lt;/p&gt;

&lt;p&gt;It is worth pointing out that what is being discussed is not the lack of
browser support for EME.
&lt;a href=&#34;https://support.mozilla.org/t5/Video-audio-and-interactive/Watch-DRM-content-on-Firefox/ta-p/37423&#34;&gt;Firefox has DRM support via Widevine and Primetime&lt;/a&gt;.
Chrome has &lt;a href=&#34;https://boingboing.net/2017/01/30/google-quietly-makes-optiona.html&#34;&gt;recently made it&amp;rsquo;s EME extension mandatory&lt;/a&gt;.
W3C&amp;rsquo;s effort is not about availability, but consensus (i.e. yet another
standard).&lt;/p&gt;

&lt;p&gt;DRM&amp;rsquo;d content in browsers is to the web&amp;rsquo;s relevance as an extra glass of
water is to the Pacific: it makes no fucking difference whatsoever.&lt;/p&gt;

&lt;p&gt;The web is relevant because it gelled. Even the &amp;ldquo;enlightened&amp;rdquo; announcing the
end of the web and the dawn (which is more like noon now&amp;hellip;) of mobile have to
acknowledge the simple truth that mobile &lt;em&gt;is built upon the web&lt;/em&gt;. Even if
everybody stops using web browsers, the web will still be there as the pipe for
the APIs that power everything, from your weekend binge of right swiping to
your imported Japanese butane fueled smart toaster oven (now with more
analytics and &lt;em&gt;kawaii&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;The possibility that content distributors might experiment with DRM-free content
if the platform in question offers DRM&amp;rsquo;d playback capabilities is, at best,
a laughable fallacy. Netflix did not succeed because of DRM on its app (or lack
thereof). They
succeeded, because they managed to provide a service that is good enough for
people to prefer forking out the monthly fee rather than trying to find out
which domain The Pirate Bay is using this week.&lt;/p&gt;

&lt;p&gt;Like Torvalds once said, &amp;ldquo;the user doesn&amp;rsquo;t care&amp;rdquo;. Aunt Sally does not know what
DRM is, and if her iPad doesn&amp;rsquo;t stream the last episode of Gilmore Girls,
chances are &amp;ldquo;what is DRM&amp;rdquo; is not what she&amp;rsquo;s going to be googling (if anything
at all; she&amp;rsquo;ll probably just call her niece to figure out the problem for her).&lt;/p&gt;

&lt;p&gt;Even for technologically inclined folk such as yours truly, dealing with the
hassle of misbehaving plugins when in reality I&amp;rsquo;m more in the mood for House of
Cards does not have good chances of being a pleasant experience. On a
personal note, the last time I tried to watch Netflix on an actual web browser
the experiment failed miserably, which further confirmed my firm belief that,
at the prices gadgets are sold these days, it&amp;rsquo;s actually better to relegate all
the binary blob ridden activities to that one &amp;ldquo;impure&amp;rdquo; device that you keep
specifically for this purpose.&lt;/p&gt;

&lt;p&gt;DRM blobs do not matter for the web&amp;rsquo;s relevance, period. But they do matter
from a security and legal perspective, as clearly pointed out by BoingBoing
(in the link above, regarding Google Chrome):&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Because of laws like section 1201 of the US Digital Millennium Copyright Act
(and Canada&amp;rsquo;s Bill C11, and EU implementations of Article 6 of the EUCD),
browsers that have DRM in them are risky for security researchers to audit.
These laws provide both criminal and civil penalties for those who tamper
with DRM, even for legal, legitimate purposes, and courts and companies have
interpreted this to mean that companies can punish security researchers who
reveal defects in their products.
Dozens of W3C members &amp;ndash; and hundreds of security professionals &amp;ndash; have asked
the W3C to amend its policies so that its members can&amp;rsquo;t use EME to silence
security researchers and whistleblowers who want to warn web users that they
are in danger from security vulnerabilities in browsers.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In other words, if you want to be a good consumer and binge on the latest
offerings from your faithful content provider, you must install this opaque
piece of code that you are not allowed to check for correct behavior.&lt;/p&gt;

&lt;p&gt;Here&amp;rsquo;s a fun fact. All DRM is breakable, the old analog way. Because, you know,
eyes are not digital. DRM is based on the assumption that, from the perspective
of the content provider, your device is more trustworthy than you are. Which,
if you think about it, is fundamentally idiotic at all levels.&lt;/p&gt;

&lt;p&gt;So no. Thank you. Keep your blobs out of my browser. It&amp;rsquo;s fine. Especially,
after knowing &lt;a href=&#34;https://13brane.net/rants/though-week-for-the-tubes-ii&#34;&gt;this&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Warming up hyperdrives. Unfolding branes.</title>
      <link>https://13brane.net/rants/warming-unfolding/</link>
      <pubDate>Sat, 28 Jan 2017 16:40:41 -0500</pubDate>
      
      <guid>https://13brane.net/rants/warming-unfolding/</guid>
      <description>&lt;p&gt;The branes have been busy. Very busy.&lt;/p&gt;

&lt;p&gt;They twisted, turned, collided, melded, unmelded, worm-holed, and folded in
pretty much every possible combination.&lt;/p&gt;

&lt;p&gt;The hyperdrives are nearly ready to activate.&lt;/p&gt;

&lt;p&gt;And best of all: the rant canon is charged and armed, ready to fire rage
quantum in all its 13-dimensional prowess.&lt;/p&gt;

&lt;p&gt;Brace for impact.&lt;/p&gt;
</description>
    </item>
    
  </channel>
</rss>
