The “SAP Cloud Application Programming Model” 1 is an open and opinionated, framework of languages, libraries, and tools for building enterprise-grade services and applications. It guides developers through proven best practices and a great wealth of out-of-the-box solutions to recurring tasks.
CAP-based projects benefit from a primary focus on domain, instead of delving into overly technical disciplines, significantly accelerated development, and safeguarded investments in a world of rapidly changing cloud technologies.
1 frequently spelled as “CAP” with a silent ‘M’ — as in here.
CAP features a mix of broadly adopted open-source and SAP technologies. The major building blocks are highlighted below.
Core Data Services (CDS)
CDS is a family of domain-specific languages (CDL, CQL) and corresponding notations (CSN, CQN, CXN). It serves as our ubiquitous modelling language, for example, for capturing domain models and service definitions in a conceptual way, and hence as the very backbone of CAP.
These are libraries for Java and Node.js to provide and consume services through synchronous as well as asynchronous APIs. Based on ubiquitous notions of events and queries, they allow implementing services in protocol-agnostic and platform-agnostic ways.
The SDKs comprise out-of-the-box integration to lower-level platform features services, such as authentication and credential-flows, on/off-boarding of SaaS tenants, etc. All this is concealed behind higher-level abstractions to avoid hard-wiring. Yet all follow a white-box approach, allowing unrestricted access to native features of underlying technologies in case that is required.
Using CAP does not require any specific editor or IDE. All can be done using the [
@sap/cds-dk] command-line interface and any editor or IDE of your choice. On top of that however, there is dedicated support for CAP through SAP Web IDE as well as through plugins to Visual Studio Code and Eclipse, including textual as well as graphical editors.
Following are the key design principles realised in CAP.
Read the headings starting with “CAP is…”
Open & Opinionated
Sounds like a contradiction, but isn’t: While CAP certainly gives opinionated guidance with many out-of-the-box solutions for recurring tasks, we do not sacrifice openness and flexibility. Means: you stay in control of which technologies to choose, which architecture patterns to follow, or which parts of CAP to actually use.
While CAP provides out-of-the-box support for Fiori and HANA, that does not lock you in to these choices. You can always combine CAP-based services with alternative UI or database technologies. CAP’s core components are explicitly designed for you to integrate with alternatives.
CAP does not presume overarching architectures or methodologies. For example, it’s your choice whether to build a classic CRUD application or wether to adopt CQRS or Event Sourcing, while CAP merely tries to get the tedious boilerplate out of your way.
Keeping pace with rapidly changing cloud technologies is a major challenge when you have to hard-wire too many things to today’s technologies, which might be obsolete soon. CAP provides out-of-the-box integration with many essential platform services, concealed behind higher-level APIs, which greatly helps avoiding such lock-ins and hence safeguarding your investments.
The core concepts of CAP, as briefly introduced in the sections below, are:
- Domain Models — to capture the static aspects of your problem domain
- Aspects — for clean models, separation of concerns, verticalization, extensibility
- Services — to capture behavioral aspects; every active thing in CAP is a service
- Events — blurring the line b/w synchronous and asyncrhonous APIs
- Queries — as the ubiquitous key ingredient for serving requests automatically
- Protocols, APIs — for providing and consuming services in a protocol-agnostic way
- The CAP Paradigm — summarizing all and putting it in context
Anatomy and Overview
The figure below illustrates the anatomy of a typical CAP-based application, highlighting the core concepts.
Anatomy of a typical CAP application
Domain Models capture the static aspects of a problem domain as entity-relationship models. With entities and Associations, CDS provides a language that is close to the conceptual thinking of domain experts. Compositions enhance this to document structures. Moreover, Aspects allow to keep domain models clean, concise and comprehensible by factoring out technical concerns.
CDS’s Aspects allow to flexibly extend definitions by new elements as well as overriding properties. This can happen in same or separate files or projects, and greatly promotes both, separation of concerns as well as extensibility, for example in verticalization and customization scenarios.
Every active thing in CAP is a service, including local or remote ones, even databases. Hence, services embody the behavioral aspects of a domain and act as facades to consumers. Service definitions are interpreted by generic providers at runtime to serve requests automatically. All services are configured, implemented and consumed using the same uniform, protocol-agnostic APIs.
Everything what happens at runtime is in response to events. CAP features a ubiquitous notion of events, which represent both, requests coming in via synchronous APIs, as well as asynchronous event messages, thus blurring the line between both worlds. In both cases, custom logic can be provided through event handlers hooked in to respective service providers.
Every data access is expressed and processed thru queries based on CQL (and CQN), which enhances SQL towards graphs and document structures. At design time, queries declare projections, that is views, on underlying entities. At runtime, queries are captured in first-class and first-order objects — that is, they can be passed to services for execution and stacked recursively as queries on queries. These powerful, intrinsic querying capabilities are key to serve requests automatically in generic handlers.
Services can be consumed (inbound) and can themselves consume other services (outbound) via various protocols. Currently supported are OData, plain REST / http and AMQP. Converters are provided to translate CDS service definitions into corresponding OData EDMX v2 and v4, JSON Schema, OpenAPI, and AsyncAPI formats to publish APIs in those formats.
Agnostic Services Design
The CAP Paradigm
CAP is based on two major paradigms: First, the declarative paradigm, that is to capture knowledge about a problem domain declaratively as much as possible in order to automate many tasks in generic, broadly reused implementations. Second, a service-centric paradigm, based on ubiquitous notions and use of Services, Events and Queries.
- Models capture intent — to benefit from generic implementations
- Data is passive — that is, without own behavior, adhering to REST
- Every active thing is a Service — acting as facades to access data
- Service are pure functions — that is, without own state
- Services react on Events — featuring synchronous and asynchronous APIs
- Querying is key! — both, to express projections as well as to access data
CAP != ORM
Note that these principles are by intent very much in contrast to frameworks applying forms of object-relational mapping, based on the notion of active objects modifying internal state, hence side effects. Moreover, querying is in strong contrast to procedural and imperative approaches to access and process data, frequently found in several persistence frameworks.
Following are the qualities and approaches of CAP, which facilitate this:
Focus on your Domain → “What, not how!”
CAP is based on a declarative paradigm, which is about placing a project’s primary focus on domain knowledge and intent, instead of imperative coding. CAP-based projects use CDS to capture static as well as behavioral aspects of a problem domain on conceptual levels, in concise, and comprehensible ways. This promotes close collaboration between developers and domain experts to gradually refine domain knowledge.
Focus on your Domain
Evolutionary Development → “Grow-as-you-go…“
Following the principle of convention over configuration, there’s no need to set up things upfront. Instead, they can be added gradually over time when needed. In addition, CAP provides lightweight stand-ins for essential platform features, which allows fast dev-test-run cycles with minimal complexity of developer landscapes by running lightweight yet fully fledged servers. Later on, you move ahead to running your apps in close-to-productive setups for integration tests and delivery, without any change in models or code.
Generic Runtimes → “Turnkey Development”
Given the declarative information in models, CAP runtimes can quickly run a lightweight server in a jump-start fashion, as well as automate many tedious tasks, such as serving CRUD requests, validating input, etc. This minimizes boilerplate code you’d otherwise have to write. This not only speeds up development, but also increases quality as the generic implementation provide single points to fix and optimize as well as taking about all the usual nonfunctional requirements, such as supportability, extensibility, etc.
Contracts First → Parallelizing Tasks
As all you need to run a service is a service definition, projects containing UIs should start with the service definitions and then spawn two teams working in parallel, one working on the frontend, the other one on the backend part. Both using the service definitions as their interface contracts, collaborating in closed loops to refine them iteratively.
Agnostic Services → ‘Late-cut Micro Services’
CAP promotes a service-oriented paradigm with single-purposed services, which can later on be deployed and run as separate micro services. However, you can always decide to alternatively run them embedded in a single-server process, avoiding the efforts and costs for actual micro service DevOps, at least in the early phases of development.