<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Typing Turtle</title>
    <description>The latest articles on DEV Community by Typing Turtle (@danieluhl).</description>
    <link>https://dev.to/danieluhl</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F127556%2Fff68caff-ddad-4ef1-b0e7-e5831e2eed9a.jpeg</url>
      <title>DEV Community: Typing Turtle</title>
      <link>https://dev.to/danieluhl</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/danieluhl"/>
    <language>en</language>
    <item>
      <title>FE/BE - Unite Them!</title>
      <dc:creator>Typing Turtle</dc:creator>
      <pubDate>Tue, 17 Mar 2026 14:02:20 +0000</pubDate>
      <link>https://dev.to/danieluhl/febe-unite-them-3kh3</link>
      <guid>https://dev.to/danieluhl/febe-unite-them-3kh3</guid>
      <description>&lt;p&gt;tl;dr;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Teams should agree upon and understand the source of truth domain, working together and evolving it together&lt;/li&gt;
&lt;li&gt;Unification is a conceptual project; having more to do with organizational and team operational structure than code/architecture&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You may notice that the ideas here are nothing new and are well represented in DDD (Domain Driven Design). For more into this topic I highly recommend reading &lt;a href="https://www.amazon.com/Learning-Domain-Driven-Design-Aligning-Architecture/dp/1098100131" rel="noopener noreferrer"&gt;Learning Domain Driven Design&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;We're rewriting a large system at Anedot. We're using rails as a backend to develop a public API which will be consumed by a bleeding edge TanStack app on the frontend, but is built to be consumed by anyone.&lt;/p&gt;

&lt;p&gt;Classically teams are split by frontend and backend specialization. This can lead to "model drift" as conceptual models of the domain that exist within the rails system can become a deeply different beast from the frontend UI models and user flows. This conceptual understanding of the model will eventually lead to differences in code and types.&lt;/p&gt;

&lt;p&gt;Over time this "drift" means the frontend lacks understanding of the system capabilities and the backend loses sight of the purpose of it all - features delivered to the user.&lt;/p&gt;

&lt;p&gt;Over time, FE ends up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;thinking in API responses, not domain concepts&lt;/li&gt;
&lt;li&gt;optimizing for screens, not system behavior&lt;/li&gt;
&lt;li&gt;missing invariants and edge cases enforced in the backend&lt;/li&gt;
&lt;li&gt;discovering issues only after integration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s not a tooling issue, it’s an information flow problem.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In most teams, this is exactly what happens: the frontend becomes a consumer of shapes rather than a participant in the system’s meaning. Over time, that leads to shallow understanding and poorer decisions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The solution is structured exposure to domain decisions and constraints.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Source of Truth
&lt;/h2&gt;

&lt;p&gt;If we can all agree on the source of truth for the domain, we can focus on a shared understanding and vigilant maintenance of that model.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;So is it the shared public API (OpenAPI spec)?&lt;/li&gt;
&lt;li&gt;Or the frontend algebraic data types?&lt;/li&gt;
&lt;li&gt;Or the database schema? (we considered generating typescript types from the rails schema)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The reality is that these will &lt;em&gt;always&lt;/em&gt; diverge unless you constrain the system.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The domain model should sit in the center. DB, API, and UI are projections of that model.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        UI (view models)
             ↑
        API contract (OpenAPI spec)
             ↑
        Domain model  ← this is the real source of truth
             ↓
        Persistence (DB schema)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;If you skip explicitly defining the domain model, the API becomes an accidental one, and drift is inevitable.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The pitfalls of other options
&lt;/h2&gt;

&lt;p&gt;The API is the contract for integration boundaries. APIs are often consumer-optimized, not domain-accurate. They hide or reshape domain concepts and so using them as a source of truth would result in leaky abstractions.&lt;/p&gt;

&lt;p&gt;Tightly coupling the DB schema directly in FE leads to tight coupling to storage decisions.&lt;/p&gt;

&lt;p&gt;Overall we need both interface correctness &lt;em&gt;and&lt;/em&gt; conceptual integrity. We need a good integration boundary &lt;em&gt;and&lt;/em&gt; shared understanding of the domain.&lt;/p&gt;

&lt;h2&gt;
  
  
  How this works
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Define an &lt;em&gt;explicit&lt;/em&gt; domain layer.
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Named domain objects (not DB tables, not API DTOs)&lt;/li&gt;
&lt;li&gt;Clear invariants&lt;/li&gt;
&lt;li&gt;Shared terminology&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Constraints on the domain model implemented in rails should be reflected in the TS types.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// domain (conceptual)&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Subscription&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
  &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;active&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;past_due&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;canceled&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="na"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Plan&lt;/span&gt;
  &lt;span class="na"&gt;billingCycle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;BillingCycle&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Treat API schemas as a projection of the domain
&lt;/h3&gt;

&lt;p&gt;The OpenAPI spec should be derived from (or at least aligned with) domain concepts.&lt;/p&gt;

&lt;p&gt;Bad:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"user_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"plan_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"stripe_subscription_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Better:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"subscriptionId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"plan"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Accept that FE models ≠ API models
&lt;/h3&gt;

&lt;p&gt;Trying to unify FE + API types directly is a trap.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;SubscriptionCard&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
  &lt;span class="na"&gt;isActive&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;
  &lt;span class="na"&gt;renewalDateFormatted&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Prevent drift with process, not just tooling
&lt;/h3&gt;

&lt;p&gt;No "Throw over the wall".&lt;/p&gt;

&lt;p&gt;Cross-functional ownership. Teams aligned with features, not function. Same management, same backlog, same project, same retrospectives and plannings/shapings, same post-mortems.&lt;/p&gt;

&lt;p&gt;In a word, shared &lt;em&gt;ownership&lt;/em&gt; and cultivation of the source of truth domain.&lt;/p&gt;

&lt;p&gt;Before building:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Define domain concept&lt;/li&gt;
&lt;li&gt;Define API shape&lt;/li&gt;
&lt;li&gt;Validate against &lt;em&gt;real&lt;/em&gt; user flows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every API change should answer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What domain concept does this represent?&lt;/li&gt;
&lt;li&gt;Is this shaped for a real workflow?&lt;/li&gt;
&lt;li&gt;Are we leaking DB structure?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Unite Them!
&lt;/h2&gt;

&lt;p&gt;Given our constraint for a public API we can generate projections in the correct direction:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DB -&amp;gt; Rails (domain) -&amp;gt; OpenAPI spec -&amp;gt; typescript types -&amp;gt; UI types -&amp;gt; UI
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Overall it's important to think about both the technology and human side of software to arrive at truly useful systems while maintaining reliability and speed of development.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Dank Owl - custom themes in Warp terminal and neovim</title>
      <dc:creator>Typing Turtle</dc:creator>
      <pubDate>Fri, 24 Feb 2023 18:52:57 +0000</pubDate>
      <link>https://dev.to/danieluhl/dank-owl-custom-themes-in-warp-terminal-and-neovim-4a24</link>
      <guid>https://dev.to/danieluhl/dank-owl-custom-themes-in-warp-terminal-and-neovim-4a24</guid>
      <description>&lt;p&gt;My &lt;a href="https://github.com/warpdotdev/themes"&gt;warp&lt;/a&gt; &lt;a href="https://github.com/danieluhl/dotfiles-3/tree/main/public/warp/themes"&gt;themes&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These go in your &lt;code&gt;~/.warp/themes&lt;/code&gt; directory - I have mine symlinked to a clone of the dotfiles referenced above (see &lt;code&gt;setup.sh&lt;/code&gt; for details).&lt;/p&gt;

&lt;p&gt;I use the font &lt;a href="https://philpl.gumroad.com/l/dank-mono#:~:text=A%20typeface%20designed%20for%20coding,diacritics%20covering%20most%20European%20languages"&gt;Dank Mono&lt;/a&gt; but you can switch the font. If you do want Dank Mono in all it's glory you'll want to run it through the &lt;a href="https://github.com/ryanoasis/nerd-fonts#option-4-homebrew-fonts"&gt;nerd-font patcher&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It's not too bad just pay close attention to the instructions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YYUi_93M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9czs22fba8ifsztd5tp8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YYUi_93M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9czs22fba8ifsztd5tp8.png" alt="Image description" width="880" height="632"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HuhwlEZA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iabyleo61cbrss80h95v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HuhwlEZA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iabyleo61cbrss80h95v.png" alt="Image description" width="880" height="630"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nXliM958--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4owmxuzc0ropk1dl2xlt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nXliM958--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4owmxuzc0ropk1dl2xlt.png" alt="Image description" width="880" height="630"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  UPDATE:
&lt;/h1&gt;

&lt;p&gt;Made a quick script to pull the top deep dream AI generated image into my theme: &lt;a href="https://github.com/danieluhl/random-warp-bg"&gt;https://github.com/danieluhl/random-warp-bg&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This runs in a terminal startup script that also pulls my latest dotfiles: &lt;a href="https://github.com/danieluhl/dotfiles-3/blob/main/public/login.sh"&gt;https://github.com/danieluhl/dotfiles-3/blob/main/public/login.sh&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Which gets kicked off here:&lt;br&gt;
&lt;a href="https://github.com/danieluhl/dotfiles-3/blob/main/public/zshrc#L126"&gt;https://github.com/danieluhl/dotfiles-3/blob/main/public/zshrc#L126&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  UPDATE 2:
&lt;/h1&gt;

&lt;p&gt;you can now run&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npx get-warp-bg --theme [theme-folder]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Passing your theme directory, e.g. for &lt;code&gt;~/.warp/themes/night_owl&lt;/code&gt; you would run &lt;code&gt;npx get-warp-bg --theme night_owl&lt;/code&gt;&lt;/p&gt;

</description>
      <category>warp</category>
      <category>neovim</category>
      <category>themes</category>
    </item>
    <item>
      <title>Flip the Bit to Win Puzzle</title>
      <dc:creator>Typing Turtle</dc:creator>
      <pubDate>Wed, 22 Feb 2023 12:43:22 +0000</pubDate>
      <link>https://dev.to/danieluhl/flip-the-bit-to-win-puzzle-4dd5</link>
      <guid>https://dev.to/danieluhl/flip-the-bit-to-win-puzzle-4dd5</guid>
      <description>&lt;p&gt;Cracking the coding interview problem 5.3:&lt;/p&gt;

&lt;p&gt;You have an integer and you can flip exactly one bit from a 0 to a 1. Write code to find the length of the longest sequence of 1s you could create.&lt;/p&gt;

&lt;p&gt;EXAMPLE:&lt;br&gt;
Input: 1775 (11011101111)&lt;br&gt;
Output: 8&lt;/p&gt;



&lt;p&gt;My first thought here is to take the approach of looking carefully at how I solve this by hand. I look at the longest string of 1s with only one zero separating them.&lt;/p&gt;

&lt;p&gt;This would be pretty difficult to do programatically.&lt;/p&gt;

&lt;p&gt;My second approach is the totally inefficient but works path of flipping each zero to a 1 and then checking the entire number for the largest string of 1s. This would be wildly inefficient for something like '100000000001'. But the input is not too long so performance is probably not a big concern. However, I wouldn't expect an interview to be satisfied with this algorithm.&lt;/p&gt;

&lt;p&gt;My third path is thinking through processing in a loop one bit at a time. This path often involves a bunch of mutable state but is often the most optimized.&lt;/p&gt;

&lt;p&gt;Here's my pseudocode I wrote on my notepad:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;variables:
isSecondZero = false;
currentRun = 0;
combinedRun = 0;

while(1)
  currentRun++
  combinedRun++
  if zero, keep incrementing large until
    we hit a second zero, but reset currentRun
  if second zero, set combinedRun to currentRun

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So for example '11011101111' when we hit the first zero we start counting fresh but also save up the "combined" total. When we hit another zero we save the total length and also treat it as a first zero for the next combined total.&lt;/p&gt;

&lt;p&gt;Here's my first pass JS solution:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const findLargestRun = (binaryString) =&amp;gt; {
  // const binaryString = num.toString(2);
  let currentRun = 0;
  let combinedRun = 0;
  let isSecondZero = false;
  let longestRun = 0;
  [...binaryString].forEach((digit) =&amp;gt; {
    if (digit === '1') {
      currentRun++;
      combinedRun++;
      return;
    }
    if (isSecondZero) {
      longestRun = Math.max(longestRun, combinedRun);
      combinedRun = currentRun + 1;
      isSecondZero = false;
    } else {
      isSecondZero = true;
      combinedRun++;
      currentRun = 0;
    }
  });
  return Math.max(longestRun, combinedRun);
};

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works for everything except zero so I'd add an exception at the top for completeness. I also don't feel great about spreading the string into an array for the loop so I'd probably switch to a &lt;code&gt;for&lt;/code&gt; loop for style points. I think the important part here is variable naming. It's difficult to convey the concept of resetting but also combining on the second zero.&lt;/p&gt;

</description>
      <category>seo</category>
      <category>socialmedia</category>
      <category>career</category>
      <category>uidesign</category>
    </item>
    <item>
      <title>Cracking the Coding Interview 5.2</title>
      <dc:creator>Typing Turtle</dc:creator>
      <pubDate>Tue, 21 Feb 2023 14:28:00 +0000</pubDate>
      <link>https://dev.to/danieluhl/cracking-the-coding-interview-52-4j44</link>
      <guid>https://dev.to/danieluhl/cracking-the-coding-interview-52-4j44</guid>
      <description>&lt;p&gt;Chapter 5 is all about bit manipulation. I'll be working with JS. Here's the puzzle:&lt;/p&gt;

&lt;p&gt;Given a real number between 0 and 1 (e.g. 0.72) that is passed in as a double, print the binary representation. If the number cannot be represented accurately in binary with at most 32 characters, print "ERROR".&lt;/p&gt;

&lt;p&gt;My first thought is that this requires knowledge of binary representation of decimals which is something like &lt;code&gt;twos compliment&lt;/code&gt;. Off to do some googling!&lt;/p&gt;

&lt;p&gt;...&lt;/p&gt;

&lt;p&gt;So I found that it's similar to powers of two where each position is represented by 2^n where n is the position, but it's sort of reversed and 1/2^n.&lt;/p&gt;

&lt;p&gt;So 0.75 would be 1/2^1 + 1/2^2 = 1/2 + 1/4 = 0.11&lt;/p&gt;

&lt;p&gt;For this problem I can't just say &lt;code&gt;input.toString(2)&lt;/code&gt; because I need to check if it can be represented in 32 bits.&lt;/p&gt;

&lt;p&gt;What does it mean to be represented in 32 bits? It means if I get to 0.111011...10 to the 32nd position and still have remainder, then it cannot be represented completely.&lt;/p&gt;

&lt;h2&gt;
  
  
  First pass algorithm
&lt;/h2&gt;

&lt;p&gt;First I'm going to try this basic pattern:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Subtract 1/2^n from the input&lt;/li&gt;
&lt;li&gt;If the result is negative, keep &lt;code&gt;n&lt;/code&gt; position a zero&lt;/li&gt;
&lt;li&gt;If the result is positive, make &lt;code&gt;n&lt;/code&gt; position a 1&lt;/li&gt;
&lt;li&gt;Move to the next position&lt;/li&gt;
&lt;li&gt;Check if we still have a remainder

&lt;ul&gt;
&lt;li&gt;If yes, check if we're at position 32, possibly error&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This should work fine when zero is the input because the first round will come up negative and there will be no remainder.&lt;/p&gt;

&lt;p&gt;Here's my quick first pass that seems to work:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;decimalToBinary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dec&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sub&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="nx"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;dec&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;binaryPosition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;next&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;binaryPosition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;dec&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;binaryPosition&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// check exit conditions&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;next&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pos&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ERROR&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;decimalToBinary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pos&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;decimalToBinary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.75&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;decimalToBinary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.25&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I might add a check at the beginning that the input is as intended (between 0 and 1). I'm also not sure how to find valid and invalid decimal input, all random decimals I tried return &lt;code&gt;ERROR&lt;/code&gt; - which is probably accurate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Time to read the book solution!
&lt;/h2&gt;

&lt;p&gt;The book starts with a slightly different algorithm:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;0b0.101 = 1 * 1/2 + 0 * 1/2^2 + 1 * 1/2^3&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;But this is equivalent to my algorithm. But this is where the similarities end. In the book they use an iterative (vs recursive) approach which multiplies the number by 2 and checking if it's gone over 1. If it is, the binary is a 1 for the position, otherwise it's a zero.&lt;/p&gt;

&lt;p&gt;This is similar but multiplying by 2 instead of subtracting the 1/2^n (essentially division with remainder). It's interesting that they multiply by two instead of bit shifting by 1 (num &amp;lt;&amp;lt; 1).&lt;/p&gt;

&lt;p&gt;Here's my implementation in JS of their solution:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;printBinary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ERROR&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;binary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;binary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ERROR&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;twoNum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;twoNum&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;binary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;binary&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;twoNum&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;binary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;binary&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;twoNum&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;binary&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While the BigO of the solutions is the same, the recursive in JS will have some overhead of function calls. Since we know the max calls will be 32 it's not a concern, so the biggest question is which is easier to comprehend. I think my solution keeps closer to the mathematical solutions which is the logical way most people will approach understanding this problem. If we did need this function to be hyper-optimized, we may need to take a closer look at the individual operations of each pattern and take the one with the fewest cycles.&lt;/p&gt;

&lt;p&gt;This was pretty fun, see you in the next one!&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>help</category>
      <category>posts</category>
    </item>
    <item>
      <title>Work Time vs Home</title>
      <dc:creator>Typing Turtle</dc:creator>
      <pubDate>Fri, 23 Apr 2021 15:08:12 +0000</pubDate>
      <link>https://dev.to/danieluhl/work-time-vs-home-4k9o</link>
      <guid>https://dev.to/danieluhl/work-time-vs-home-4k9o</guid>
      <description>&lt;p&gt;I've recently realized how short the hours at work are. On a workday we tend to think of tons of time available at work, and very little once we get home. However, if you've taken part of a workday to do non-work activity (e.g. read a book) you'll quickly realize how short the at-work time really is.&lt;/p&gt;

&lt;p&gt;Each moment matters. The number of times you need to go to the bathroom maters. I'm not saying we should be paranoid about optimal time usage in every moment. In fact, we tend to greatly overestimate the time it takes to do the connective tissue tasks throughout the day. But we should be aware of where time is going at all times and try to not get lulled into a false sense of having lots of time to spare during the day.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Habit Breaker: circles</title>
      <dc:creator>Typing Turtle</dc:creator>
      <pubDate>Thu, 15 Apr 2021 14:39:17 +0000</pubDate>
      <link>https://dev.to/danieluhl/habit-breaker-circles-1nna</link>
      <guid>https://dev.to/danieluhl/habit-breaker-circles-1nna</guid>
      <description>&lt;p&gt;I draw circles for todos in my notes. I draw starting at the top of the circle and go counter-clockwise. Sometimes the smallest habit breakers bring moments of awareness into the day. This week I'm doing this: start the circle at bottom-right and go clockwise.&lt;/p&gt;

</description>
      <category>habit</category>
    </item>
    <item>
      <title>Fiction Reading for Software Engineers</title>
      <dc:creator>Typing Turtle</dc:creator>
      <pubDate>Fri, 09 Apr 2021 15:58:45 +0000</pubDate>
      <link>https://dev.to/danieluhl/fiction-reading-for-software-engineers-2mj7</link>
      <guid>https://dev.to/danieluhl/fiction-reading-for-software-engineers-2mj7</guid>
      <description>&lt;p&gt;My favorite line in the Harry Potter movies is zombie Dumbledore towards the end:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Of course it's happening inside your head, Harry. Why should that mean that it's not real?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Software engineering is primarily a people problem. Software engineering also happens entirely in your head.&lt;/p&gt;

&lt;p&gt;When you read good fiction books you begin to build the muscle of creating a good story in your head. You can build out worlds and mental models more easily. Same for playing games like D&amp;amp;D.&lt;/p&gt;

&lt;p&gt;Bring this skill and habit to engineering in how you think and communicate the non-fiction reality in terms that pulls others in and captures their imagination and in the end creates clarity and cohesion.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Speak as if Someone is Listening</title>
      <dc:creator>Typing Turtle</dc:creator>
      <pubDate>Fri, 02 Apr 2021 14:26:00 +0000</pubDate>
      <link>https://dev.to/danieluhl/speak-as-if-someone-is-listening-3f7h</link>
      <guid>https://dev.to/danieluhl/speak-as-if-someone-is-listening-3f7h</guid>
      <description>&lt;p&gt;I was riding in an uber with my wife long ago and noticed our conversation took on a strange tone. Without any planning, we both began to speak with half our minds taking the point of view of the driver. It's hard to describe, but you'd know it if this has happened to you.&lt;/p&gt;

&lt;p&gt;It reminds me of a line from Seneca: "Live among men as if God beheld you; speak with God as if men were listening"&lt;/p&gt;

&lt;p&gt;Our minds are great. With each new person that enters a room we can immediately adjust what we say to accommodate a level of empathy for how that person will understand or react to what we are saying.&lt;/p&gt;

&lt;p&gt;Recently my manager and tech lead are only coming to two standups per week. The other three standups are markedly different. With less people in the room and no manager it's easier to open up and express oneself in a clear manner. If you don't have an open space like this for your team, I do highly recommend finding it.&lt;/p&gt;

</description>
      <category>agile</category>
      <category>standup</category>
    </item>
    <item>
      <title>Can't Stop, Won't Stop</title>
      <dc:creator>Typing Turtle</dc:creator>
      <pubDate>Thu, 25 Mar 2021 13:09:16 +0000</pubDate>
      <link>https://dev.to/danieluhl/can-t-stop-won-t-stop-3d31</link>
      <guid>https://dev.to/danieluhl/can-t-stop-won-t-stop-3d31</guid>
      <description>&lt;h1&gt;
  
  
  Friday Nights
&lt;/h1&gt;

&lt;p&gt;On typical Fridays, I would often go hang out at bars with friends, celebrate weekly wins, and was overjoyed for the weekend.&lt;/p&gt;

&lt;p&gt;Because of this routine, when I went deep in self-reflection by meditating on a Friday after work I saw the welling up of joy and anticipation for the night. &lt;/p&gt;

&lt;p&gt;I wondered, where does this feeling come from? There's nothing inherently different about my internal state now vs any other meditative sitting. Why is this coming up? Why can't I control it? Why can't I bring it up on other days?&lt;/p&gt;

&lt;p&gt;Societal expectations, habits, and history are very strong and deeply ingrained in the mind. It takes years of practice to unwind these subconscious patterns and master them. However, just noticing them at a surface level and understanding their nature can help setup success.&lt;/p&gt;

&lt;h2&gt;
  
  
  Working Late
&lt;/h2&gt;

&lt;p&gt;Another example of the same situation "feeling" a different way is when I do work on my own time. I'm not "on the clock", but I have an itch to scratch or rising motivation that I can't explain. &lt;/p&gt;

&lt;p&gt;I &lt;em&gt;could&lt;/em&gt; go play video games, watch tv, catch up on reading, but instead I choose to think through a hard problem or debug some code.&lt;/p&gt;

&lt;p&gt;The difference in feeling is subtle yet influences everything about the activity:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I'm more open to rabbit holes and going deep to investigate underlying logic; it's my time, I can do what I want with it.&lt;/li&gt;
&lt;li&gt;I'm more creative in problem solving. I'm no longer driving precisely at what the company/manager/team wants or what some ticket says, I'm coding for myself and what &lt;em&gt;I&lt;/em&gt; want&lt;/li&gt;
&lt;li&gt;I engage my subconscious, often if I've taking my free time on a problem it will stick with me throughout the night even in sleep thinking through all different paths I could have taken&lt;/li&gt;
&lt;li&gt;It feels good! When it's my time I feel more comfortable with not being productive. It's not about the goal, it's about the journey.&lt;/li&gt;
&lt;li&gt;It's more productive. Despite the previous bullet, it's usually much more productive because when stress goes down and creativity goes up programming gets better. Happy engineers write better code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's not something I can control, like Friday nights it's an involuntary shift in approach that happens naturally and is difficult to reproduce.&lt;/p&gt;

&lt;h2&gt;
  
  
  Not All Good
&lt;/h2&gt;

&lt;p&gt;Sometimes working on your own time is a recipe for disaster. Burnout lives here and work/life balance can quickly go out the window. Like the involuntary feeling of excitement and anticipation that a Friday night brings, we need to be aware of the feeling going into off-hours work. Is it going to be the big win, or are we pushing ourselves into a bad area?&lt;/p&gt;

&lt;h2&gt;
  
  
  Re-framing
&lt;/h2&gt;

&lt;p&gt;There's a lack of distinction in our industry between positive off-hours work and negative. Corporations tend to play on the safe side saying you shouldn't work off hours and go so far as to say don't use internal comms off hours because it sets a bad example. This throws the baby out with the bath water.&lt;/p&gt;

&lt;p&gt;We need new terminology and re-framing around the concept of positive, motivating, productive off-hours work. Something with no shame attached and that doesn't require an apology the next day.&lt;/p&gt;

&lt;p&gt;I don't have any brilliant ideas here, if you do, please comment!&lt;/p&gt;

&lt;h2&gt;
  
  
  Other Thoughts
&lt;/h2&gt;

&lt;p&gt;Maybe this is connected to "flow" time but having flow time during the day still feels different than working off-hours. Again, this feeling of freedom and change in approach is something I have yet to be able to replicate during the work day. It's not about time of day either, take a vacation day and do some work and you get the same results.&lt;/p&gt;

</description>
      <category>inspiration</category>
    </item>
    <item>
      <title>Mistake vs Tragedy</title>
      <dc:creator>Typing Turtle</dc:creator>
      <pubDate>Tue, 09 Mar 2021 21:55:23 +0000</pubDate>
      <link>https://dev.to/danieluhl/mistake-vs-tragedy-4h1k</link>
      <guid>https://dev.to/danieluhl/mistake-vs-tragedy-4h1k</guid>
      <description>&lt;p&gt;Fair warning, I'm getting into stoic philosophy a bit here. If you're not into the stoic perspective, I recommend looking up research on growth vs static mindset. Same junk different name 😋&lt;/p&gt;

&lt;p&gt;Tragedy is severe an unwarranted injustice where nobody is at fault. The circumstances of nature happen to come together in a way that something awful happens and it's pointless.&lt;/p&gt;

&lt;p&gt;I was playing a video game the other day and started reflecting on the several mistakes I made - mostly around optimizing for time/resources. The thought is, if I had more information, awareness, reaction time, etc. I would have taken a different action.&lt;/p&gt;

&lt;p&gt;I started thinking, what's the difference between a tragedy and a mistake?&lt;/p&gt;

&lt;p&gt;Stoic philosophy often points towards determinism, that is, we cannot change the past and given the trajectory of the universe we also cannot alter the future. We can learn from the past and adjust our actions and all of this is predictable. The question I often get when talking to others about this is, "so what? How does this change anything about how I live". This is a great question for any philosophical line of thinking.&lt;/p&gt;

&lt;p&gt;In the case of determinism, the hurdle of understanding its truth is just the start, and most people have trouble getting past that. But humor me for a moment and assume determinism is true. This assumption sets us down an interesting path chain of logic! &lt;/p&gt;

&lt;p&gt;Let's look at a common occurrence when a player makes a mistake in a video game: the other players blame them for losing the game, the player may hit their keyboard and blame the speed of their computer, everyone &lt;em&gt;feels&lt;/em&gt; awful.&lt;/p&gt;

&lt;p&gt;None of this makes sense from a lens of determinism. Instead, we can think deeply about all the factors that led up to the moment of that mistake with the knowledge that it was inevitable given the situation. We stop thinking in terms of agency and start thinking in systems! &lt;/p&gt;

&lt;p&gt;Regret, guilt, and blame do not exist in this worldview, there is no place for them, instead we get technical, creative, and curious. &lt;/p&gt;

&lt;p&gt;What if the computer was a factor? How could I test that? How can I most accurately re-create the situation in a simulator to adjust and try different things to optimize the outcome next time it happens? Maybe I can even get an AI to do that work for me!&lt;/p&gt;




&lt;p&gt;I've been in 12 severe car accidents, I know that's a lot, but I swear I'm a good driver. One particularly bad accident involved getting t-boned by a large truck completely smashing my car. &lt;/p&gt;

&lt;p&gt;This left me quite shaken up and I spent the entire night re-living the few hours before the accident: "if only I hadn't forgot my wallet and gone back in the house", "if only I hadn't taken extra time in the shower", "if I had taken a different route to work", on and on and on and on. So many events led to us both being in that exact time and place and boom! &lt;/p&gt;

&lt;p&gt;I felt so powerless in that moment: the accident had taken place and there's nothing I could do to change that fact. This was a key turning point and realization for me. Stoicism takes this feeling of powerlessness and normalizes it applying the idea broadly to all events. Yes you're powerless, and that's OK. In fact, it's better to understand this true nature so you can get past the mental anguish that would arise otherwise.&lt;/p&gt;




&lt;p&gt;There is a key moment where it's critical to catch yourself, reflect, and practice making mental adjustments by thinking through the deterministic worldview. The key moment to look for is just when you realize you've made a mistake. Take a moment to check what's going on in your body and mind. What is your natural thought process? How do you feel? Does your heart rate go up, maybe tightness in the chest or lump in the throat, maybe a sinking feeling? &lt;/p&gt;

&lt;p&gt;With practice you can replace the typical default bad feelings of regret, loss, and guilt with immediate curiosity: "huh, I wonder why that happened". Remove your &lt;strong&gt;self&lt;/strong&gt; from the equation by default and you'll quickly find yourself chuckling on the inside by others' reactions.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Learning from Shoveling the Yard</title>
      <dc:creator>Typing Turtle</dc:creator>
      <pubDate>Fri, 05 Mar 2021 20:09:37 +0000</pubDate>
      <link>https://dev.to/danieluhl/learning-from-shoveling-the-yard-4odg</link>
      <guid>https://dev.to/danieluhl/learning-from-shoveling-the-yard-4odg</guid>
      <description>&lt;h1&gt;
  
  
  Shoveling Sucks
&lt;/h1&gt;

&lt;p&gt;Living in the northeast shoveling driveways is a known pain. This year I got a small electric snowblower which helped a bit but it's always been a chore. My back aches after, it's cold and wet and often early in the morning so we can get the car out for the day.&lt;/p&gt;

&lt;h2&gt;
  
  
  I need a sledding hill!
&lt;/h2&gt;

&lt;p&gt;This year due to travel restrictions it didn't make much sense to take our usual winter vacation out of state. I have a 1yo boy and I wanted to introduce him to sledding. Local tubing places have height restrictions he does not meet. &lt;/p&gt;

&lt;p&gt;After much research I looked out the window and realized I have a pretty good slope in my yard. Just need to pile up some snow. So I took an afternoon and built a curving path with walls so you don't fly out and a big wall at the end to catch you. It was awesome. The baby giggled the whole way down. We spent the next two weeks tubing every day!&lt;/p&gt;

&lt;h2&gt;
  
  
  Wait, shoveling is awesome?
&lt;/h2&gt;

&lt;p&gt;Only in later reflection did it hit me: the activity of shoveling in the yard was physically the same as shoveling the driveway, but my mental state was profoundly different. I actually enjoyed it. How could this be? And, if I can deconstruct this phenomenon, could I enjoy shoveling the yard just as much? Or even expand this to apply to other chores I dislike?&lt;/p&gt;

&lt;h2&gt;
  
  
  Key differences
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Driveway&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Needs to be done (no autonomy)&lt;/li&gt;
&lt;li&gt;Known solution (no creativity)&lt;/li&gt;
&lt;li&gt;Same every year (no variety)&lt;/li&gt;
&lt;li&gt;Result is restored ability to drive the car&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Yard&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I had the idea&lt;/li&gt;
&lt;li&gt;I decided &lt;em&gt;how&lt;/em&gt; to form the hill&lt;/li&gt;
&lt;li&gt;I did the work on my time&lt;/li&gt;
&lt;li&gt;I planned out each phase, got creative with the process&lt;/li&gt;
&lt;li&gt;Result is something both I and others enjoy&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Shifting State of Mind
&lt;/h2&gt;

&lt;p&gt;If something is boring, turn it into a game. Maybe next time I'll try to get all the snow in one area and build an igloo.&lt;/p&gt;

&lt;p&gt;When my wife pesters me to go shovel I shouldn't take this as a burden, but as a sign of how grateful she is that I'm around to take care of these sorts of tasks. I'm much happier when I'm doing something that I know others will enjoy.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>My First Chrome Plugin</title>
      <dc:creator>Typing Turtle</dc:creator>
      <pubDate>Fri, 05 Mar 2021 18:06:41 +0000</pubDate>
      <link>https://dev.to/danieluhl/my-first-chrome-plugin-389c</link>
      <guid>https://dev.to/danieluhl/my-first-chrome-plugin-389c</guid>
      <description>&lt;p&gt;It was much faster than I thought it would be.&lt;/p&gt;

&lt;h2&gt;
  
  
  Generate the Project
&lt;/h2&gt;

&lt;p&gt;I used &lt;a href="https://yeoman.io/"&gt;Yeoman&lt;/a&gt; to generate the scaffolding. Make a project folder and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -g yo generator-web-extension
yo web-extension
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lots of options but I'd go with the minimum for now. One thing I did include was a button in the extension.&lt;/p&gt;

&lt;p&gt;Then go to your &lt;a href="https://dev.tochrome://extensions/"&gt;chrome extensions&lt;/a&gt; and click "Load Unpacked". Find the &lt;code&gt;dist&lt;/code&gt; directory that was generated and you should have your dev extension in chrome ready to go. Click the puzzle piece in the extensions area and pin your extension.&lt;/p&gt;

&lt;p&gt;Now we can fire up the watcher and start coding while getting a live refresh:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run dev chrome
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Code Structure
&lt;/h2&gt;

&lt;p&gt;There's a little popup when you click the extension. Think of this as it's own separate web page. In fact, you can right-click the extension and "inspect" just like it's a web page. This is where you'll see any &lt;code&gt;console.log&lt;/code&gt; for the extension bits.&lt;/p&gt;

&lt;p&gt;We'll be injecting a super simple timer onto the page. To do this the extension needs to send a message to the page.&lt;/p&gt;

&lt;p&gt;Go to &lt;code&gt;app/pages/popup.html&lt;/code&gt; and add a button with class &lt;code&gt;timerButton&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now look in &lt;code&gt;/app/scripts&lt;/code&gt; and you'll see three files, two we'll be touching are:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;popup.js&lt;/code&gt;: this is for code that runs inside the extension "page"&lt;/p&gt;

&lt;p&gt;&lt;code&gt;contentscript.js&lt;/code&gt;: this is for code that runs in the page the user is currently on&lt;/p&gt;

&lt;p&gt;So we need to send a message from &lt;code&gt;popup.js&lt;/code&gt; to &lt;code&gt;contentscript.js&lt;/code&gt; to trigger injection of a timer on the page.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;popup.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;document.querySelector('.timerButton').addEventListener('click', addTimer);
function addTimer() {
  browser.tabs
    .query({
      active: true,
      currentWindow: true,
    })
    .then(tabs =&amp;gt; {
      browser.tabs
        .sendMessage(tabs[0].id, {
          timerMessage: `create`,
        })
        .then(response =&amp;gt; {
          console.log({response});
        })
        .catch(({message}) =&amp;gt; console.error('error', message));
    });
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once we hit the page we'll do all the timer stuff including injecting some html on the page that has some hacky draggability:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const SECOND = 1000;
const MINUTE = SECOND * 60;
class Timer {
  timerHtmlHandle;
  timerInterval;
  originalTime;
  currentTime;
  startTimer() {
    this.timerInterval = setInterval(this.tick.bind(this), SECOND);
  }
  stopTimer() {
    clearInterval(this.timerInterval);
    this.timerInterval = null;
  }
  toggleTimer() {
    this.timerInterval ? this.stopTimer() : this.startTimer();
  }
  resetTimer(seedTime = prompt('Enter Timer Minutes') * MINUTE) {
    this.stopTimer();
    this.currentTime = this.originalTime = seedTime;
    this.tick();
  }
  refreshTimer() {
    this.stopTimer();
    this.currentTime = this.originalTime;
    this.tick();
  }
  addMinute() {
    this.currentTime = this.currentTime + MINUTE;
    this.tick();
  }
  tick() {
    const timerText = `${Math.floor(this.currentTime / MINUTE)}:${`${
      (this.currentTime % MINUTE) / SECOND
    }`.padStart(2, '0')}`;

    this.timerHtmlHandle.innerText = timerText;
    this.currentTime = this.currentTime - SECOND;

    if (this.currentTime &amp;lt; 0) {
      this.stopTimer();
    } else if (this.currentTime &amp;lt; MINUTE * 2) {
      // two minute warning
      this.timerHtmlHandle.style.color = '#f5b20a';
    } else if (this.currentTime &amp;lt; MINUTE) {
      // one minute warning
      this.timerHtmlHandle.style.color = '#da521f';
    }
  }
}
const duhlTimer = new Timer();

const addTimer = () =&amp;gt; {
  const timerHtml = `
    &amp;lt;div draggable="true" class="duhl-timer"&amp;gt;
      &amp;lt;div class="drag"&amp;gt;&amp;lt;/div&amp;gt;
      &amp;lt;div class="ext-timer"&amp;gt;0:00&amp;lt;/div&amp;gt;
      &amp;lt;button class="refreshTimer"&amp;gt;🔂&amp;lt;/button&amp;gt;
      &amp;lt;button class="addMinute"&amp;gt;1️⃣&amp;lt;/button&amp;gt;
      &amp;lt;button class="resetTimer"&amp;gt;🆕&amp;lt;/button&amp;gt;
      &amp;lt;button class="toggleTimer"&amp;gt;⏯&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  `;
  document.body.insertAdjacentHTML('afterbegin', timerHtml);
  duhlTimer.timerHtmlHandle = document.querySelector('.ext-timer');
  document
    .querySelector('.duhl-timer .refreshTimer')
    .addEventListener('click', () =&amp;gt; duhlTimer.refreshTimer());
  document
    .querySelector('.duhl-timer .addMinute')
    .addEventListener('click', () =&amp;gt; duhlTimer.addMinute());
  document
    .querySelector('.duhl-timer .resetTimer')
    .addEventListener('click', () =&amp;gt; duhlTimer.resetTimer());
  document
    .querySelector('.duhl-timer .toggleTimer')
    .addEventListener('click', () =&amp;gt; duhlTimer.toggleTimer());
  document.querySelector('.duhl-timer').addEventListener('dragend', e =&amp;gt; {
    console.log(e);
    e.target.style.top = `${e.pageY}px`;
    e.target.style.left = `${e.pageX}px`;
  });
};

browser.runtime.onMessage.addListener((req, sender, sendResponse) =&amp;gt; {
  // only one timer for you!
  if (duhlTimer &amp;amp;&amp;amp; duhlTimer.timerHtmlHandle) {
    return;
  }
  addTimer();
  // reflow before starting things or it gets wonky
  setTimeout(() =&amp;gt; {
    duhlTimer.resetTimer(5 * MINUTE);
  });
});

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally the related &lt;code&gt;contentscript.css&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.duhl-timer {
  padding: 0 4px;
  position: absolute;
  z-index: 10000000;
  top: 0;
  left: 0;
  background: rgba(0, 0, 0, 0.8);
  box-shadow: 0 2px 2px rgba(0, 0, 0, 0.3);
  border: 1px solid #fff;
  border-radius: 12px;
  color: #fff;
}

.duhl-timer .drag {
  position: absolute;
  top: 0;
  left: 0;
  width: 16px;
  height: 16px;
  border-radius: 12px 0 2px 0;
  background: repeating-linear-gradient(
    to bottom,
    #666,
    #666 2px,
    #333 2px,
    #333 4px
  );
  cursor: move;
}

.duhl-timer .ext-timer {
  font-size: 3rem;
  line-height: 3rem;
  text-align: center;
}

.duhl-timer button {
  padding: 2px 6px;
  border: none;
  background: none;
  border-radius: 4px;
}

.duhl-timer button:hover {
  cursor: pointer;
  background: rgba(255, 255, 255, 0.1);
}
.duhl-timer button:active {
  background: rgba(255, 255, 255, 0.2);
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's my timer injection plugin!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/danieluhl/timer-chrome-extension"&gt;src&lt;/a&gt;&lt;/p&gt;

</description>
      <category>chrome</category>
      <category>plugin</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
