Blog SAPienteSAPiente
CAPRAP

Diferenças e Semelhanças entre CAP e RAP

SAPiente6 de ago. de 2026· 11 min read

Duas línguas da mesma família

Você abre um projeto CAP pela primeira vez e encontra isto:

using { cuid, managed } from '@sap/cds/common';

entity Books : cuid, managed {
  title  : localized String;
  author : Association to Authors;
}

Parece CDS. É CDS — mas não é o seu CDS. Cadê o define view entity as select from? Cadê a tabela transparente por baixo? O que são esses dois nomes depois dos dois-pontos? E localized na frente do tipo?

A confusão tem raiz histórica: ABAP CDS e o CDS do CAP são dialetos irmãos da mesma ideia (Core Data Services como linguagem declarativa de modelos), mas evoluíram para mundos com premissas diferentes. No ABAP, o CDS nasceu em cima de um dicionário de dados que já existia há 30 anos — toda view aponta para algo. No CAP, o CDS é a origem de tudo: das entidades nasce o schema do banco, o serviço OData e até a tipagem do código. Este post é o guia de tradução — o que muda, o que engana e o que o ABAPista ganha de graça do outro lado.

Primeiro, os nomes: CDS, CDL e CSN

No capire (a documentação oficial do CAP), CDS é o termo guarda-chuva. A linguagem legível que você escreve nos arquivos .cds chama-se CDL — Conceptual Definition Language, descrita como "um derivado conciso e mais expressivo do SQL DDL". E o que o compilador produz é CSN (Core Schema Notation): uma notação JSON dos modelos, consumida pelos runtimes.

E aqui vem o primeiro choque cultural: não existe ativação. Nada de DDIC, nada de "objeto ativo/inativo", nada de SE11. Você salva o arquivo, o cds watch recompila em memória e o servidor já serve o modelo novo. O cds compile --to csn mostra o resultado; o cds deploy gera o schema no banco. O ciclo editar-ativar-testar do ABAP vira editar-salvar-pronto.

A tabela de tradução

No ABAP CDS / DDIC

No CDL do CAP

A diferença que importa

Tabela transparente (SE11/ADT) + view entity por cima

entity

A entity É a persistência — o schema do banco é gerado dela; não há camada DDIC separada

define view entity ... as select from

entity X as projection on Y (dentro de um service)

Projeção existe, mas é a exceção (camada de serviço), não a regra

Data element / domínio

type

type Amount { value : Decimal(10,3); currency : Currency; } — types podem ser estruturados

include de estrutura / interface view

aspect (mixin via :)

Herança múltipla componível: entity Books : cuid, managed { }

Abstract entity (tipos, payloads)

aspect / type

⚠️ abstract entity existe no CAP mas é deprecated — detalhes abaixo

Associação com on $projection.campo = _Assoc.campo

Association to Authors (managed)

Sem on-condition: a foreign key é gerada automaticamente

composition / association to parent

Composition of many ... on ...$self

Mesma semântica de documento; backlink via $self

Metadata extension (arquivo separado de anotações)

Diretiva annotate em outro .cds

Mesma filosofia de separar anotação de modelo — aqui, para qualquer coisa

Extension include / BDEF extension

Diretiva extend

Qualquer um estende qualquer definição — inclusive as do @sap/cds/common

DCL (access control)

@requires / @restrict

Autorização declarada por anotação no modelo (e por default nada é autorizado!)

Service definition + service binding

service NomeDoServico { ... }

Uma construção da própria linguagem; os protocol adapters servem OData automaticamente

@EndUserText.label, @Semantics.*, @AbapCatalog.*

@title, @Common.*, @UI.*...

Vocabulários diferentes; @AbapCatalog não tem equivalente — não há catálogo ABAP

Choque cultural nº 1: a entity é a tabela

No ABAP, o caminho é tabela → view básica → view de composição → projeção. No CAP, você declara a entity no domain model (por convenção, na pasta db/) e ela vira tabela no deploy — HANA, SQLite, PostgreSQL, tanto faz, o compilador gera o DDL de cada banco. A "camada de views" do VDM não existe como obrigação: o que existe é o service expondo projeções do domínio:

// db/schema.cds — o domínio (vira tabela)
namespace sapiente.bookshop;
using { cuid, managed } from '@sap/cds/common';

entity Books : cuid, managed {
  title  : String(111);
  stock  : Integer;
  author : Association to Authors;
}

entity Authors : cuid {
  name  : String;
  books : Association to many Books on books.author = $self;
}
// srv/cat-service.cds — a camada de serviço (vira OData)
using { sapiente.bookshop as db } from '../db/schema';

service CatalogService {
  @readonly entity Books as projection on db.Books;
}

Traduzindo para o seu mapa mental RAP: o db/schema.cds faz o papel da tabela + interface view; o service faz o papel de projection + service definition + binding — três artefatos ABAP em uma construção, com o servidor OData de brinde.

Choque cultural nº 2: associação sem on-condition (e a FK que se materializa sozinha)

No ABAP CDS, toda associação carrega sua on-condition. No CAP, a managed association to-one dispensa isso: author : Association to Authors e pronto — o compilador gera a coluna de foreign key na tabela, com o nome <elemento>_<chave-do-alvo>. No exemplo, nasce a coluna author_ID em Books, sem você declarar campo nenhum.

A on-condition só aparece quando precisa — no backlink to-many: books : Association to many Books on books.author = $self. O $self é o "esta instância" do CDL, primo do $projection mental do ABAP, mas apontando para a entidade inteira.

O mesmo vale para os reuse types do pacote comum: declare country : Country num endereço e a tabela ganha a coluna country_code, com a code list de países (dados inclusos, via @sap/cds-common-content) e value help de graça.

Choque cultural nº 3: aspects — e o destino irônico da abstract entity

O : cuid, managed da primeira linha do post é o mecanismo mais idiomático do CDL: aspects, blocos de elementos e anotações que você mistura nas entidades como herança múltipla. Os dois mais usados vêm do @sap/cds/common e valem decorar:

// o que "cuid" e "managed" expandem por baixo dos panos:
entity Foo {
  key ID     : UUID;                                    // cuid: chave canônica,
                                                        // preenchida automaticamente
  createdAt  : Timestamp @cds.on.insert : $now;         // managed: os quatro
  createdBy  : User      @cds.on.insert : $user;        // campos de auditoria,
  modifiedAt : Timestamp @cds.on.insert : $now          // mantidos pelo runtime
                         @cds.on.update : $now;         // sem uma linha de código
  modifiedBy : User      @cds.on.insert : $user
                         @cds.on.update : $user;
}

É o papel que include e as views de interface fazem no ABAP — mas componível, extensível e com comportamento de runtime amarrado. A doc chama a filosofia de aspect-oriented modeling: separar as preocupações transversais (auditoria, chave, temporalidade) do domínio, inclusive em arquivos e pacotes diferentes.

A ironia da abstract entity: quem leu o guia de abstract entities do hub RAP sabe que lá ela é peça central (payloads, parâmetros). No CDS do CAP, abstract entity também existe — mas usar gera warning de deprecated. O motivo, segundo a própria doc: o recurso era usado majoritariamente para o anti-pattern da "super classe base", e foi descontinuado para empurrar todo mundo para aspects de reuso separados. Mesma palavra, destinos opostos nos dois mundos — não leve o hábito de um para o outro.

Choque cultural nº 4: localized — a text table que você não cria

Viu o title : localized String lá no começo? Esse qualificador dispara, na compilação, a geração de uma entidade .texts (com locale), as views de leitura com fallback de idioma e todo o encanamento de tradução — o equivalente ao par "tabela + text table + associação com @Semantics.text" que no ABAP você monta à mão. Uma palavra, o pacote inteiro. O mesmo espírito vale para o aspect temporal (dados com vigência/time slices, incluindo time travel) — anotou, ganhou.

Choque cultural nº 5: composition of aspects (o documento inline)

Para itens que só existem dentro do pai, o CDL tem um atalho que não existe no ABAP CDS: compor sobre um aspect anônimo, inline — sem criar a entidade filha explicitamente:

entity Projects : cuid {
  title   : String;
  members : Composition of many { key user : Association to Users };
}

Por baixo, o compilador gera a entidade de ligação (Projects.members, com o backlink up_) — é também o jeito recomendado de modelar many-to-many, que o CDS (dos dois mundos!) não suporta diretamente: duas one-to-many com uma link entity no meio.

Onde o mapa mental ABAP ajuda — e onde atrapalha

Ajuda

Atrapalha

Entidade-relacionamento, composições, projeções, anotações como metadado — a gramática conceitual é a mesma

Procurar "a tabela por baixo da view" — não há; a entity é a origem

Disciplina de camadas (domínio vs. consumo) — o CAP tem a mesma separação db/ vs. srv/

Escrever on-condition em toda associação — managed association resolve to-one sozinha

Separar anotações do modelo (metadata extension ≈ annotate em arquivo próprio)

Reusar abstract entity como no RAP — no CAP é deprecated; use aspects/types

Pensar em contrato: o service expõe o mínimo

Esperar ativação/transporte — o ciclo é save → watch → git

Boas práticas (as que a própria doc crava)

  1. Chave primária: simples, imutável, canônica. A doc recomenda o aspect cuid (UUID único) — chaves compostas de vários campos degradam joins, e chave que muda quebra referências. Não interprete UUIDs, não use binário como chave.

  2. Capture intenção, não implementação. "What, not How": localized, managed, temporal declaram o quê; os providers genéricos entregam o como.

  3. Aspects para preocupações transversais, em arquivos separados — não polua o domínio com dezenas de anotações de UI.

  4. Evite delimited identifiers (![Nome Com Espaço]) e caracteres não-ASCII — interoperabilidade agradece.

  5. Reuse o @sap/cds/common (Country, Currency, Language, managed, cuid) em vez de reinventar — é interoperabilidade entre apps CAP e dados prontos via @sap/cds-common-content.

  6. KISS, citado literalmente pela doc: o modelo de domínio é um serviço aos consumidores dele, não um monumento do autor.

Perguntas frequentes

Cadê a SE11? Onde vejo "a tabela"?

Não há dicionário separado: a entity do db/ é compilada em DDL na hora do cds deploy (HANA em produção; SQLite em desenvolvimento, sem instalar nada). Quer ver o resultado? cds compile --to sql mostra o DDL gerado; --to csn mostra a representação interna.

Preciso "ativar" alguma coisa?

Não. O cds watch recompila e recarrega a cada save. O conceito de objeto inativo não existe — versionamento e transporte são papel do git e do pipeline de deploy.

Abstract entity existe no CAP?

Existe e está deprecated — usar gera warning. O caminho idiomático são aspects (para reuso estrutural) e types (para tipos nomeados, inclusive estruturados). O contraste com o RAP, onde a abstract entity é protagonista de payloads e parâmetros, é total: mesma palavra, papéis opostos.

Como faço many-to-many?

Como no ABAP: não há suporte direto; resolve-se com duas associações one-to-many e uma link entity — que no CAP pode ser gerada por você via composition of aspects inline, sem declarar a entidade do meio explicitamente.

O CDL vira ABAP CDS em algum momento? Os dois conversam?

Não há conversão — são linguagens de plataformas distintas. A conversa acontece nos protocolos: um app CAP consome o OData do S/4 (via cds import do EDMX) e escuta os eventos do RAP pelo Event Mesh — os dois caminhos já têm guia aqui no hub.

E o "managed" do CAP tem a ver com o managed do RAP?

Só o nome. No RAP, managed é o tipo de implementação do BO (framework provê buffer e persistência). No CAP, managed é um aspect de auditoria (created/modified by/at) e "managed association" é a associação sem on-condition com FK gerada. Três conceitos, uma palavra — cuidado nas conversas de arquitetura.

Conclusão

O CDS do CAP não é um ABAP CDS "portado" — é a mesma filosofia declarativa levada às últimas consequências num mundo sem dicionário legado: a entity gera a tabela, a associação gera a foreign key, o qualificador gera a text table, o aspect compõe o que o include nunca sonhou, e o service embrulha projeção, definição e binding numa construção só. Para o ABAPista, a curva não é aprender uma linguagem nova — é desaprender meia dúzia de reflexos. Feita essa tradução, o resto da trilha CAP (eventos, plugins, outbox) fica com a porta aberta.

Referências oficiais

TagsHANAClean CoreDesenvolvedor
Avalie este conteúdo
para avaliar
SAPiente
@sapiente

Blog sobre SAP, ABAP, BTP, Fiori e tudo que envolve o ecossistema SAP.

Ver perfil →
FacebookInstagramYouTubeTwitter

Comentários 0

Entre na conversa

Faça login para deixar seu comentário neste artigo.

Ainda sem comentários

Seja o primeiro a comentar este artigo.