The Computing Series

Tradeoffs

AT3 — Simplicity vs. Flexibility

Four operators: AND, OR, NOT, XOR. This is a minimal, complete set. In fact, AND and NOT alone are functionally complete — every possible boolean function can be expressed using only AND and NOT. NAND (NOT AND) is also functionally complete by itself. Hardware designers use NAND gates extensively because NAND is cheap to fabricate and expressive enough to build everything else.

The simplicity is the point. Four operators. Fixed truth tables. No ambiguity. The cost of this simplicity is that complex real-world conditions require verbose expressions.

“Allow access if the user is an admin, or if they own the resource and either the resource is public or they have an explicit grant, but not if their account is suspended regardless of ownership.”

This translates to:

def can_access(user: User, resource: Resource) -> bool:
    # Atomic statements
    is_admin = user.role == "admin"
    owns_resource = resource.owner_id == user.id
    resource_is_public = resource.visibility == "public"
    has_explicit_grant = user.id in resource.explicit_grants
    is_suspended = user.account_status == "suspended"

    # Compound statement: access rule
    base_access = is_admin or (owns_resource and (resource_is_public or has_explicit_grant))

    # Override: suspension blocks all access
    return base_access and not is_suspended

The verbosity is intentional. Each named variable is an atomic statement. The compound statement is built from named parts. The structure is readable, testable, and debuggable. The alternative — one long inline expression — is flexible (fewer lines) but less simple to reason about. AT3 applies: the named-variable approach favors simplicity of reasoning; the inline approach favors brevity.


Read in the book →