The Confident Pipeline
The Confident Pipeline: timid code checks nil at every step because it trusts nothing, including itself. Confident code validates once, at the barricade, and then speaks in declarative sentences. Same pipeline, written both ways - and then both are made to face the same malformed input, so the difference is behavior, not taste.
Data & Pipelines
Round 11
Avdi Grimm
exit 0
bundle exec ruby examples/confident_pipeline.rb
a real captured run
THE CONFIDENT PIPELINE (same job, two postures)
timid: 10 conditionals, 24 lines
confident: 0 conditionals, 9 lines
good input:
timid: {:total_cents=>2750, :delivery=>"receipt to a@b.co"}
confident: {:total_cents=>2750, :delivery=>"receipt to a@b.co"}
malformed input (an item with a nil price, email: ""):
timid: {:total_cents=>0, :delivery=>"no receipt"}
confident: raises ValidationError - email rejected AT THE DOOR
look at what the timid version returned for garbage: a polite,
well-formed, WRONG answer - zero dollars, "no receipt", no error.
that nil-tolerance didn't handle the bad input, it LAUNDERED it;
some downstream ledger now owes a customer an explanation. the
confident version has one conditional posture: a barricade at
each door (inputs validated once, outputs too - honesty is also
a promise about what you return). inside, every line is a
declarative sentence about data that is KNOWN to be shaped.
confidence isn't optimism - it's pushing all the doubt to the
boundary, where it can say no out loud.
source
# frozen_string_literal: true # The Confident Pipeline: timid code checks nil at every step because # it trusts nothing, including itself. Confident code validates once, # at the barricade, and then speaks in declarative sentences. Same # pipeline, written both ways - and then both are made to face the # same malformed input, so the difference is behavior, not taste. # # bundle exec ruby examples/confident_pipeline.rb # # Runs offline; the conditional count is computed from this file. require class="s">"bundler/setup" require class="s">"agentic" Agentic.logger.level = class="y">:fatal # --- the timid version ---------------------------------------------------------- # Every method distrusts its caller, so every method re-litigates # reality. Read it aloud: it's all subordinate clauses. module Timid def self.process(order) return nil if order.nil? items = order[class="y">:items] return nil if items.nil? || !items.is_a?(Array) || items.empty? total = 0 items.each do |item| next if item.nil? price = item[class="y">:price_cents] qty = item[class="y">:qty] || 1 total += price * qty if !price.nil? && price.is_a?(Numeric) && price >= 0 end email = order[class="y">:email] receipt = if email && !email.empty? class="s">"receipt to #{email}" end {total_cents: total, delivery: receipt || class="s">"no receipt"} end end # --- the confident version ------------------------------------------------------- # One barricade at the boundary. Inside it, every sentence is # indicative mood: the data IS shaped; the contract said so. ORDER_CONTRACT = Agentic:class="y">:CapabilitySpecification.new( name: class="s">"process_order", description: class="s">"Price an order", version: class="s">"1.0.0", inputs: { items: {type: class="s">"array", required: true, non_empty: true}, email: {type: class="s">"string", required: true, non_empty: true} }, outputs: {total_cents: {type: class="s">"number", required: true}, delivery: {type: class="s">"string", required: true}} ) BARRICADE = Agentic:class="y">:CapabilityValidator.new(ORDER_CONTRACT) module Confident def self.process(order) BARRICADE.validate_inputs!(order) total = order[class="y">:items].sum { |item| item.fetch(class="y">:price_cents) * item.fetch(class="y">:qty, 1) } output = {total_cents: total, delivery: class="s">"receipt to #{order[class="y">:email]}"} BARRICADE.validate_outputs!(output) output end end GOOD = {items: [{price_cents: 1200, qty: 2}, {price_cents: 350}], email: class="s">"a@b.co"}.freeze BAD = {items: [{price_cents: nil, qty: 3}], email: class="s">""}.freeze puts class="s">"THE CONFIDENT PIPELINE (same job, two postures)" puts source = File.read(__FILE__, encoding: class="s">"UTF-8") timid_src = source[/module Timid.*?\n end\nend/m] confident_src = source[/module Confident.*?\n end\nend/m] count = ->(src) { src.scan(/\b(?class="y">:if|unless|return nil|next if|\|\|)\s/).size + src.scan(class="s">"&&").size } puts format(class="s">" %-12s %2d conditionals, %2d lines", class="s">"timid:", count.call(timid_src), timid_src.lines.size) puts format(class="s">" %-12s %2d conditionals, %2d lines", class="s">"confident:", count.call(confident_src), confident_src.lines.size) puts puts class="s">" good input:" puts class="s">" timid: #{Timid.process(GOOD)}" puts class="s">" confident: #{Confident.process(GOOD)}" puts puts class="s">" malformed input (an item with a nil price, email: \"\class="s">"):" puts class="s">" timid: #{Timid.process(BAD).inspect}" begin Confident.process(BAD) rescue Agentic:class="y">:Errors:class="y">:ValidationError => e puts class="s">" confident: raises ValidationError - #{e.violations.keys.join(", class="s">")} rejected AT THE DOOR" end puts puts class="s">" look at what the timid version returned for garbage: a polite," puts class="s">" well-formed, WRONG answer - zero dollars, \"no receipt\class="s">", no error." puts class="s">" that nil-tolerance didn't handle the bad input, it LAUNDERED it;" puts class="s">" some downstream ledger now owes a customer an explanation. the" puts class="s">" confident version has one conditional posture: a barricade at" puts class="s">" each door (inputs validated once, outputs too - honesty is also" puts class="s">" a promise about what you return). inside, every line is a" puts class="s">" declarative sentence about data that is KNOWN to be shaped." puts class="s">" confidence isn't optimism - it's pushing all the doubt to the" puts class="s">" boundary, where it can say no out loud."