Skip to content
C.W.K.
Stream
Lesson 01 of 05 · published

Price the Cheapest One First

~11 min · migration, planning, measurement, process

Level 0Loose Parts
0 XP0/36 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete

Every Estimate Before the First One Is a Guess

Four apps had to converge onto one shared component. Before any of them had, the honest state of knowledge was: nobody knew what a conversion cost. Everyone had opinions, all of them derived from reading code rather than from moving it, and code reading systematically underestimates — it shows you the shape of the work and hides the accumulated exceptions.

So the order was cheapest first, deliberately, and the first conversion was written up in detail: what moved into the shared component, what had to be deleted from the app, what the shared component had to grow, and what turned out not to be a problem at all.

The Write-Up Is the Deliverable

That record did real work three more times. Each subsequent conversion started by reading it and asking which of those costs applied here. Sometimes the answer was none — the same architectural question came up in all three that followed and cost nothing in any of them, because only the first app had actually exposed the affected controls to a user.

Without the write-up, that question would have been re-litigated three times from scratch, each time by somebody reasoning about it rather than checking. With it, the question took a minute: does this app expose those controls? No. Then this cost does not apply.

The first conversion's invoice is worth more than the conversion. A migration's real risk is that its total cost is unknown until it is mostly spent, so the first unit of work should be chosen and documented for its information value. Cheapest-first is not about momentum — it is about paying the smallest possible price to replace every remaining guess with a priced estimate, while the option to stop is still cheap.

The Last One Was the Cheapest, and That Is Not a Contradiction

The ordering was by expected cost, and the expectation was wrong at the far end. The app everybody assumed would be worst — different platform, its own settings store, a bridge into an editor — turned out to be the cheapest of the four, because most of what it feared did not survive contact.

Its supposed blocker was that a component swap would break an editor bridge. Reading the file settled it: the bridge listens on the window and replies through the message event's source, so it never holds the frame element at all and a swap cannot touch it. And its layout already satisfied the shared component's structural requirement without any change.

That is worth generalizing. Fear-based cost estimates are the least reliable kind, and they are cheapest to disprove. An hour of reading the specific file that worries you will either remove the fear or turn it into a real, sized problem — and either outcome is better than an estimate carrying it as an unexamined premium.

Code

The invoice, written after each conversion·text
CONVERSION 1 - app A (chosen first: expected cheapest)
  moved to shared    : panel geometry -> shared local storage
  DELETED from app   : 3 settings controls (mode picker, w/h sliders)
                       + the state fields and types behind them
  shared grew        : an extra frame permission - this app's embed
                       carried one the shared policy lacked, and
                       adopting as-is would have SILENTLY removed a
                       working input method
  did NOT move       : the embed URL builder - composed from the
                       app's own settings, which is the app-owned
                       half the shared component expects
  surprise           : none

CONVERSION 2 - app B
  applied from #1    : the geometry question -> COST NOTHING HERE.
                       Same architectural change; this app had never
                       exposed the controls, so nothing to delete.
  shared grew        : a region above the frame (a slot)

CONVERSION 3 - app C   (largest host stylesheet)
  applied from #1    : geometry question -> again nothing
  shared grew        : this app had solved packing BETTER than the
                       shared component; the shared version took its
                       approach. Conversions run both directions.

CONVERSION 4 - app D   (expected WORST: different platform, own
                        settings store, an editor bridge)
  actual             : CHEAPEST OF THE FOUR
  the feared blocker : the editor bridge listens on the window and
                       replies via the message event's source, so it
                       never holds the frame element - a swap cannot
                       touch it. Did not survive reading the file.
  layout change      : none; its shell already met the requirement
  moved app-side     : one slot's default centering, in the app's
                       own stylesheet

WHAT THE INVOICE BOUGHT: three conversions that started from a
priced list instead of an argument, and one fear disproved by an
hour of reading rather than by attempting the work.

External links

Exercise

For a migration you are planning across several components, rank them by expected cost and convert the cheapest one completely. Write the invoice: what moved, what was deleted, what the shared thing had to grow, what surprised you, and what cost nothing. Then re-estimate the rest against it and note which estimates changed.
Hint
Write the invoice the same day, before the details compress into 'it went fine'. The specific things that cost nothing are the first to be forgotten, and they are the entries that will save the most time on conversions two through four.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.