Be Framework Blog

ROP and BOP: From Transformation to Existence

Unix gave us pipes. Functional programming gave us Result. What if the domain doesn’t need either?

The Pipeline

The core of Railway Oriented Programming is simple. A workflow is a pipeline. Failure is just another track.

Input → validate → extract → identify → save
          ↓           ↓          ↓         ↓
        Error       Error      Error     Error

cat | grep | sort flows text through transformations. ROP flows domain data through functions — with error handling made explicit in the type system.

A TypeScript example:

const workflow: WorkFlow = (command) =>
  ok(command)
    .andThen(validateReservationEvent)
    .andThen(extractActualVisitor)
    .asyncAndThen(identifyCustomer(findIdenticalCustomer))
    .andThen(importReservationEvent)

Each stage has its own type:

UnvalidatedCommand
  → SiteReservationValidated
    → VisitorExtracted
      → CustomerIdentified
        → SiteReservationEventImported

The functional concern is data transformation. ROP gives that transformation a failure context. Result types make errors explicit. Union types eliminate impossible states. Immutability prevents corruption.

The Resonance

Place a Be Framework chain next to it.

OrderInput → OrderValidated → PaymentProcessed → OrderConfirmed

Union types constrain what can exist. Immutable. Each transition explicit. Different starting points, similar structures.

The Subject

The resemblance is structural. The difference is grammatical.

// ROP
const archived = archiveCustomer(customer)
// BOP
$becoming(new PatientArrival($vitals))

In ROP, extractActualVisitor(command). In BOP, a PatientArrival encounters a triage protocol and becomes an EmergencyCase.

The ROP workflow is a conductor with a score. In BOP, each being declares #[Be]. Nobody knows the whole.

The Question

ROP asks: did this transformation succeed or fail?

How to handle the error. How to propagate failure. How to compose functions that might fail. A HOW question.

BOP asks: can this exist at all?

An Email doesn’t get validated and produce Result<Email, Error>. It exists, or it doesn’t. There is no error track — there is no track. Semantic variables define a world where invalid values cannot be. A WHETHER question.

From this shift in question, self-proving existence, self-determined relations, and choreography all follow.

Accumulation

ROP solved a real problem.

BOP doesn’t solve that problem. It moves where the question is.

The two look at the same landscape from different elevations. From one, you see tracks and switches. From the other, the trains were never separate from the rails.