Skip to content
Search lessons, topics, tests…
Esc

    ↑ ↓ moveEnter openEsc close

    Module 1 · Ownership, Ordering and Failure · Lesson 1 of 2

    Observer: Independent Notifications and Subscription Lifetimes

    Watch

    Start with the relationship

    A sensor dashboard receives a new temperature reading. A chart redraws, a logger records the value, and an alert panel evaluates its own threshold. The source should not know each concrete screen. Observer fits when these reactions are independent and additional subscribers can join or leave. It is not a substitute for a sequence whose steps depend on one another.

    Define the payload and lifetime

    An example reading contains a sensor identifier, measurement time, numeric value and unit. Decide whether the timestamp means measurement time or receipt time. A value of 30 without a unit is not an adequate contract. Treat the payload as a fact, not a command to perform an unrelated business action.

    In the .NET observable interfaces, subscription returns an IDisposable handle. The consumer should own that handle and dispose it when the screen closes. The observable contract does not specify observer notification order. These lifecycle and ordering points are documented in Microsoft Learn.

    A useful lifecycle test is: open a screen, subscribe, receive one update, close the screen, publish another update, and confirm the closed screen does not react. Repeat opening and closing to catch duplicate subscriptions. A test that only verifies the first notification misses the common retention and duplicate-handler problems.

    Separate the pattern from delivery guarantees

    QuestionDecision to make
    Must every sample be retained?Choose storage or a durable delivery mechanism explicitly.
    May a slow chart delay the producer?State synchronous versus queued delivery and bounded-buffer behavior.
    Does one handler failing affect others?Define, observe and test failure propagation.
    Must one subscriber run before another?Move that dependency into an explicit workflow.

    Naming the design Observer does not answer these questions. A chart may legitimately show only the latest reading, whereas an audit recorder may require every accepted sample. Those requirements can justify different delivery paths rather than one overloaded event bus.

    Worked design exercise

    A chart needs the latest value, an audit log needs all accepted readings, and a billing operation must happen only after persistence. Should three interchangeable subscribers handle all three?

    A stronger design persists the accepted reading under an explicit contract, then exposes the appropriate notifications. Billing is a dependent workflow step with duplicate protection, not an incidental subscriber whose position in a registration list happens to work. The chart can remain an independent observer. Document what happens if persistence succeeds but later notification fails.

    Interview check

    Explain one invariant, one lifetime boundary and one failure case before naming a library. If there is one fixed collaborator and no independent subscription need, a direct call can be clearer.

    Continue with the coordinator lesson, then try the six-scenario workbook.

    Terminal signals and concurrent lifetimes

    IObservable<T> describes push notifications: OnNext supplies a value; OnCompleted or OnError ends that subscription's sequence. Do not continue sending values to the same observer after a terminal signal. A later subscription is a separate interaction whose behavior the provider must define. OnError is a provider notification, not automatic isolation of arbitrary exceptions thrown by a subscriber.

    With concurrent producers or a callback already in flight, disposal is not a universal promise that no callback can finish after it returns. Define serialization and disposal behavior for the implementation. Keep subscriber state thread-safe where needed, and arrange lifecycle tests with explicit synchronization rather than sleeps. For a simple single-threaded source, closing the screen before the next publish should prevent that later update.

    See Microsoft Observer best practices for terminal signals, error handling, ordering and subscription concurrency.

    Video companion

    Dev Leader: Mastering the Observer Pattern with System.Reactive in C#, by Nick Cosentino (2023), introduces observables and filtered or transformed reactions. Use it for the relationship and Rx vocabulary, then identify who owns each returned IDisposable in this lesson. The creator companion tutorial is also available.

    The walkthrough does not establish a production subscription-lifetime policy or a current package baseline. Rx does not by itself give durable delivery, cross-observer ordering or a booking transaction. Adapt APIs to your chosen .NET and System.Reactive versions.

    A building notice service

    The building publishes a notice that the lobby temperature changed. A wall display redraws, a caretaker records it, and an alert panel checks its own threshold. Each signs up independently. A display removed from the building also cancels its subscription; the building does not shut down because one display leaves.

    The source is the publisher, each recipient is an observer, and the cancellation receipt is the owned subscription handle. The message must include the sensor, time, value and unit.

    Where the analogy stops

    Real software callbacks may run synchronously and can delay or fail the publisher. A mailing-list analogy does not imply a queue, replay, thread safety, failure isolation or guaranteed delivery. If the caretaker must first store a reading before billing can run, put that dependency in an explicit workflow. It is no longer merely two independent recipients.

    Observer cheat sheet

    DecisionUseful rule
    FitOne source; independently attachable reactions to a fact
    PayloadIdentify source, measurement time, unit and meaning; prefer stable value snapshots
    OwnershipRetain and dispose the subscription you own; do not dispose a shared provider
    OrderingIObservable does not guarantee order among observers
    DeliveryChoose synchronous or queued behavior; specify bounded capacity and overflow
    RetentionLatest-only charts and retain-every-sample audits need different contracts
    FailureDecide fail-fast versus isolation; observe errors; do not silently swallow them
    TerminationOnCompleted or OnError ends the current subscription sequence
    ConcurrencyDefine callback serialization, reentrancy and disposal behavior
    SimplicityPrefer a direct call when only one fixed collaborator is needed

    Four tests worth explaining

    1. Open, subscribe, publish, close, publish again; then reopen and check for duplicate handlers.
    2. Make one subscriber throw and verify the documented effect on other subscribers.
    3. Make one subscriber slow and verify the backpressure or overflow policy.
    4. Introduce a required persistence-before-billing dependency and show its explicit owner.

    These are design and test-planning checks, not a claim that an implementation was executed.

    Practice

    Sign in to mark lessons done and keep your place in the course.Sign in