<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>kmarekspartz</title>
    <link>https://kmarekspartz.writeas.com/</link>
    <description>*Expanding our capacity to respond to unforeseen changes*</description>
    <pubDate>Fri, 29 May 2026 22:28:32 +0000</pubDate>
    <image>
      <url>https://i.snap.as/FSRdToME.jpg</url>
      <title>kmarekspartz</title>
      <link>https://kmarekspartz.writeas.com/</link>
    </image>
    <item>
      <title>A nonary calendar.</title>
      <link>https://kmarekspartz.writeas.com/a-nonary-calendar?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[Upon observing that nine cubed is off by one from the number of days in two years, a calendar system emerged.&#xA;&#xA;---&#xA;&#xA;There are 9 nonths in a biennium, with 9 neeks in a nonth, and 9 days in a neek. There is a biennial holiday between bienniums. Every other biennium holiday is two days.&#xA;&#xA;The first day of the biennium corresponds with March 1st on the Gregorian calendar. The biennial holiday occurs on even number years and is equivalent to February 28th (or February 28th and 29th on Gregorian leap years).&#xA;&#xA;The biennium is expressed in base 9 as well, so the current (at time of writing) biennium would be:&#xA;&#xA;\\(\lfloor2025 \div 2\rfloor = 1012 = 13449\\)&#xA;&#xA;I wrote this on 30₉th (27₁₀)th day of the 5th nonth, on the 3rd neekend.&#xA;&#xA;Handy conversions:&#xA;&#xA;3 neeks (27 days) is approximately a lunisolar month.&#xA;1 nonth is approximately a quarter, or a season.&#xA;&#xA;Representing a nonary calendar on a page isn&#39;t too different from a 9 by 9 Sudoku grid, which can be used to represent the neeks in a biennium, or the days in a nonth. This also means scheduling exclusive recurring tasks maps to a Sudoku puzzle. For example:&#xA;&#xA;  We have 9 tasks to do this nonth. We must do each task once per neek, but never on the same neekday as another neek. We also can&#39;t do the task during the same third of the neek as the other neeks in our third of the nonth.&#xA;&#xA;The closest existing calendars to this system that I&#39;m aware of are the Mayan and French Revolutionary calendars, if you want comparisons, though neither were taken to the nines.]]&gt;</description>
      <content:encoded><![CDATA[<p><em>Upon observing that nine cubed is off by one from the number of days in two years, a calendar system emerged.</em></p>

<hr/>

<p>There are 9 nonths in a biennium, with 9 neeks in a nonth, and 9 days in a neek. There is a biennial holiday between bienniums. Every other biennium holiday is two days.</p>

<p>The first day of the biennium corresponds with March 1st on the Gregorian calendar. The biennial holiday occurs on even number years and is equivalent to February 28th (or February 28th and 29th on Gregorian leap years).</p>

<p>The biennium is expressed in base 9 as well, so the current (at time of writing) biennium would be:</p>

<p>\(\lfloor2025 \div 2\rfloor = 1012 = 1344_9\)</p>

<p>I wrote this on 30₉th (27₁₀)th day of the 5th nonth, on the 3rd neekend.</p>

<p>Handy conversions:</p>
<ul><li>3 neeks (27 days) is approximately a lunisolar month.</li>
<li>1 nonth is approximately a quarter, or a season.</li></ul>

<p>Representing a nonary calendar on a page isn&#39;t too different from a 9 by 9 Sudoku grid, which can be used to represent the neeks in a biennium, or the days in a nonth. This also means scheduling exclusive recurring tasks maps to a Sudoku puzzle. For example:</p>

<blockquote><p>We have 9 tasks to do this nonth. We must do each task once per neek, but never on the same neekday as another neek. We also can&#39;t do the task during the same third of the neek as the other neeks in our third of the nonth.</p></blockquote>

<p>The closest existing calendars to this system that I&#39;m aware of are the <a href="https://en.wikipedia.org/wiki/Maya_calendar">Mayan</a> and <a href="https://en.wikipedia.org/wiki/French_Republican_calendar">French Revolutionary</a> calendars, if you want comparisons, though neither were taken to the nines.</p>
]]></content:encoded>
      <guid>https://kmarekspartz.writeas.com/a-nonary-calendar</guid>
      <pubDate>Mon, 17 Feb 2025 02:56:54 +0000</pubDate>
    </item>
    <item>
      <title>Decisions and the long term</title>
      <link>https://kmarekspartz.writeas.com/decisions-and-the-long-term?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[  Marginal maintenance costs are much more important than fixed initial costs when making business decisions&#xA;&#xA;When making business decisions, people often use initial or fixed costs to justify their decision. While being difficult to estimate, they still are much easier to estimate than maintenance and marginal costs. However, in the long term, maintenance and marginal costs will outweigh initial and fixed costs, so careful attention must be paid to marginal maintenance costs.&#xA;&#xA;Long term costs increase for marginal or maintenance costs, and increase significantly for marginal maintenance costs.&#xA;&#xA;Let&#39;s consider each combination. While a given cost isn&#39;t categorically in one quadrant, these dimensions can be used to conceptualize relative costs of alternatives under consideration. &#xA;&#xA;Fixed initial costs&#xA;&#xA;These are one time costs that are always necessary to take a given path, even in an ideal world.&#xA;&#xA;Marginal initial costs&#xA;&#xA;These are inefficiencies in implementing a decision that are included each time you make similar decisions. Bureaucracy, redundant efforts, and technical debt are three examples.&#xA;&#xA;Fixed maintenance costs&#xA;&#xA;These are the base recurring costs that you must incur as a consequence of your decision. Flat membership or licensing fees are a good example.&#xA;&#xA;Marginal maintenance costs&#xA;&#xA;These are recurring costs that grow proportionally to the number of customers are affected the outcome of your decision. Hiring people or paying for more computers are examples of this. Minimizing these costs has more benefit than reducing the other three types because they are recurring and growing.&#xA;&#xA;---&#xA;&#xA;See also: The Equation of Software Design]]&gt;</description>
      <content:encoded><![CDATA[<blockquote><p>Marginal maintenance costs are much more important than fixed initial costs when making business decisions</p></blockquote>

<p>When making business decisions, people often use initial or fixed costs to justify their decision. While being difficult to estimate, they still are much easier to estimate than maintenance and marginal costs. However, in the long term, maintenance and marginal costs will outweigh initial and fixed costs, so careful attention must be paid to marginal maintenance costs.</p>

<p><img src="https://i.snap.as/V6tnxP6Z.png" alt="Long term costs increase for marginal or maintenance costs, and increase significantly for marginal maintenance costs."/></p>

<p>Let&#39;s consider each combination. While a given cost isn&#39;t categorically in one quadrant, these dimensions can be used to conceptualize relative costs of alternatives under consideration.</p>

<h3 id="fixed-initial-costs" id="fixed-initial-costs">Fixed initial costs</h3>

<p>These are one time costs that are always necessary to take a given path, even in an ideal world.</p>

<h3 id="marginal-initial-costs" id="marginal-initial-costs">Marginal initial costs</h3>

<p>These are inefficiencies in implementing a decision that are included each time you make similar decisions. Bureaucracy, redundant efforts, and technical debt are three examples.</p>

<h3 id="fixed-maintenance-costs" id="fixed-maintenance-costs">Fixed maintenance costs</h3>

<p>These are the base recurring costs that you must incur as a consequence of your decision. Flat membership or licensing fees are a good example.</p>

<h3 id="marginal-maintenance-costs" id="marginal-maintenance-costs">Marginal maintenance costs</h3>

<p>These are recurring costs that grow proportionally to the number of customers are affected the outcome of your decision. Hiring people or paying for more computers are examples of this. Minimizing these costs has more benefit than reducing the other three types because they are recurring and growing.</p>

<hr/>

<p>See also: <a href="http://www.codesimplicity.com/post/the-equation-of-software-design/">The Equation of Software Design</a></p>
]]></content:encoded>
      <guid>https://kmarekspartz.writeas.com/decisions-and-the-long-term</guid>
      <pubDate>Sat, 05 Dec 2015 06:00:00 +0000</pubDate>
    </item>
    <item>
      <title>Themes as Goals</title>
      <link>https://kmarekspartz.writeas.com/themes-as-goals?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[  Use themes to clarify your goals&#xA;&#xA;When defining goals, I&#39;ve found themes to be more effective than particular&#xA;achievements. Themes give clarity of purpose and direction, even when the day to&#xA;day tactical priorities change. Does my plan for the day fit into my theme?&#xA;&#xA;On the other hand, measuring progress against a theme is difficult. Instead of&#xA;measuring directly, we have to use proxies. Choose proxies carefully. Be&#xA;comfortable changing your proxy measurements even when you maintain the theme.&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<blockquote><p>Use themes to clarify your goals</p></blockquote>

<p>When defining goals, I&#39;ve found themes to be more effective than particular
achievements. Themes give clarity of purpose and direction, even when the day to
day tactical priorities change. Does my plan for the day fit into my theme?</p>

<p>On the other hand, measuring progress against a theme is difficult. Instead of
measuring directly, we have to use proxies. Choose proxies carefully. Be
comfortable changing your proxy measurements even when you maintain the theme.</p>
]]></content:encoded>
      <guid>https://kmarekspartz.writeas.com/themes-as-goals</guid>
      <pubDate>Wed, 25 Nov 2015 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>Moving to monorepos without losing history</title>
      <link>https://kmarekspartz.writeas.com/moving-to-monorepos-without-losing-history?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[  No need to start from scratch; you can merge your repos and preserve history.&#xA;---&#xA;&#xA;If you&#39;d like to merge two (or more) git repositories together and preserve&#xA;the commit histories of both, here&#39;s the script for you:&#xA;&#xA;~ bash&#xA;cd some-repo&#xA;&#xA;git remote add other-repo git@other-repo.com:other-repo/other-repo.git&#xA;git fetch other-repo&#xA;git checkout other-repo/master&#xA;&#xA;git checkout -b merge-other-repo&#xA;mkdir other-repo&#xA;&#xA;for f in *; do&#xA;  git mv $f other-repo&#xA;done&#xA;&#xA;If you&#39;re making a merge request:&#xA;&#xA;git merge master --allow-unrelated-histories&#xA;&#xA;git push origin merge-other-repo&#xA;&#xA;Then make a merge request&#xA;&#xA;If you&#39;re pushing directly to master:&#xA;&#xA;git checkout master&#xA;&#xA;git merge merge-other-repo&#xA;&#xA;git push origin master&#xA;~&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<blockquote><p>No need to start from scratch; you can merge your repos and preserve history.</p>

<hr/>
</blockquote>

<p>If you&#39;d like to merge two (or more) git repositories together and preserve
the commit histories of both, here&#39;s the script for you:</p>

<pre><code class="language-bash">cd some-repo

git remote add other-repo git@other-repo.com:other-repo/other-repo.git
git fetch other-repo
git checkout other-repo/master

git checkout -b merge-other-repo
mkdir other-repo

for f in *; do
  git mv $f other-repo
done

# If you&#39;re making a merge request:

git merge master --allow-unrelated-histories

git push origin merge-other-repo

# Then make a merge request

# If you&#39;re pushing directly to master:

git checkout master

git merge merge-other-repo

git push origin master
</code></pre>
]]></content:encoded>
      <guid>https://kmarekspartz.writeas.com/moving-to-monorepos-without-losing-history</guid>
      <pubDate>Tue, 17 Nov 2015 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>Concurrent implementation of the Daytime Protocol in Rust</title>
      <link>https://kmarekspartz.writeas.com/concurrent-implementation-of-the-daytime-protocol-in-rust?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[  A concurrent implementation Daytime protocol in Rust&#xA;---&#xA;&#xA;When learning a language, I rewrite small programs I&#39;ve previously written to&#xA;jumpstart my learning. Implementing a concurrent&#xA;Daytime server has proved&#xA;particularly useful because it uses both sockets and threads. If a language has&#xA;good socket and threading libraries, it is likely a good language.&#xA;&#xA;Previously, I&#xA;demonstrated&#xA;a Haskell implementation. Here&#39;s an example in Rust:&#xA;&#xA;extern crate time;&#xA;&#xA;use std::time::Duration;&#xA;use std::io::Write;&#xA;use std::net::{TcpListener, TcpStream};&#xA;use std::thread;&#xA;&#xA;fn handleclient(mut stream: TcpStream) {&#xA;    let date = time::strftime(&#34;%F %T\n&#34;, &amp;time::nowutc()).unwrap().tostring();&#xA;    let  = stream.write(date.asbytes());&#xA;}&#xA;&#xA;fn main() {&#xA;    let listener = TcpListener::bind(&#34;127.0.0.1:13&#34;).unwrap();&#xA;&#xA;    for stream in listener.incoming() {&#xA;        match stream {&#xA;            Ok(stream) =  {&#xA;                thread::spawn(move || {&#xA;                    // connection succeeded&#xA;                    thread::sleep(Duration::new(1,0));&#xA;                    handleclient(stream)&#xA;                });&#xA;            }&#xA;            Err() =  { / connection failed / },&#xA;        }&#xA;    }&#xA;&#xA;    drop(listener);&#xA;}&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<blockquote><p>A concurrent implementation Daytime protocol in Rust</p>

<hr/>
</blockquote>

<p>When learning a language, I rewrite small programs I&#39;ve previously written to
jumpstart my learning. Implementing a concurrent
<a href="https://en.wikipedia.org/wiki/Daytime_Protocol">Daytime</a> server has proved
particularly useful because it uses both sockets and threads. If a language has
good socket and threading libraries, it is likely a good language.</p>

<p>Previously, I
<a href="http://kyle.marek-spartz.org/posts/2014-08-26-concurrent-implementation-of-the-daytime-protocol-in-haskell.html">demonstrated</a>
a Haskell implementation. Here&#39;s an example in Rust:</p>

<pre><code class="language-rust">extern crate time;

use std::time::Duration;
use std::io::Write;
use std::net::{TcpListener, TcpStream};
use std::thread;

fn handle_client(mut stream: TcpStream) {
    let date = time::strftime(&#34;%F %T\n&#34;, &amp;time::now_utc()).unwrap().to_string();
    let _ = stream.write(date.as_bytes());
}

fn main() {
    let listener = TcpListener::bind(&#34;127.0.0.1:13&#34;).unwrap();

    for stream in listener.incoming() {
        match stream {
            Ok(stream) =&gt;  {
                thread::spawn(move || {
                    // connection succeeded
                    thread::sleep(Duration::new(1,0));
                    handle_client(stream)
                });
            }
            Err(_) =&gt; { /* connection failed */ },
        }
    }

    drop(listener);
}
</code></pre>
]]></content:encoded>
      <guid>https://kmarekspartz.writeas.com/concurrent-implementation-of-the-daytime-protocol-in-rust</guid>
      <pubDate>Mon, 16 Nov 2015 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>Eventual consistency for SQL: Normalization</title>
      <link>https://kmarekspartz.writeas.com/eventual-consistency-for-sql-normalization?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[  Using a log-structured schema, we can merge SQL databases to achieve eventual consistency.&#xA;---&#xA;&#xA;Previously, I&#xA;introduced&#xA;eventual consistency for SQL. This post illustrates how to normalize an&#xA;eventually consistent SQL database.&#xA;&#xA;To demonstrate how to normalize for eventual consistency, let&#39;s design a&#xA;database for a Twitter clone, consisting of users and statuses. A traditional&#xA;schema for a Twitter looks like:&#xA;&#xA;~ SQL&#xA;CREATE TABLE Users (&#xA;  username VARCHAR(255) PRIMARY KEY,&#xA;  email VARCHAR(255),&#xA;  phone VARCHAR(255),&#xA;  location VARCHAR(255),&#xA;  confirmed BOOLEAN NOT NULL,&#xA;  salt VARCHAR(255) NOT NULL,&#xA;  hashedpassword VARCHAR(255) NOT NULL&#xA;);&#xA;&#xA;CREATE TABLE Statuses (&#xA;  content VARCHAR(140) NOT NULL,&#xA;  createdat DATE DEFAULT ( SYSDATE ) NOT NULL,&#xA;  username VARCHAR(255) REFERENCES Users (username) NOT NULL,&#xA;) PRIMARY KEY (content, createdat, userid);&#xA;&#xA;CREATE TABLE Follows (&#xA;  followerusername VARCHAR(255) REFERENCES Users (username) NOT NULL,&#xA;  followeeusername VARCHAR(255) REFERENCES Users (username) NOT NULL&#xA;) PRIMARY KEY (followerusername, followeeusername);&#xA;~&#xA;&#xA;The first step in normalizing for eventual consistency is to identify state&#xA;changes in your data. For example, a user becomes confirmed after clicking a&#xA;link in an email or text message. Under the schema above, the following&#xA;UPDATE statement would get executed:&#xA;&#xA;~ SQL&#xA;UPDATE Users&#xA;SET confirmed = true&#xA;WHERE username = &#39;kmarekspartz&#39;;&#xA;~&#xA;&#xA;However, since we&#39;re avoiding UPDATE, this will not work. Instead, let&#39;s&#xA;normalize this mutation out of our database.&#xA;&#xA;: I&#39;m going to assume offline migrations for simplicity, but these&#xA;migrations can be achieved in a zero-downtime environment, too. You would create&#xA;both places for the data reside, deploy a version of the application to read&#xA;from both, deploy a version of the application to write to both, run a backfill&#xA;migration (like in the example), then deploy a version which only reads and&#xA;writes the new place, then drop the old place. Fun!&#xA;&#xA;~ SQL&#xA;CREATE TABLE Confirmations (&#xA;  username VARCHAR(255) REFERENCES Users (username) NOT NULL&#xA;);&#xA;&#xA;INSERT INTO Confirmations&#xA;SELECT username&#xA;FROM Users&#xA;WHERE confirmed = true;&#xA;&#xA;ALTER TABLE Users&#xA;DROP COLUMN confirmed;&#xA;&#xA;INSERT INTO Confirmations VALUES (&#39;kmarekspartz&#39;);&#xA;&#xA;SELECT Users.*, ISNULL(Confirmations.username) AS confirmed&#xA;FROM Users&#xA;LEFT OUTER JOIN Confirmations&#xA;ON Users.username = Confirmations.username;&#xA;~&#xA;&#xA;Applying this normalization to the rest of the schema would lead to a new&#xA;schema:&#xA;&#xA;~ SQL&#xA;CREATE TABLE Users (&#xA;  username VARCHAR(255) PRIMARY KEY,&#xA;  salt VARCHAR(255) NOT NULL,&#xA;  hashedpassword VARCHAR(255) NOT NULL&#xA;);&#xA;&#xA;CREATE TABLE Confirmations (&#xA;  username VARCHAR(255) REFERENCES Users (username) NOT NULL&#xA;);&#xA;&#xA;CREATE TABLE Emails (&#xA;  email VARCHAR(255) PRIMARY KEY&#xA;);&#xA;&#xA;CREATE TABLE UserEmails (&#xA;  username VARCHAR(255) REFERENCES Users (username) NOT NULL,&#xA;  email VARCHAR(255) REFERENCES Emails (email) NOT NULL&#xA;) PRIMARY KEY (username, email);&#xA;&#xA;CREATE TABLE Phones (&#xA;  phone VARCHAR(255) PRIMARY KEY&#xA;);&#xA;&#xA;CREATE TABLE UserPhones (&#xA;  username VARCHAR(255) REFERENCES Users (username) NOT NULL,&#xA;  phone VARCHAR(255) REFERENCES Phones (phone) NOT NULL&#xA;) PRIMARY KEY (username, phone);&#xA;&#xA;CREATE TABLE Locations (&#xA;  location VARCHAR(255) PRIMARY KEY&#xA;);&#xA;&#xA;CREATE TABLE UserLocations (&#xA;  userlocationid PRIMARY KEY AUTOINCREMENT&#xA;  username VARCHAR(255) REFERENCES Users (username) NOT NULL,&#xA;  location VARCHAR(255) REFERENCES Locations (location) NOT NULL&#xA;);&#xA;&#xA;CREATE TABLE UserLocationDeletions (&#xA;  userlocationid REFERENCES UserLocations (userlocationid) NOT NULL&#xA;);&#xA;&#xA;CREATE TABLE Statuses (&#xA;  content VARCHAR(140) NOT NULL,&#xA;  createdat DATE DEFAULT ( SYSDATE ) NOT NULL,&#xA;  username VARCHAR(255) REFERENCES Users (username) NOT NULL,&#xA;) PRIMARY KEY (content, createdat, userid);&#xA;&#xA;CREATE TABLE Follows (&#xA;  followid PRIMARY KEY AUTOINCREMENT,&#xA;  followerusername VARCHAR(255) REFERENCES Users (username) NOT NULL,&#xA;  followeeusername VARCHAR(255) REFERENCES Users (username) NOT NULL&#xA;);&#xA;&#xA;CREATE TABLE FollowDeletions (&#xA;  followid REFERENCES Follows (followid) NOT NULL&#xA;);&#xA;~&#xA;&#xA;I&#39;ve turned most properties into many-to-many relationships, and added deletion&#xA;tables for the join tables. This is because many-to-many relationships are&#xA;easier to merge than one-to-one. With a many-to-many, you can use UNION as&#xA;your merge strategy. With one-to-one, there&#39;s not a deterministic way to choose&#xA;a winner. This will result in temporary inconsistencies, but if you have each&#xA;user interact with a particular host or shard, you can minimize those&#xA;inconsistencies. In a mobile environment, the user is interacting with their&#xA;phone, and we can guarantee that their phone is in a consistent state at any&#xA;given time. In a server environment, we can route that user&#39;s interactions to a&#xA;particular host, failing over to an in sync replica if that host is down.&#xA;&#xA;One thing that doesn&#39;t work well with a many-to-many relationship is passwords.&#xA;I left it as one-to-one, but passwords aren&#39;t needed anymore, particularly when&#xA;there is an email address or a phone number available. Instead of asking a user&#xA;for a password, we can send them a link with a token to sign in. This is&#xA;one-factor authentication, but uses what is commonly a second factor in&#xA;two-factor authentication. Removing passwords from this schema would make&#xA;eventual consistency possible.&#xA;&#xA;---&#xA;&#xA;I like to call this method of normalization &#39;log normalization&#39; but that gets&#xA;confusing. It is too&#xA;bad we have unique constraints on technical terms. If there&#39;s a better name for&#xA;this, let me know!&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<blockquote><p>Using a log-structured schema, we can merge SQL databases to achieve eventual consistency.</p>

<hr/>
</blockquote>

<p><em>Previously, I
<a href="http://kyle.marek-spartz.org/posts/2015-09-08-eventual-consistency-for-sql-databases.html">introduced</a>
eventual consistency for SQL. This post illustrates how to normalize an
eventually consistent SQL database.</em></p>

<p>To demonstrate how to normalize for eventual consistency, let&#39;s design a
database for a Twitter clone, consisting of users and statuses. A traditional
schema for a Twitter looks like:</p>

<pre><code class="language-SQL">CREATE TABLE Users (
  username VARCHAR(255) PRIMARY KEY,
  email VARCHAR(255),
  phone VARCHAR(255),
  location VARCHAR(255),
  confirmed BOOLEAN NOT NULL,
  salt VARCHAR(255) NOT NULL,
  hashed_password VARCHAR(255) NOT NULL
);

CREATE TABLE Statuses (
  content VARCHAR(140) NOT NULL,
  created_at DATE DEFAULT ( SYSDATE ) NOT NULL,
  username VARCHAR(255) REFERENCES Users (username) NOT NULL,
) PRIMARY KEY (content, created_at, user_id);

CREATE TABLE Follows (
  follower_username VARCHAR(255) REFERENCES Users (username) NOT NULL,
  followee_username VARCHAR(255) REFERENCES Users (username) NOT NULL
) PRIMARY KEY (follower_username, followee_username);
</code></pre>

<p>The first step in normalizing for eventual consistency is to identify state
changes in your data. For example, a user becomes confirmed after clicking a
link in an email or text message. Under the schema above, the following
<code>UPDATE</code> statement would get executed:</p>

<pre><code class="language-SQL">UPDATE Users
SET confirmed = true
WHERE username = &#39;kmarekspartz&#39;;
</code></pre>

<p>However, since we&#39;re avoiding <code>UPDATE</code>, this will not work. Instead, let&#39;s
normalize this mutation out of our database.[^1]</p>

<p>[^1]: I&#39;m going to assume offline migrations for simplicity, but these
migrations can be achieved in a zero-downtime environment, too. You would create
both places for the data reside, deploy a version of the application to read
from both, deploy a version of the application to write to both, run a backfill
migration (like in the example), then deploy a version which only reads and
writes the new place, then drop the old place. Fun!</p>

<pre><code class="language-SQL">CREATE TABLE Confirmations (
  username VARCHAR(255) REFERENCES Users (username) NOT NULL
);

INSERT INTO Confirmations
SELECT username
FROM Users
WHERE confirmed = true;

ALTER TABLE Users
DROP COLUMN confirmed;

INSERT INTO Confirmations VALUES (&#39;kmarekspartz&#39;);

SELECT Users.*, IS_NULL(Confirmations.username) AS confirmed
FROM Users
LEFT OUTER JOIN Confirmations
ON Users.username = Confirmations.username;
</code></pre>

<p>Applying this normalization to the rest of the schema would lead to a new
schema:</p>

<pre><code class="language-SQL">CREATE TABLE Users (
  username VARCHAR(255) PRIMARY KEY,
  salt VARCHAR(255) NOT NULL,
  hashed_password VARCHAR(255) NOT NULL
);

CREATE TABLE Confirmations (
  username VARCHAR(255) REFERENCES Users (username) NOT NULL
);

CREATE TABLE Emails (
  email VARCHAR(255) PRIMARY KEY
);

CREATE TABLE UserEmails (
  username VARCHAR(255) REFERENCES Users (username) NOT NULL,
  email VARCHAR(255) REFERENCES Emails (email) NOT NULL
) PRIMARY KEY (username, email);

CREATE TABLE Phones (
  phone VARCHAR(255) PRIMARY KEY
);

CREATE TABLE UserPhones (
  username VARCHAR(255) REFERENCES Users (username) NOT NULL,
  phone VARCHAR(255) REFERENCES Phones (phone) NOT NULL
) PRIMARY KEY (username, phone);

CREATE TABLE Locations (
  location VARCHAR(255) PRIMARY KEY
);

CREATE TABLE UserLocations (
  user_location_id PRIMARY KEY AUTOINCREMENT
  username VARCHAR(255) REFERENCES Users (username) NOT NULL,
  location VARCHAR(255) REFERENCES Locations (location) NOT NULL
);

CREATE TABLE UserLocationDeletions (
  user_location_id REFERENCES UserLocations (user_location_id) NOT NULL
);

CREATE TABLE Statuses (
  content VARCHAR(140) NOT NULL,
  created_at DATE DEFAULT ( SYSDATE ) NOT NULL,
  username VARCHAR(255) REFERENCES Users (username) NOT NULL,
) PRIMARY KEY (content, created_at, user_id);

CREATE TABLE Follows (
  follow_id PRIMARY KEY AUTOINCREMENT,
  follower_username VARCHAR(255) REFERENCES Users (username) NOT NULL,
  followee_username VARCHAR(255) REFERENCES Users (username) NOT NULL
);

CREATE TABLE FollowDeletions (
  follow_id REFERENCES Follows (follow_id) NOT NULL
);
</code></pre>

<p>I&#39;ve turned most properties into many-to-many relationships, and added deletion
tables for the join tables. This is because many-to-many relationships are
easier to merge than one-to-one. With a many-to-many, you can use <code>UNION</code> as
your merge strategy. With one-to-one, there&#39;s not a deterministic way to choose
a winner. This will result in temporary inconsistencies, but if you have each
user interact with a particular host or shard, you can minimize those
inconsistencies. In a mobile environment, the user is interacting with their
phone, and we can guarantee that their phone is in a consistent state at any
given time. In a server environment, we can route that user&#39;s interactions to a
particular host, failing over to an in sync replica if that host is down.</p>

<p>One thing that doesn&#39;t work well with a many-to-many relationship is passwords.
I left it as one-to-one, but passwords aren&#39;t needed anymore, particularly when
there is an email address or a phone number available. Instead of asking a user
for a password, we can send them a link with a token to sign in. This is
one-factor authentication, but uses what is commonly a second factor in
two-factor authentication. Removing passwords from this schema would make
eventual consistency possible.</p>

<hr/>

<p>I like to call this method of normalization &#39;log normalization&#39; but that gets
<a href="https://en.wikipedia.org/wiki/Log-normal_distribution">confusing</a>. It is too
bad we have unique constraints on technical terms. If there&#39;s a better name for
this, let <a href="mailto:kyle.marek.spartz@gmail.com">me</a> know!</p>
]]></content:encoded>
      <guid>https://kmarekspartz.writeas.com/eventual-consistency-for-sql-normalization</guid>
      <pubDate>Wed, 14 Oct 2015 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>Eventual consistency for SQL databases</title>
      <link>https://kmarekspartz.writeas.com/eventual-consistency-for-sql-databases?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[  Using a log-structured schema, we can merge SQL databases to achieve eventual consistency.&#xA;---&#xA;&#xA;Eventual consistency is&#xA;typically thought of as a property of certain NoSQL databases.  However, SQL&#xA;databases can achieve eventual consistency with adequate planning.&#xA;&#xA;Eventual consistency is particularly useful for horizontally scaling web&#xA;services, as each node does not need the full, up to date picture. Another use&#xA;case is synchronizing mobile applications with intermittent network&#xA;connectivity. In both cases, partitioning or&#xA;sharding&#xA;allows each user or client to maintain a consistent view.&#xA;&#xA;A data structure is considered eventually consistent if two instances can reach&#xA;a consistent state given the same unordered set of state changes. Two databases&#xA;are eventually consistent if all actions taken in one propagate to the other.&#xA;&#xA;Strong eventual consistency can be achieved if state changes are&#xA;commutative,&#xA;associative, and&#xA;idempotent.&#xA;&#xA;State changes are commutative if swapping two operations yields the same state.&#xA;For example, these two operations can apply in either order to yield a&#xA;logically equivalent table:&#xA;&#xA;~ SQL&#xA;INSERT INTO sometable (somecolumn) VALUES (1);&#xA;INSERT INTO sometable (somecolumn) VALUES (2);&#xA;~&#xA;&#xA;Similarly, state changes are associative if three operations can be paired&#xA;either way yielding the same state. For example, three databases each with one&#xA;of the following operations can be merged as (1 + 2) + 3 or 1 + (2 + 3) to yield&#xA;a logically equivalent table:&#xA;&#xA;~ SQL&#xA;INSERT INTO sometable (somecolumn) VALUES (1);&#xA;INSERT INTO sometable (somecolumn) VALUES (2);&#xA;INSERT INTO sometable (somecolumn) VALUES (3);&#xA;~&#xA;&#xA;Not all SQL DML can&#xA;be commutative or associative:&#xA;&#xA;~ SQL&#xA;UPDATE sometable SET a = 1;&#xA;UPDATE sometable SET a = 2;&#xA;UPDATE sometable SET a = 3;&#xA;~&#xA;&#xA;Depending on the order of these operations, the resulting database would be in&#xA;different states.&#xA;&#xA;DELETEs also cause problems. Given two databases, where one has ran a deletion&#xA;and one has not, merging them would re-insert the deleted row in the database&#xA;with the deletion:&#xA;&#xA;~ SQL&#xA;DELETE FROM sometable WHERE somecolumn = 4;&#xA;~&#xA;&#xA;We can limit DML to SELECTs and INSERTs to avoid using other synchronization&#xA;methods. Avoiding updates and deletes provides&#xA;immutability, which guarantees&#xA;a row will not change or disappear from our databases.&#xA;&#xA;By staying INSERT-only, we treat our database as a [persistent data&#xA;structure](https://en.wikipedia.org/wiki/Persistentdatastructure), or an&#xA;append-only commit log.&#xA;&#xA;Immutability and persistence helps with eventual consistency, but they are not&#xA;sufficient. We also need idempotence. State changes are idempotent if repeatedly&#xA;applying the same state change yields the same state. Our previous example,&#xA;INSERT INTO sometable (somecolumn) VALUES (1) is not idempotent, unless we&#xA;de-duplicate rows at query time:&#xA;&#xA;~ SQL&#xA;SELECT DISTINCT somecolumn&#xA;FROM sometable;&#xA;~&#xA;&#xA;Another way to achieve idempotence is to use a unique constraint to prevent&#xA;duplicates from being inserted and ignore unique constraint violations upon&#xA;insertion. We can also manually check for duplicates during an insert:&#xA;&#xA;~ SQL&#xA;INSERT INTO sometable (somecolumn)&#xA;SELECT 4&#xA;WHERE NOT EXISTS (&#xA;  SELECT 1&#xA;  FROM sometable&#xA;  WHERE somecolumn = 4&#xA;);&#xA;~&#xA;&#xA;How can we delete an item from our database without using SQL DELETE?&#xA;Tombstones provide&#xA;our answer. Instead of DELETEing the row, we can create a marker in another&#xA;table that says an object is deleted.&#xA;&#xA;~ SQL&#xA;INSERT INTO sometabledeletions (sometableid)&#xA;VALUES (123456);&#xA;~&#xA;&#xA;Queries for undeleted rows then become:&#xA;&#xA;~ SQL&#xA;SELECT sometable.*&#xA;FROM sometable&#xA;WHERE id NOT IN (&#xA;  SELECT sometableid&#xA;  FROM sometabledeletions&#xA;);&#xA;~&#xA;&#xA;If we want to support deletion and re-adding of the same value, we cannot use a&#xA;unique constraint for idempotence since the unique constraint would prevent the&#xA;addition of the new row. Instead, either de-duplicate at query time using&#xA;DISTINCT or prevent duplicates from getting inserted without using a unique&#xA;constraint:&#xA;&#xA;~ SQL&#xA;INSERT INTO sometable (somecolumn)&#xA;SELECT 4&#xA;WHERE NOT EXISTS (&#xA;  SELECT 1&#xA;  FROM sometable&#xA;  WHERE somecolumn = 4&#xA;  AND id NOT IN (&#xA;    SELECT sometableid&#xA;    FROM sometabledeletions&#xA;  )&#xA;);&#xA;~&#xA;&#xA;At this point it looks like we&#39;ll need to&#xA;normalize our database,&#xA;or structure our data in a particular way in order to satisfy these properties.&#xA;In my next blog post, I&#39;ll demonstrate how to normalize a database to&#xA;achieve eventual consistency.&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<blockquote><p>Using a log-structured schema, we can merge SQL databases to achieve eventual consistency.</p>

<hr/>
</blockquote>

<p><a href="https://en.wikipedia.org/wiki/Eventual_consistency">Eventual consistency</a> is
typically thought of as a property of certain NoSQL databases.  However, SQL
databases can achieve eventual consistency with adequate planning.</p>

<p>Eventual consistency is particularly useful for horizontally scaling web
services, as each node does not need the full, up to date picture. Another use
case is synchronizing mobile applications with intermittent network
connectivity. In both cases, partitioning or
<a href="https://en.wikipedia.org/wiki/Shard_%28database_architecture%29">sharding</a>
allows each user or client to maintain a consistent view.</p>

<p>A data structure is considered eventually consistent if two instances can reach
a consistent state given the same unordered set of state changes. Two databases
are eventually consistent if all actions taken in one propagate to the other.</p>

<p>Strong eventual consistency can be achieved if state changes are
<a href="https://en.wikipedia.org/wiki/Commutative_property">commutative</a>,
<a href="https://en.wikipedia.org/wiki/Associative_property">associative</a>, and
<a href="https://en.wikipedia.org/wiki/Idempotence">idempotent</a>.</p>

<p>State changes are commutative if swapping two operations yields the same state.
For example, these two operations can apply in either order to yield a
logically equivalent table:</p>

<pre><code class="language-SQL">INSERT INTO some_table (some_column) VALUES (1);
INSERT INTO some_table (some_column) VALUES (2);
</code></pre>

<p>Similarly, state changes are associative if three operations can be paired
either way yielding the same state. For example, three databases each with one
of the following operations can be merged as (1 + 2) + 3 or 1 + (2 + 3) to yield
a logically equivalent table:</p>

<pre><code class="language-SQL">INSERT INTO some_table (some_column) VALUES (1);
INSERT INTO some_table (some_column) VALUES (2);
INSERT INTO some_table (some_column) VALUES (3);
</code></pre>

<p>Not all <a href="https://en.wikipedia.org/wiki/Data_manipulation_language">SQL DML</a> can
be commutative or associative:</p>

<pre><code class="language-SQL">UPDATE some_table SET a = 1;
UPDATE some_table SET a = 2;
UPDATE some_table SET a = 3;
</code></pre>

<p>Depending on the order of these operations, the resulting database would be in
different states.</p>

<p><code>DELETE</code>s also cause problems. Given two databases, where one has ran a deletion
and one has not, merging them would re-insert the deleted row in the database
with the deletion:</p>

<pre><code class="language-SQL">DELETE FROM some_table WHERE some_column = 4;
</code></pre>

<p>We can limit DML to <code>SELECT</code>s and <code>INSERT</code>s to avoid using other synchronization
methods. Avoiding updates and deletes provides
<a href="https://en.wikipedia.org/wiki/Immutable_object">immutability</a>, which guarantees
a row will not change or disappear from our databases.</p>

<p>By staying <code>INSERT</code>-only, we treat our database as a <a href="https://en.wikipedia.org/wiki/Persistent_data_structure">persistent data
structure</a>, or an
append-only commit log.</p>

<p>Immutability and persistence helps with eventual consistency, but they are not
sufficient. We also need idempotence. State changes are idempotent if repeatedly
applying the same state change yields the same state. Our previous example,
<code>INSERT INTO some_table (some_column) VALUES (1)</code> is not idempotent, unless we
de-duplicate rows at query time:</p>

<pre><code class="language-SQL">SELECT DISTINCT some_column
FROM some_table;
</code></pre>

<p>Another way to achieve idempotence is to use a unique constraint to prevent
duplicates from being inserted and ignore unique constraint violations upon
insertion. We can also manually check for duplicates during an insert:</p>

<pre><code class="language-SQL">INSERT INTO some_table (some_column)
SELECT 4
WHERE NOT EXISTS (
  SELECT 1
  FROM some_table
  WHERE some_column = 4
);
</code></pre>

<p>How can we delete an item from our database without using SQL <code>DELETE</code>?
<a href="https://en.wikipedia.org/wiki/Tombstone_%28data_store%29">Tombstones</a> provide
our answer. Instead of <code>DELETE</code>ing the row, we can create a marker in another
table that says an object is deleted.</p>

<pre><code class="language-SQL">INSERT INTO some_table_deletions (some_table_id)
VALUES (123456);
</code></pre>

<p>Queries for undeleted rows then become:</p>

<pre><code class="language-SQL">SELECT some_table.*
FROM some_table
WHERE id NOT IN (
  SELECT some_table_id
  FROM some_table_deletions
);
</code></pre>

<p>If we want to support deletion and re-adding of the same value, we cannot use a
unique constraint for idempotence since the unique constraint would prevent the
addition of the new row. Instead, either de-duplicate at query time using
<code>DISTINCT</code> or prevent duplicates from getting inserted without using a unique
constraint:</p>

<pre><code class="language-SQL">INSERT INTO some_table (some_column)
SELECT 4
WHERE NOT EXISTS (
  SELECT 1
  FROM some_table
  WHERE some_column = 4
  AND id NOT IN (
    SELECT some_table_id
    FROM some_table_deletions
  )
);
</code></pre>

<p>At this point it looks like we&#39;ll need to
<a href="https://en.wikipedia.org/wiki/Database_normalization">normalize</a> our database,
or structure our data in a particular way in order to satisfy these properties.
In my next blog post, I&#39;ll demonstrate how to normalize a database to
achieve eventual consistency.</p>
]]></content:encoded>
      <guid>https://kmarekspartz.writeas.com/eventual-consistency-for-sql-databases</guid>
      <pubDate>Tue, 08 Sep 2015 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>cons, car, and cdr need not be primitive</title>
      <link>https://kmarekspartz.writeas.com/cons-car-and-cdr-need-not-be-primitive?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[  An exercise from SICP&#xA;&#xA;A lisp) can be implemented using a small set of primitives from which other lisp features can be derived. The set is not fixed; different lisps use different primitives. cons, car, and cdr are often primitives, but they do not need to be.&#xA;&#xA;Primitive cons, car, and cdr&#xA;&#xA;Typical implementations of cons, car, and cdr use an underlying array representations in their host environment. In a JavaScript host environment, this could look like:&#xA;&#xA;var cons = function (head, tail) {&#xA;  return [head, tail];&#xA;};&#xA;&#xA;var car = function (pair) {&#xA;  return pair[0];&#xA;};&#xA;&#xA;var cdr = function (pair) {&#xA;  return pair[1];&#xA;};&#xA;&#xA;Derived cons, car, and cdr&#xA;&#xA;To implement cons, car, and cdr as derived features, the lisp should only need function definitions and lambdas as features (either derived or primitive).&#xA;&#xA;(define (cons head tail)&#xA;  (lambda (f) (f head tail))&#xA;&#xA;(define (car pair)&#xA;  (pair (lambda (head tail) head)))&#xA;&#xA;(define (cdr pair)&#xA;  (pair (lambda (head tail) tail)))&#xA;&#xA;This could compile down into:&#xA;&#xA;var cons = function (head, tail) {&#xA;  return function (f) {&#xA;    return f(head, tail);&#xA;  };&#xA;};&#xA;&#xA;var car = function (pair) {&#xA;  return pair(&#xA;    function (head, tail) { return head; }&#xA;  );&#xA;};&#xA;&#xA;var cdr = function (pair) {&#xA;  return pair(&#xA;    function (head, tail) { return tail; }&#xA;  );&#xA;};&#xA;&#xA;See also: SICP Exercise 2.4&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<blockquote><p>An exercise from SICP</p></blockquote>

<p>A <a href="https://en.wikipedia.org/wiki/Lisp_(programming_language)">lisp</a> can be implemented using a small set of primitives from which other lisp features can be derived. The set is not fixed; different lisps use different primitives. <code>cons</code>, <code>car</code>, and <code>cdr</code> are often primitives, but they do not need to be.</p>

<h3 id="primitive-cons-car-and-cdr" id="primitive-cons-car-and-cdr">Primitive <code>cons</code>, <code>car</code>, and <code>cdr</code></h3>

<p>Typical implementations of <code>cons</code>, <code>car</code>, and <code>cdr</code> use an underlying array representations in their host environment. In a JavaScript host environment, this could look like:</p>

<pre><code class="language-javascript">var cons = function (head, tail) {
  return [head, tail];
};

var car = function (pair) {
  return pair[0];
};

var cdr = function (pair) {
  return pair[1];
};
</code></pre>

<h3 id="derived-cons-car-and-cdr" id="derived-cons-car-and-cdr">Derived <code>cons</code>, <code>car</code>, and <code>cdr</code></h3>

<p>To implement <code>cons</code>, <code>car</code>, and <code>cdr</code> as derived features, the lisp should only need function definitions and lambdas as features (either derived or primitive).</p>

<pre><code class="language-scheme">(define (cons head tail)
  (lambda (f) (f head tail))

(define (car pair)
  (pair (lambda (head tail) head)))

(define (cdr pair)
  (pair (lambda (head tail) tail)))
</code></pre>

<p>This could compile down into:</p>

<pre><code class="language-javascript">var cons = function (head, tail) {
  return function (f) {
    return f(head, tail);
  };
};

var car = function (pair) {
  return pair(
    function (head, tail) { return head; }
  );
};

var cdr = function (pair) {
  return pair(
    function (head, tail) { return tail; }
  );
};
</code></pre>

<p><em>See also:</em> <a href="https://mitp-content-server.mit.edu/books/content/sectbyfn/books_pres_0/6515/sicp.zip/full-text/book/book-Z-H-14.html#%25_thm_2.4">SICP Exercise 2.4</a></p>
]]></content:encoded>
      <guid>https://kmarekspartz.writeas.com/cons-car-and-cdr-need-not-be-primitive</guid>
      <pubDate>Mon, 16 Mar 2015 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>Review Checklists</title>
      <link>https://kmarekspartz.writeas.com/review-checklists?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[  Making routine simpler.&#xA;---&#xA;&#xA;Review, reflection, and refinement should be part of your routine. I&#39;m a loose follower of GTD and a heavy user of Things (though I don&#39;t always use it in the way they suggest), but I&#39;ve struggled to make reviews part of my routine. I made these checklists to lower the barrier of entry. In addition, I&#39;ve created Beeminder goals to keep me on track.&#xA;&#xA;Unlike most blog posts, this is a living document. I expect it to change. When It does, I plan to make notes of the changes at the bottom.&#xA;&#xA;Daily Review&#xA;&#xA;labelinput type=&#34;checkbox&#34;/ What do I want to get done today?/labelbr&#xA;labelinput type=&#34;checkbox&#34;/ Check calendar./labelbr&#xA;labelinput type=&#34;checkbox&#34;/ Review and archive all emails in inboxes, creating next actions as needed./labelbr&#xA;labelinput type=&#34;checkbox&#34;/ Review next actions in Things, moving to today as needed./labelbr&#xA;labelinput type=&#34;checkbox&#34;/ Review due today actions in Outlook./labelbr&#xA;labelinput type=&#34;checkbox&#34;/ Choose one important thing to get done first tomorrow./labelbr&#xA;&#xA;Weekly Review&#xA;&#xA;labelinput type=&#34;checkbox&#34;/ What went well last week?/labelbr&#xA;labelinput type=&#34;checkbox&#34;/ What didn&#39;t go well last week?/labelbr&#xA;labelinput type=&#34;checkbox&#34;/ What do I want to get done this week?/labelbr&#xA;labelinput type=&#34;checkbox&#34;/ Review someday actions in Things, moving to next as needed./labelbr&#xA;labelinput type=&#34;checkbox&#34;/ Review unscheduled actions in Outlook, scheduling as needed./labelbr&#xA;labelinput type=&#34;checkbox&#34;/ Do I have appointments to make?/labelbr&#xA;&#xA;Monthly Review&#xA;&#xA;labelinput type=&#34;checkbox&#34;/ What went well last month?/labelbr&#xA;labelinput type=&#34;checkbox&#34;/ What didn&#39;t go well last month?/labelbr&#xA;labelinput type=&#34;checkbox&#34;/ What do I want to get done this month?/labelbr&#xA;labelinput type=&#34;checkbox&#34;/ What events are this month?/labelbr&#xA;labelinput type=&#34;checkbox&#34;/ What projects are my focus this month?/labelbr&#xA;labelinput type=&#34;checkbox&#34;/ Are all recurring items being minded?/labelbr&#xA;&#xA;Annual Review&#xA;&#xA;labelinput type=&#34;checkbox&#34;/ What went well last year?/labelbr&#xA;labelinput type=&#34;checkbox&#34;/ What didn&#39;t go well last year?/labelbr&#xA;labelinput type=&#34;checkbox&#34;/ What do I want to get done this year?/labelbr&#xA;labelinput type=&#34;checkbox&#34;/ Where do I want to be next year, and how do I get there?/labelbr&#xA;labelinput type=&#34;checkbox&#34;/ What are my priorities for the next year?/labelbr&#xA;&#xA;Updates:&#xA;&#xA;Added &#34;What went well&#34; and &#34;didn&#39;t&#34; checkpoints. Added backlog reviews.&#xA;Added calendar check. Changed email process from keeping actionable to creating actions.&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<blockquote><p>Making routine simpler.</p>

<hr/>
</blockquote>

<p>Review, reflection, and refinement should be part of your routine. I&#39;m a loose follower of <a href="http://gettingthingsdone.com/">GTD</a> and a heavy user of <a href="http://culturedcode.com/things/guide/">Things</a> (though I don&#39;t always use it in the way they suggest), but I&#39;ve struggled to make reviews part of my routine. I made these checklists to lower the barrier of entry. In addition, I&#39;ve created <a href="https://www.beeminder.com/">Beeminder</a> goals to keep me on track.</p>

<p>Unlike most blog posts, this is a living document. I expect it to change. When It does, I plan to make notes of the changes at the bottom.</p>

<h3 id="daily-review" id="daily-review">Daily Review</h3>

<p><input type="checkbox"/> What do I want to get done today?<br>
<input type="checkbox"/> Check calendar.<br>
<input type="checkbox"/> Review and archive all emails in inboxes, creating next actions as needed.<br>
<input type="checkbox"/> Review next actions in Things, moving to today as needed.<br>
<input type="checkbox"/> Review due today actions in Outlook.<br>
<input type="checkbox"/> Choose one important thing to get done first tomorrow.<br></p>

<h3 id="weekly-review" id="weekly-review">Weekly Review</h3>

<p><input type="checkbox"/> What went well last week?<br>
<input type="checkbox"/> What didn&#39;t go well last week?<br>
<input type="checkbox"/> What do I want to get done this week?<br>
<input type="checkbox"/> Review someday actions in Things, moving to next as needed.<br>
<input type="checkbox"/> Review unscheduled actions in Outlook, scheduling as needed.<br>
<input type="checkbox"/> Do I have appointments to make?<br></p>

<h3 id="monthly-review" id="monthly-review">Monthly Review</h3>

<p><input type="checkbox"/> What went well last month?<br>
<input type="checkbox"/> What didn&#39;t go well last month?<br>
<input type="checkbox"/> What do I want to get done this month?<br>
<input type="checkbox"/> What events are this month?<br>
<input type="checkbox"/> What projects are my focus this month?<br>
<input type="checkbox"/> Are all recurring items being <a href="https://www.beeminder.com/">minded</a>?<br></p>

<h3 id="annual-review" id="annual-review">Annual Review</h3>

<p><input type="checkbox"/> What went well last year?<br>
<input type="checkbox"/> What didn&#39;t go well last year?<br>
<input type="checkbox"/> What do I want to get done this year?<br>
<input type="checkbox"/> Where do I want to be next year, and how do I get there?<br>
<input type="checkbox"/> What are my priorities for the next year?<br></p>

<h3 id="updates" id="updates">Updates:</h3>
<ol><li>Added “What went well” and “didn&#39;t” checkpoints. Added backlog reviews.</li>
<li>Added calendar check. Changed email process from keeping actionable to creating actions.</li></ol>
]]></content:encoded>
      <guid>https://kmarekspartz.writeas.com/review-checklists</guid>
      <pubDate>Tue, 20 Jan 2015 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>Your Turn</title>
      <link>https://kmarekspartz.writeas.com/your-turn?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[  Never give in to impostor syndrome&#xA;---&#xA;&#xA;This week I&#39;ll be participating in the Your Turn Challenge. Participants have promised each other to make at least one blog post each day this week. The challenge combats impostor syndrome and gets a routine going.&#xA;&#xA;Impostor Syndrome&#xA;&#xA;Impostor syndrome is the fear of claiming you are something you are not. Most often, I see people struggle with it in programming, but personally I have had it when becoming a business owner and with writing.&#xA;&#xA;  &#34;I&#39;m terrible at it.&#34;&#xA;&#xA;I&#39;ve noticed people with impostor syndrome often have high standards. People get to a point where they can recognize the good from the bad. However, their standards cause them to notice issues in their work that others would gloss over.&#xA;&#xA;These standards are often a reflection of the breadth of their experience. They would not have these standards if they were true impostors.&#xA;&#xA;  &#34;What if I fail?&#34;&#xA;&#xA;We hear about others&#39; successes, but usually not about the failures that lead to their eventual successes. Even with failure, we learn. Sometimes the best lessons are learned when we fail. Embrace failure and jump in.&#xA;&#xA;  &#34;What if I say the wrong thing?&#34;&#xA;&#xA;With many things in life, you have to claim it before growth can happen. This is the &#34;fake it until you make it&#34; strategy. If you are waiting to be qualified, you&#39;ll have missed your opportunity. Qualification comes through experience; your qualifications will catch up.&#xA;&#xA;Habit, routine, ritual&#xA;&#xA;We improve when we iterate and reflect. Each program, business opportunity, and blog post is an opportunity to start again. Get in a habit of reflecting on lessons learned in previous iterations. Build a routine of trying something new. Make starting a ritual.&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<blockquote><p>Never give in to impostor syndrome</p>

<hr/>
</blockquote>

<p>This week I&#39;ll be participating in the <a href="http://yourturnchallenge.strikingly.com/">Your Turn Challenge</a>. Participants have promised each other to make at least one blog post each day this week. The challenge combats <a href="https://en.wikipedia.org/wiki/Impostor_syndrome">impostor syndrome</a> and gets a routine going.</p>

<h3 id="impostor-syndrome" id="impostor-syndrome">Impostor Syndrome</h3>

<p>Impostor syndrome is the fear of claiming you are something you are not. Most often, I see people struggle with it in programming, but personally I have had it when becoming a business owner and with writing.</p>

<blockquote><p>“I&#39;m terrible at it.”</p></blockquote>

<p>I&#39;ve noticed people with impostor syndrome often have high standards. People get to a point where they can recognize the good from the bad. However, their standards cause them to notice issues in their work that others would gloss over.</p>

<p>These standards are often a reflection of the breadth of their experience. They would not have these standards if they were true impostors.</p>

<blockquote><p>“What if I fail?”</p></blockquote>

<p>We hear about others&#39; successes, but usually not about the failures that lead to their eventual successes. Even with failure, we learn. Sometimes the best lessons are learned when we fail. Embrace failure and jump in.</p>

<blockquote><p>“What if I say the wrong thing?”</p></blockquote>

<p>With many things in life, you have to claim it before growth can happen. This is the “fake it until you make it” strategy. If you are waiting to be qualified, you&#39;ll have missed your opportunity. Qualification comes through experience; your qualifications will catch up.</p>

<h3 id="habit-routine-ritual" id="habit-routine-ritual">Habit, routine, ritual</h3>

<p>We improve when we iterate and reflect. Each program, business opportunity, and blog post is an opportunity to start again. Get in a habit of reflecting on lessons learned in previous iterations. Build a routine of trying something new. Make starting a ritual.</p>
]]></content:encoded>
      <guid>https://kmarekspartz.writeas.com/your-turn</guid>
      <pubDate>Mon, 19 Jan 2015 00:00:00 +0000</pubDate>
    </item>
  </channel>
</rss>