LAB#05: Implementing Zone Access Control Logic
π― Learning Objectives
- Understand different approaches to implementing complex business logic
- Practice breaking down a decision tree into clean, maintainable code
- Compare trade-offs between code styles (readability, testability, maintainability)
- Learn how to separate business logic from UI in a React Native app
π Scenario
You are building a wristband access control system for a large venue (festival, conference, stadium, etc.).
When a wristband is scanned at a checkpoint, the system must decide whether to GRANT or DENY access based on the flowchart provided.
Files:
ZONE_ACCESS-flow.pngβ Complete flowchart: flowchart: image- flowchart: txt
π The Four Approaches
You will implement the same logic using four different styles:
- Nested If/Else (Simple but messy)
- Composable Pure Functions (Focused, testable functions.)
- Declarative Rules Array (Policy-based)
- State Machine (Conceptual / XState style)
π Requirements
Create a function evaluateWristbandAccess(wristband, checkpoint) that returns:
type AccessResult = {
granted: boolean;
code: string;
message: string;
metadata?: Record<string, any>;
};Core Rules (from flowchart):
- If
checkpoint.direction === 'OUT'β Always GRANTED - If
direction === 'IN':- Check if
wristband.typeis incheckpoint.allowedTypes - If not β
TYPE_NOT_ALLOWED - If yes β Check Bypass Policy
- If bypass active β GRANTED
- Else β Check Zone Config
- If no config β
ZONE_CONFIG_MISSING - If
enterPermission === falseβNO_PERMISSION - Else β Check Capacity
- If full β
CAPACITY_FULL - Else β GRANTED
- If full β
- If no config β
- Check if
π οΈ Exercise Tasks
Task 1: Nested If/Else Approach
Goal: Implement the logic using nested if/else statements.
Clues:
- Start with the direction check (early exit)
- Be careful with indentation
- Try to avoid deep nesting where possible
Task 2: Composable Pure Functions
Goal: Break the logic into small, focused, testable functions.
Clues:
- Create helper functions like:
isExit(checkpoint)isTypeAllowed(wristband, allowedTypes)hasActiveBypass(wristband)getZoneConfig(zoneId)(async)isCapacityAvailable(config)
- Build a clean
evaluateAccessorchestrator that calls them in sequence - Each function should do one thing
Task 3: Declarative Rules Array
Goal: Create a list of rules that are evaluated in order.
Clues:
const rules = [
{
condition: (w, c) => c.direction === 'OUT',
result: () => ({ granted: true, code: 'GRANTED', message: 'Exit allowed' })
},
// ... more rules
];- Rules are evaluated from top to bottom (first match wins)
- Good for non-developers to understand
Task 4: State Machine Style
Goal: Model the flowchart as a state machine (conceptual or using XState).
Clues:
- States could be:
scanned,checkingDirection,checkingType,checkingBypass,checkingCapacity,granted,denied - Transitions based on conditions
- Excellent for complex flows with side effects
π Deliverables
For each approach, create a file:
approach-1-nested.jsapproach-2-composable.jsapproach-3-declarative.jsapproach-4-state-machine.js
Include:
- The implementation
- A short comment at the top explaining pros & cons
- At least 2 unit tests per approach (using Jest)
π‘ Bonus Challenges
- Add proper TypeScript types
- Make the logic fully async (simulate network calls for zone config and capacity)
- Add audit logging for every decision
- Create a React Native component that uses your favorite approach
- Implement error handling (network failure β fail closed)
π Evaluation Criteria
- Correctness (matches flowchart)
- Code readability & organization
- Separation of concerns
- Test coverage
- Comments & explanations
π Starter Template
// approach-2-composable.js
function isExit(checkpoint) {
// your code
}
function isTypeAllowed(wristband, allowedTypes) {
// your code
}
// ... more helpers
async function evaluateWristbandAccess(wristband, checkpoint) {
// orchestrator
}Good luck!
Think about:
- Which approach feels easiest to test and debug?
- Which approach feels easiest to maintain and understand?
- Which one would be easiest to scale and add new features?
- Which one would be easiest for a non-developer to review?
- Which one would you choose for a real production app? Why?