This article applies Dave Snowden's Cynefin framework to distinguish between 'Complicated' and 'Complex' problems in software development, particularly in the context of AI coding tools. It argues that while AI tools excel at Complicated tasks like writing functions, they fall short in addressing the emergent 'Complex' challenges of system coherence and interaction. Understanding this distinction is crucial for architects and developers to leverage AI effectively and navigate system evolution.
Read original on Dev.to #architectureThe Cynefin framework helps classify problems based on the nature of cause and effect. In system design, it's vital to differentiate between Complicated and Complex problems, as they require fundamentally different approaches.
The article highlights that current AI-dev tooling, such as Agent Skills, Superpowers, and spec-driven development kits, are highly effective in the Complicated domain. They make individual tasks (units of work) more reliable, repeatable, and verifiable by packaging procedural knowledge, enforcing rigorous processes, and ensuring adherence to specifications.
The Overclaim Trap
It is a significant mistake to assume that making individual units of work perfectly reliable (Complicated domain) will automatically lead to a coherent and correct overall system (Complex domain). System coherence is an emergent property of interactions, not merely the sum of perfectly executed isolated tasks. A system can be incoherent even if every individual component adheres perfectly to its specifications.
Issues like mismatched field names (e.g., `userId` vs. `user_id`), conflicting retry/timeout policies, or interdependent refactors often arise from the Complex domain. These are not caught by per-task discipline because each task was 'done right' in isolation. Integration failures are often emergent, not deducible from individual components or even large context windows.
For Complex problems, the methodology shifts from 'analyze, then execute' to 'probe, sense, respond'. This involves active integration, deployment, and monitoring under real load to observe emergent behaviors. Integration and property-based tests become crucial instrumentation to sharpen sensing, rather than exhaustive upfront checks that presume foreknowledge of all failure modes.