Skip to content

Latest commit

 

History

History
475 lines (306 loc) · 17.3 KB

index.md

File metadata and controls

475 lines (306 loc) · 17.3 KB
section status
About
released
<style scoped> .cols-2 { display: flex; flex-wrap: wrap; } .cols-2 > * { width: 100%; } @media (min-width: 640px) { .cols-2 { gap: 1em; } .cols-2 > * { flex: 1; width: calc(100% / 2); } } </style>

About CAP

The SAP Cloud Application Programming Model (CAP) is a framework of languages, libraries, and tools for building enterprise-grade services and applications. It guides developers along a 'golden path' of 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, we focus on accelerated development and safeguarding investments in a world of rapidly changing cloud technologies.


Overview & Design Principles {#overview}

The CAP framework features a mix of proven and broadly adopted open-source and SAP technologies, as highlighted in the figure below.

The graphic is explained in the accompanying text.

Node.js logo Express logo Java logo spring logo
<style scoped> #logos img { display:inline-block; margin: 12px;align-items:center;vertical-align:middle } </style>

On top of open source technologies, CAP mainly adds:

  • Core Data Services (CDS) as our universal modeling language for both domain models and service definitions.

  • Service SDKs and runtimes for Node.js and Java, offering libraries to implement and consume services as well as generic provider implementations serving many requests automatically.

Agnostic Design → Safeguarding Investments {#agnostic-approach}

Keeping pace with a rapidly changing world of cloud technologies and platforms is a major challenge when having to hardwire too many things to today's technologies, which might soon become obsolete. CAP avoids such lock-ins through higher-level concepts and APIs, which abstract low-level platform features and protocols to a large extent. In particular, this applies to things like:

  • Platform-specific deployment approaches and techniques
  • Platform-specific identity providers and authentication strategies
  • On-/Offboarding of tenants in SaaS solutions and tenant isolation
  • Synchronous protocols like REST, OData, or GraphQL
  • Asynchronous channels and brokers like SAP Event Mesh, MQ, or Kafka 1
  • Different database technologies including SQL and NoSQL

These abstractions allow us to quickly adapt to new emerging technologies or platforms, without affecting application code, thus safeguarding your investments.

CAP is Open and Opinionated → Zero Lock-in {#open-and-opinionated}

That might sound like a contradiction, but isn't: While CAP certainly gives opinionated guidance, we do so without sacrificing openness and flexibility. At the end of the day, you stay in control of which tools or technologies to choose, or which architecture patterns to follow as depicted in the table below.

CAP is Opinionated in... CAP is Open as...
Higher-level concepts and APIs abstracting from and avoiding lock-ins to low-level platform features and protocols All abstractions follow a glass-box pattern that allows unrestricted access to lower-level things, if required
Best Practices served out of the box with generic solutions for many recurring tasks You can always handle things your way in custom handlers, decide whether to adopt CQRS or Event Sourcing, for example ... while CAP simply tries to get the tedious tasks out of your way.
Out-of-the-box support for
SAP Fiori and SAP HANA
You can also choose other UI technologies, like Vue.js, or databases, by providing new database integrations.
Dedicated tools support provided in SAP Business Application Studio or Visual Studio Code. CAP doesn't depend on those tools. Everything in CAP can be done using the @sap/cds-dk CLI and any editor or IDE of your choice.

Key Concepts & Paradigms

The following sections highlight key concepts of CAP, which are based on two major paradigms: A declarative paradigm using CDS to capture knowledge about problem domains, and a service-centric paradigm, with ubiquitous notions of Services, Events, and Queries.

Focus on Domain, Powered by CDS {#domain-modeling}

CAP places primary focus on domain, by capturing domain knowledge and intent instead of imperative coding — that means, What, not How — thereby promoting:

  • Close collaboration of developers and domain experts in domain modeling.
  • Out-of-the-box implementations for best practices and recurring tasks.
  • Platform-agnostic approach to avoid lock-ins, hence protecting investments.

The figure below illustrates the prevalent use of CDS models (in the left column), which fuel generic runtimes, like the CAP service runtimes or databases.

CDS models are used to define domain models, service models and UI markup. You can add custom code on top of them. Anatomy of a Typical Application{.caption}


Core Data Services (CDS)

CDS is our universal modeling language to capture static, as well as behavioral aspects of problem domains in conceptual, concise, and comprehensible ways, and hence serves as the very backbone of CAP.


Domain Models in CDS
entity Books : cuid {
  title  : localized String;
  author : Association to Authors;
}

entity Orders : cuid, managed {
  descr : String;
  Items : Composition of many {
    book : Association to Books;
    quantity : Integer;
  }
}

Domain Models capture static aspects of problem domains as well-known entity-relationship models.

Associations capture relationships. Compositions extend that to easily model document structures.

Annotations allow enriching models with additional metadata, such as for UIs, Validations, Input Validation or Authorization.

CDS Aspects & Mixins
// Separation of Concerns
extend Books with @restrict: [
  { grant:'WRITE', to:'admin' }
];

// Verticalization
extend Books with {
  ISBN : String
};

// Customization
extend Orders with {
  customer_specific : String
};

Aspects allow to flexibly extend models in same or separate modules, packages, or projects; at design time or dynamically at runtime.

This greatly promotes adaptability in verticalization and customization scenarios, especially in SaaS solutions.

Moreover, that fosters separation of concerns, for example to keep domain models clean and comprehensible, by factoring out technical concerns.

Proven Best Practices, Served Out of the Box {#generic-providers label='Proven Best Practices'}

The CAP runtimes in Node.js and Java provide many generic implementations for recurring tasks and best practices, distilled from proven SAP applications. Benefits are significantly accelerated development, minimized boilerplate code, as well as increased quality through single points to fix and optimize.

Following is an excerpt of generic features provided:

Automatically Serving Requests
Handling Recurring Tasks
Enterprise Best Practices

See also the Features Overview{.learn-more}

Dynamic Querying & Views {#querying}

All data access in CAP is through dynamic queries, which allows clients to request the exact information they really need. These powerful intrinsic querying capabilities are key enablers for serving requests automatically.

Note: The querying-based approach to process data is in strong contrast to Object-Relational Mapping (→ see also Related Concepts: CAP != ORM)


Core Query Language (CQL)

CQL is CDS's advanced query language. It enhances standard SQL with elements to easily query deeply nested object graphs and document structures. For example, here's a query in CQL:

SELECT ID, addresses.country.name from Employees

... and the same in plain SQL:

SELECT Employees.ID, Countries.name FROM Employees
 LEFT JOIN Addresses ON Addresses.emp_ID=Employees.ID
 LEFT JOIN Countries AS Countries ON Addresses.country_ID = Countries.ID

Queries as first-order Objects (CQN)
// In JavaScript code
orders = await SELECT.from (Orders, o=>{
  o.ID, o.descr, o.Items (oi=>{
    oi.book.title, oi.quantity
  })
})
// Via OData
GET .../Orders?$select=ID,descr
$expand=Items(
  $select=book/title,quantity
)

Queries are first-order objects – using CQN as a plain object notation – sent to local services directly, to remote services through protocols like OData or GraphQL, or to database services, which translate them to native database queries for optimized execution with late materialization.

Projections at Design Time
// Projections in CDS
service OrdersService {
  define entity OrderDetails
  as select from Orders {
     ID, descr, Items
  }
}

We also use CQL in CDS to declare de-normalized views on the underlying domain model, such as in tailored service APIs.

Services & Events {#services}

All behavioral aspects in CAP are based on ubiquitous notions of Services and Events, as expressed in this manifest:

  1. All active things are Services — local ones, remote ones, as well as databases
  2. Services are declared in CDS — reflected and used in generic service providers
  3. Services provide uniform APIs — consumed by other services or frontends
  4. Services react on Events — covering synchronous and asynchronous APIs
  5. Services consume other Services — in event handler implementations
  6. All data is passive — that is, without its own behavior, adhering to REST

Services in CAP are stateless and with a minimal footprint, which allows you to modularize solutions into single-purposed (nano) services or functions-as-a-service.

Hexagonal Architecture à la CAP



Service Definitions in CDS
// Service Definition in CDS
service OrdersService {
  entity Orders as projection on my.Orders;
  action cancelOrder (ID:Orders.ID);
  event orderCanceled : { ID:Orders.ID }
}

Services are declared in CDS models, used to serve requests automatically. They embody the behavioral aspects of a domain in terms of exposed entities, actions, and events.

Uniform Consumption
// Consumption in JavaScript
let srv = cds.connect.to('OrdersService')
let { Orders } = srv.entities
order = await SELECT.one.from (Orders)
  .where({ ID:4711 })
srv.cancelOrder (order.ID)
// Consumption via REST APIs
GET /orders/Orders/4711
POST /orders/cancelOrder/4711

Every active thing in CAP is a service, including local services or remote ones — even databases are represented as services.

All services provide a uniform API for programmatic consumption. Thus, application code stays agnostic to underlying protocols.

::: tip Late-cut µ services This protocol-agnostic API allows mocking remote services, as well as late changes to service topologies, for example, co-locating services in a single process or deploying them to separate micro services later on. :::


Ubiquitous Events {#events}
// Service Implementation
cds.service.impl (function(){
  this.on ('UPDATE','Orders', (req)=>{})
  this.on ('cancelOrder', (req)=>{})
})


// Emitting Events
// e.g. in this.on ('cancelOrder', ...)
let { ID } = req.data
this.emit ('orderCancelled', {ID})


// Subscribing to Events
let srv = cds.connect.to('OrdersService')
srv.on ('orderCancelled', (msg)=>{})

Everything in CAP happens in response to events. CAP features a ubiquitous notion of events, which represent both, requests coming in through synchronous APIs, as well as asynchronous event messages, thus blurring the line between both worlds.

We add custom logic in event handlers, registered to implement service operations. In the same way, we subscribe to asynchronous events emitted by other services.

::: tip Domain-level Eventing Instead of talking to message brokers, services in CAP simply emit events on themselves, and consumers subscribe to events from services. Everything else is handled behind the scenes. :::

Jumpstart & Grow-as-you-go {#grow-as-you-go}

Following the principle of convention over configuration, there's no need to set up things upfront. CAP allows you to jumpstart projects within seconds and have a team starting development right away, using generic providers, on top of a lightweight in-memory database → see Getting Started in a Nutshell.

CAP also offers mocks for many platform features, which allow fast dev-test-run cycles with minimal development environment complexity — aka Airplane Mode. Similarly, CAP greatly facilitates integration scenarios by simply importing an API from, say, an SAP S/4 backend or from SAP API Hub and running mocks for this locally.

Over time, you add things gradually, only when they're needed. For example, you can move ahead to running your apps in close-to-productive setups for integration tests and delivery, without any change in models or code. → see Grow-as-you-Go.

Finally, projects are encouraged to parallelize workloads. For example, following a contracts-first approach, a service definition is all that is required to automatically run a full-fledged REST or OData service. So, projects could spawn two teams in parallel: one working on the frontend, while the other one works on the backend part. A third one could start setting up CI/CD and delivery in parallel.

Related Concepts

Learn more how CAP relates to other concepts.{.learn-more}

Features Overview

Get an overview of all features.{.learn-more}

Glossary

Glossary of common terms and abbreviations.{.learn-more}


1 *Kafka* isn't supported out of the box today, but might be added in future.