Concept design and software development

Who concept design can help

Concept design is a tool that can help people create software, whatever their role:

  • For software engineers, architects and programmers, concept design offers a way to structure complex functions and move easily to clean and maintainable code.
  • For product managers and user experience designers, concept design offers a way to express and analyze user interactions at a high level.
  • For CTOs, chief architects and VPs of engineering, concept design offers visibility into complex projects and a way to chart directions, focus effort and foster collaboration across teams.
  • For sales, marketing and legal, concept design offers a shorter path to grasping the key features of each product and the value that it brings.

How concept design helps

Concept design helps you make software better, and make better software.

  • Clarifying functionality. As Fred Brooks noted in his influential No Silver Bullet article, the hardest part of software development is deciding what the software should do. Concept design helps you do this by giving you a precise and lightweight language for expressing behavior that is unencumbered by implementation (and user interface) details.
  • Separating of concerns. Concept design helps you tease apart the different concerns in a design, so you can work on them independently. This is essential for division of labor. The separation of concerns in the design becomes modularity in the code.
  • Reusing designs and code. Structuring functionality as concepts exposes more opportunities for reuse. Concepts become reusable patterns that carry design knowledge, including knowledge about issues that come up in the context of use. By reusing concepts at the design level, you can reduce costs (by avoiding rework) and reduce risk (by adopting solutions with known properties). By reusing concepts at the implementation level, you can reducing coding costs and improve reliability.
  • Factoring out novelty. Concept design separates general-purpose and familiar aspects of behavior cleanly from application-specific ones. Often the majority of a design can be based on familiar concepts, and highlighting the new or modified concepts while just naming the reused concepts accelerates the design process.
  • Aligning across roles. One of the biggest challenges in software development is that people in different roles speak different technical languages. On the UX side, people communicate with wireframes and user flows, but on the engineering side, they draw box-and-line diagrams such as entity-relationship and component models. Concept design offers a language that can be shared across roles, because it addresses the fundamental concern that everyone has (of what the behavior of the product is, and why) without infringing on the specialized concerns that are relevant only to some roles (eg, the user interface details that are not relevant to engineering, and the architectural details that are not relevant to UX).
  • Aligning across teams. In addition to alignment across roles, concepts also help to align across teams. Teams need to be able to work independently, but it's become increasingly important to align designs around shared concepts, because of cloud integration and because of users expectations that the same functionality will work in the same way in all the products in a product suite.
  • Aligning functionality with users. Making better software means aligning functionality with the needs of users and providing a compelling and simple mental model. Concepts are what users need to understand to use a product, and by designing the concepts first (and by using familiar concepts when possible), you can ensure a strong alignment between the user's mental model of the software and how the software actually behaves.
  • Eliminating friction. Software should be not just usable but a delight to use. This is achieved not by adding frills but by eliminating the friction that frustrates users and that limits the product's market potential. Concept design helps you reduce friction by simplifying the behavior and minimizing the steps the user needs to perform.

How concept design amplifies AI tools

AI is having a big impact on software development. Concept design amplifies the power of AI tools in several ways.

  • Making behavior explicit. Making behavior explicit is key to communicating designs not only with people but also with agents. Concept design gives you a simple and effective way to record the behavior -- what you want the software to do -- which you can then give to an AI agent to analyze your design, explore alternatives, generate code, etc. Concept designs are free of implementation details, and independent of any particular platform or AI agent.
  • Making code modular. Concept design leads naturally to extremely modular codebases, with each concept realized as a module that has no dependencies on any other concept. This limits the impact of changes, and makes it easier to know where to make a change. The result is that AI agents are less prone to breaking old functions when they add new ones, and any technical debt due to lower quality AI coding is contained and does not corrupt the system structure.
  • Making code legible. Concept design leads to code that is more legible in the sense that its elements map directly to the observed behavior: what you see is what it does. Concept structuring does not require the kinds of coding patterns (factories, callbacks, dependence injection) that rely on indirection and that make code harder to understand and reason about. Concepts map naturally to activities in the domain, and actions map to steps taken by users. This legibility results in more reliable agentic coding, and makes it easier to understand generated code and ensure that it works as expected.

The mindset shift of concept design

Concept design calls for a shift in mindset in three key respects.

  • A new language of discourse. To describe software functionality, concept design offers a language of behavior in which actions that involve individuals cause changes in facts. Software designs are more conventionally described either in terms of user interfaces (with wireframes and user journeys that involve clicking buttons and navigating through screens) or in terms of implementation (with code components, or objects and classes that have no correspondence to the problem domain).
  • A new way to structure function. Much of the history of software engineering involves attempts to achieve better separation of concerns and modularity. Concept design provides a new approach that builds on two well-established ideas: event-driven programming and view separation. Event-driven programming is the idea that modules aren't coordinated by having one call another, but instead by writing external rules that cause modules to react to events. By using event rules as the sole form of composition, concept design allows functionality to be broken into modules that have no mutual dependencies whatsoever. View separation is the idea that functionality can be broken into distinct views each with its own states and actions, tracking different attributes of the same individuals. By using view separation, concept design lets you disentangle the behaviors associated with individuals, makes modules more cohesive and avoids the conflation of different aspects that should be kept separate.
  • A new emphasis on purpose. Designers have long recognized how helpful it is to ask not only what a product should be but also why. Concept design challenges designers to find motivations not just for the product as a whole but for each individual concept, asking what would go wrong if it were omitted, and what purpose it serves.
  • A drive for simplicity. As Tony Hoare put it, there are two ways of constructing a software design: "One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies." It may seem naive to imagine that a simple design can deliver rich functionality in a complex domain. But, as Hoare realized, there is no viable alternative, because the cost of complexity is unsustainable. Simplicity can be achieved by a combination of technique and attitude. Concept design offers the technique: breaking a complex system down into simple parts, and expressing them clearly and directly, so that even if the aggregate behavior is complex, the parts can be easily understood. You bring the attitude: an unrelenting insistence on the utmost clarity, and a willingness to stop tolerating incomplete understanding.

How concept design compares to other approaches

Concept design builds on some of the most successful innovations in software development:

  • Relational state. From relational databases (and entity-relationship modeling), formal specification languages (notably Alloy, B and Z), and knowledge graphs, concept design takes the idea of representing states with relations between the identities of individuals.
  • Actions. From formal specification languages, transaction theory and process algebras, concept design takes the idea of representing the behavior of a system in terms of sequences of action occurrences.
  • Pre/post conditions. From formal specification languages and program verification, concept design takes the idea of defining the effect of actions on states as preconditions (or more correctly firing conditions) that say in which states an action can occur and postconditions that say what states result afterwards.
  • Granular services. From microservices, concept design takes the idea of structuring a system as a collection of services that run independently, each holding the state and handling all the behavior associated with some aspect of functionality.
  • View separation. From approaches such as entity-component structuring, subject-oriented programming and aspect-oriented programming, concept design takes the idea of allowing the same individuals to have different attributes and behaviors in different behavioral views.
  • Event-driven programming. From architectural patterns such as publish-subscribe and event bus systems, concept design takes the idea of composing concepts by writing event rules, external to the concepts, that coordinate the concept behaviors without introducing any explicit dependencies between them.

Concept design differs in some important ways from other approaches:

  • Object-oriented design. Object-oriented design advocates organizing functionality around objects in the problem domain. For example, you would identify the class of users, and then associate with it functionality that involves users such as authenticating, friending and subscribing. This leads to conflation in which the same object holds unrelated functionality. In concept design, functionality is organized instead around distinct activities and their purposes, for example into Authenticating (identifying users), Friending (connecting users for sharing updates), and Subscribing (recording service subscriptions). Concept design can be implemented in object-oriented languages, but objects are not the key organizing principle.
  • Domain-driven design. Domain-driven design recommends that each team work within a bounded context, defining their own language and data models. Cross-team integration then requires explicit translations between contexts. Concept design instead encourages teams to define shared concepts for shared functionality (to prevent inconsistencies and needless rework), and to base concept states on the identities of individuals and not on object-oriented class definitions, which make it hard to translate across contexts. Concept design gives modular structure to functionality within different domains, while in domain-driven design each domain has a single monolithic data model. Also, domain-driven design focuses on data models, while concept design provides actions to go beyond state to behavior.
  • Publish-subscribe systems. Event-driven architectures are usually based on modules publishing some events and subscribing to others. An event bus then listens for published events and calls the functions registered by subscribers. This offers decoupling by avoiding direct calls, but there is still a dependency if the subscribing module must name the events it subscribes to. And because modules can typically publish and subscribe dynamically, it can be hard to figure out which subscriptions are active. Concept design avoids these problems, because the events in one concept that trigger events in another are just occurrences of the concept's actions, and the code that determines which action causes which other is written in declarative rules, externally to the concepts, making it easy to see at a glance how concepts are coordinated.
  • Agile development. Agile practices have had some positive impacts by encouraging more incremental development focused on delivering value to users. But with the advent of AI-based coding, some key principles of agile development are inappropriate. In particular, agile development disparages design upfront, and suggests that code be the source of truth. Concept design turns this on its head: design is primary, and is where most effort should be invested, and code is a secondary form, often generated automatically by translation from the design.
  • Design thinking. Design thinking is a process for design that prescribes a series of steps from problem framing to detailed design. It incorporates some practices that professional designers commonly use, most notably an emphasis on iteration and early prototyping, and sustained attention to the needs of users. In other respects, however, in its attempt to democratize design and make design accessible to those without any design background, it moves away from professional practice. Some advocates of design thinking argue that because designs are made for people, the main skill called for is understanding human behavior and psychology. In practice, this tends to devalue discipline-specific expertise, and design thinking workshops often encourage the idea that a lack of familiarity with prior designs leads to more creative solutions. Concept design, in contrast, places considerable weight on the value of reusing concepts that embody vital design knowledge, and innovating only when existing and well understood solutions fail. And unlike design thinking which is focused on the design process rather than the design artifacts, concept design attempts to offer a language for designing, and way to structure a complex design as a composition of simpler parts.