<?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: Good game</title>
    <description>The latest articles on DEV Community by Good game (@good_game_a9756179b299005).</description>
    <link>https://dev.to/good_game_a9756179b299005</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3997057%2F78d70ed5-a14f-4066-8fb0-7288546454ed.png</url>
      <title>DEV Community: Good game</title>
      <link>https://dev.to/good_game_a9756179b299005</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/good_game_a9756179b299005"/>
    <language>en</language>
    <item>
      <title>Money Is the Only Invariant: Modeling Personal Finance as Hours of Your Life</title>
      <dc:creator>Good game</dc:creator>
      <pubDate>Mon, 22 Jun 2026 13:46:14 +0000</pubDate>
      <link>https://dev.to/good_game_a9756179b299005/money-is-the-only-invariant-modeling-personal-finance-as-hours-of-your-life-4feo</link>
      <guid>https://dev.to/good_game_a9756179b299005/money-is-the-only-invariant-modeling-personal-finance-as-hours-of-your-life-4feo</guid>
      <description>&lt;p&gt;I spent a while building a personal-finance app around one idea: a price isn't really dollars, it's hours of your life. A $1,200 phone is "3 weeks of work." The dollars are an abstraction; the time is not.&lt;/p&gt;

&lt;p&gt;The interesting part wasn't the UI — it was figuring out what the &lt;em&gt;source of truth&lt;/em&gt; should be.&lt;/p&gt;

&lt;p&gt;## The naive model&lt;/p&gt;

&lt;p&gt;My first version stored everything in hours. Save $50 → store "2.5 hours saved." Clean and simple — until the user's salary changes. Suddenly all their history is wrong: those 2.5 hours were&lt;br&gt;
  computed against an old hourly rate.&lt;/p&gt;

&lt;p&gt;Do you freeze the old value? Re-compute it? Both feel arbitrary, and both create migration pain every time the income profile changes.&lt;/p&gt;

&lt;p&gt;## Flipping it: money as the invariant&lt;/p&gt;

&lt;p&gt;The fix was to invert the model: &lt;strong&gt;money is the only thing stored as truth.&lt;/strong&gt; Hours and days are never persisted — they're &lt;em&gt;projections&lt;/em&gt; of a money amount through your &lt;em&gt;current&lt;/em&gt; income&lt;br&gt;
  profile.&lt;/p&gt;

&lt;p&gt;hoursForMoney(money, profile) = money / hourlyIncome(profile)&lt;br&gt;
  lifeDaysForMoney(money, profile) = money / netMonthly(profile) * 30&lt;/p&gt;

&lt;p&gt;Your salary doubles? Your past savings now represent half as many hours — automatically. The framing shifts from "how many hours this &lt;em&gt;was&lt;/em&gt; worth" to "your savings equal X hours of your life&lt;br&gt;
  &lt;em&gt;right now&lt;/em&gt;."&lt;/p&gt;

&lt;p&gt;## Why this paid off&lt;/p&gt;

&lt;p&gt;This killed a whole class of edge cases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Editing or deleting a record&lt;/strong&gt; just changes the money total. Every derived view — goals, achievements, streaks — recomputes reactively, because none of them store hours.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One conversion function&lt;/strong&gt;, one source of truth. No "4 copies of the hourly-rate formula slowly drifting apart" (which is exactly the bug I started with).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No migrations&lt;/strong&gt; when the profile changes — there's nothing derived to migrate.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The whole system became easier to reason about once I accepted that time is a &lt;em&gt;view&lt;/em&gt;, not &lt;em&gt;data&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;## The open question&lt;/p&gt;

&lt;p&gt;The behavioral one I still can't answer: does seeing "3 weeks of your life" actually change what people buy, or is it a novelty that wears off after a month? I have anecdotes, not data —&lt;br&gt;
  curious if anyone here has tried framing spending this way.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(The idea ships as a free Android app — &lt;a href="https://play.google.com/store/apps/details?id=com.priceoftime" rel="noopener noreferrer"&gt;Price of Time on Google Play&lt;/a&gt; — but the model above is the part I think is worth discussing.)&lt;/em&gt;&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>kotlin</category>
      <category>android</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
