Hướng dẫn xây dựng ứng dụng Fiori hiện đại bằng ABAP RAP: Góc nhìn của một Kiến trúc sư cấp cao
Bài viết này khám phá sâu về ABAP RESTful Application Programming Model (RAP), giải thích cách xây dựng các ứng dụng Fiori trên SAP S/4HANA một cách hiện đại hơn. Tác giả phân tích kỹ lưỡng kiến trúc 3 lớp, từ CDS Views đến Behavior Definition và Service Binding, đồng thời cung cấp các mẹo về Managed/Unmanaged RAP và kiểm thử. Cuối cùng, bài viết chỉ ra những lỗi thường gặp và các nguyên tắc hiệu suất quan trọng.

Nếu bạn đã xây dựng các ứng dụng SAP trong hơn vài năm, bạn chắc chắn đã thấy bức tranh thay đổi mạnh mẽ. Chúng ta đã chuyển từ màn hình Dynpro truyền thống sang Web Dynpro, sau đó đến SAPUI5 với các dịch vụ OData được kết nối thủ công, và giờ là kỷ nguyên của ABAP RESTful Application Programming Model (RAP). Và tôi phải thẳng thắn với bạn — RAP là bước tiến kiến trúc lớn nhất mà tôi thấy trong thế giới ABAP trong hơn một thập kỷ.
Nhưng vấn đề nằm ở chỗ: hầu hết các đội ngũ tôi tư vấn vẫn đang xây dựng các ứng dụng Fiori theo cách cũ. Họ tạo các Module chức năng, tự động hóa việc xuất bản dịch vụ OData và thắc mắc tại sao việc bảo trì lại khiến họ kiệt sức sau 6 tháng. Nếu bạn thuộc đội ngũ đó, hướng dẫn này dành cho bạn. Chúng ta sẽ phá vỡ ABAP RAP dưới góc nhìn của một kiến trúc sư cấp cao — đó thực sự là cái gì, kiến trúc lớp nào hoạt động như thế nào và cách xây dựng một ứng dụng thực sự hoạt động mà không lãng phí hàng tuần cho mã sườn (boilerplate).
ABAP RAP là gì và tại sao bạn nên quan tâm?
ABAP RESTful Application Programming Model là khung khung chính thức, được khuyến nghị của SAP để xây dựng các ứng dụng giao dịch và chỉ đọc trên SAP S/4HANA (phiên bản trên máy chủ 1909+) và SAP BTP ABAP Environment. Nó kết hợp CDS Views, định nghĩa hành vi, định nghĩa dịch vụ và liên kết dịch vụ thành một kiến trúc liền mạch và có lớp.
Hãy tưởng tượng RAP là câu trả lời cho câu hỏi: "Làm thế nào để xây dựng các dịch vụ OData cấp doanh nghiệp mà không phải viết lại cùng một mã sườn mãi mãi?".
Các trụ cột chính của RAP bao gồm:
- CDS Views làm nền tảng mô hình dữ liệu — không chỉ cho báo cáo nữa
- Định nghĩa hành vi (BDEF) — khai báo các thao tác mà đối tượng doanh nghiệp của bạn hỗ trợ
- Triển khai hành vi (BAPI replacement) — logic ABAP thực tế
- Định nghĩa dịch vụ và Liên kết dịch vụ — xuất bản mô hình của bạn dưới dạng OData V2 hoặc V4
Nếu bạn đã theo dõi loạt bài về CDS Views trên trang web này, bạn đã hiểu rõ lớp mô hình dữ liệu. RAP lấy nền tảng đó và thêm khả năng giao dịch lên trên. Đó là điểm quan trọng.
Ngoài ra đáng chú ý: nếu bạn đã thực hiện các khái niệm trong loạt bài về ABAP OOP Design Patterns, bạn sẽ thấy kiến trúc RAP khuyến khích cùng một kỷ luật thiết kế — tách biệt rõ ràng trách nhiệm, đơn nhiệm và các đơn vị có thể kiểm thử.
Kiến trúc RAP: 3 lớp bạn cần hiểu
Trước khi viết một dòng code nào, hãy để tôi dẫn bạn qua kiến trúc. Hiểu điều này sớm sẽ giúp bạn tiết kiệm hàng giờ đồng hồ sau này.
Lớp 1: Mô hình dữ liệu (CDS Interface Views)
Ở cơ bản, bạn định nghĩa thực thể doanh nghiệp của mình bằng CDS views. Trong RAP, chúng ta phân biệt giữa Interface Views (hợp đồng dữ liệu thô) và Projection Views (chiếu cụ thể cho việc tiêu thụ). Sự phân biệt này là quan trọng — view giao diện của bạn ổn định và có thể tái sử dụng; view chiếu của bạn được tùy chỉnh cho một ứng dụng Fiori hoặc thành phần UI5 cụ thể.
@AbapCatalog.sqlViewName: 'ZI_SALESORDER';
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Sales Order - Interface View'
define root view entity ZI_SalesOrder
as select from vbak
association [0..*] to ZI_SalesOrderItem as _Item
on $projection.SalesOrder = _Item.SalesOrder
{
key vbeln as SalesOrder,
erdat as CreationDate,
ernam as CreatedByUser,
netwr as NetValue,
waerk as Currency,
-- Association
_Item
}
Lưu ý từ khóa define root view entity — điều này đánh dấu nó là gốc của một đối tượng doanh nghiệp (BO), mà RAP cần hiểu cấu trúc đồ thị thực thể của bạn.
Lớp 2: Định nghĩa hành vi (BDEF)
Đây là nơi RAP trở nên thú vị. Định nghĩa hành vi là một tác phẩm được khai báo, nơi bạn nói với khung framework đối tượng doanh nghiệp của bạn có thể làm gì. Nó có thể được tạo không? Cập nhật? Xóa? Nó hỗ trợ bản nháp (draft)? Nó có hành động tùy chỉnh không?
managed implementation in class ZBP_SalesOrder unique;
strict ( 2 );
with draft;
define behavior for ZI_SalesOrder alias SalesOrder
persistent table vbak
draft table zdraft_salesorder
etag master LastChangedAt
lock master
authorization master ( instance )
{
field ( numbering : managed, readonly ) SalesOrder;
field ( readonly ) CreationDate, CreatedByUser;
create;
update;
delete;
draft action Edit;
draft action Activate;
draft action Discard;
draft action Resume;
draft determine action Prepare;
action ( features : instance ) ApproveSalesOrder result [1] $self;
mapping for vbak {
SalesOrder = vbeln;
CreationDate = erdat;
CreatedByUser = ernam;
NetValue = netwr;
Currency = waerk;
}
association _Item { create; }
}
Hãy để tôi làm nổi bật những gì đang diễn ra ở đây. Từ khóa managed có nghĩa là khung SAP xử lý CRUD ổn định tiêu chuẩn — bạn không tự viết logic INSERT/UPDATE/DELETE. Điều đó xóa bỏ hàng trăm dòng mã sườn. Tuyên bố with draft cung cấp khả năng bản nháp (lưu nháp trước khi cam kết cuối) cơ bản là miễn phí.
Lớp 3: Lớp triển khai hành vi
Đối với bất cứ điều gì vượt quá CRUD tiêu chuẩn — xác thực, xác định và hành động tùy chỉnh — bạn triển khai một Lớp triển khai hành vi (BIL). Đây là một hệ thống phân cấp lớp cục bộ được khung framework tạo và quản lý.
CLASS lhc_SalesOrder DEFINITION INHERITING FROM cl_abap_behavior_handler.
PRIVATE SECTION.
METHODS:
validate_net_value FOR VALIDATE ON SAVE
IMPORTING keys FOR SalesOrder~ValidateNetValue,
approve_sales_order FOR ACTION
IMPORTING keys FOR SalesOrder~ApproveSalesOrder RESULT result.
ENDCLASS.
CLASS lhc_SalesOrder IMPLEMENTATION.
METHOD validate_net_value.
" Read the instances that need validation
READ ENTITIES OF ZI_SalesOrder IN LOCAL MODE
ENTITY SalesOrder
FIELDS ( NetValue Currency )
WITH CORRESPONDING #( keys )
RESULT DATA(lt_salesorders)
FAILED DATA(lt_failed).
LOOP AT lt_salesorders INTO DATA(ls_order).
IF ls_order-NetValue <= 0.
APPEND VALUE #(
%tky = ls_order-%tky
) TO failed-salesorder.
APPEND VALUE #(
%tky = ls_order-%tky
%state_area = 'VALIDATE_NET_VALUE'
%msg = new_message(
id = 'ZSO_MESSAGES'
number = '001'
severity = if_abap_behv_message=>severity-error
v1 = ls_order-SalesOrder )
%element-NetValue = if_abap_behv=>mk-on
) TO reported-salesorder.
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD approve_sales_order.
" Read current state
READ ENTITIES OF ZI_SalesOrder IN LOCAL MODE
ENTITY SalesOrder
ALL FIELDS
WITH CORRESPONDING #( keys )
RESULT DATA(lt_orders).
" Modify the status - in real scenario update a status field
MODIFY ENTITIES OF ZI_SalesOrder IN LOCAL MODE
ENTITY SalesOrder
UPDATE FIELDS ( NetValue )
WITH VALUE #( FOR ls_order IN lt_orders (
%tky = ls_order-%tky
NetValue = ls_order-NetValue " apply business logic here
) )
REPORTED DATA(lt_reported)
FAILED DATA(lt_failed)
MAPPED DATA(lt_mapped).
" Return result to caller
result = VALUE #( FOR ls_order IN lt_orders (
%tky = ls_order-%tky
%param = ls_order
) ).
ENDMETHOD.
ENDCLASS.
Hãy chú ý kỹ các câu lệnh READ ENTITIES và MODIFY ENTITIES — đây là các câu lệnh EML (Entity Manipulation Language) đặc thù của RAP. Chúng hoạt động qua bộ đệm của đối tượng doanh nghiệp, không phải trực tiếp với cơ sở dữ liệu, điều này cho RAP sự nhất quán giao dịch.
Định nghĩa dịch vụ và Liên kết: Xuất bản BO của bạn dưới dạng OData
Một khi mô hình dữ liệu và hành vi đã sẵn sàng, việc xuất bản chúng dưới dạng dịch vụ OData khá đơn giản. Định nghĩa dịch vụ chọn các thực thể để xuất bản:
@EndUserText.label: 'Sales Order Service Definition'
define service ZSD_SalesOrder {
expose ZC_SalesOrder as SalesOrder;
expose ZC_SalesOrderItem as SalesOrderItem;
}
Lưu ý rằng chúng ta đang xuất bản các Projection Views (ZC_*), không phải view giao diện trực tiếp. Điều này có chủ đích — nó giữ cho hợp đồng dữ liệu nội bộ của bạn tách biệt với những gì bạn xuất bản cho người tiêu dùng.
Liên kết dịch vụ sau đó gắn nó với một giao thức (OData V2 cho ứng dụng Fiori truyền thống, OData V4 cho những cái mới hơn) và cho phép bạn xuất bản và kiểm tra dịch vụ trực tiếp từ ADT (Eclipse). Đây là nơi bạn cũng có thể xem trước ứng dụng Fiori được tạo từ các chú thích của bạn.
Managed vs. Unmanaged: Lựa chọn hương vị RAP phù hợp
Một trong những câu hỏi phổ biến nhất tôi nhận được là: "Tôi nên dùng Managed hay Unmanaged RAP?" Đây là quan điểm chân thực của tôi sau khi làm việc với cả hai trên hệ thống sản xuất.
Sử dụng Managed RAP khi:
- Bạn đang xây dựng trên bảng tùy chỉnh mới hoặc xanh (greenfield)
- Bạn muốn xử lý bản nháp mà không cần tự xây dựng
- Mô hình ổn định của bạn khớp với mô hình BO của bạn
- Tốc độ phát triển là ưu tiên hàng đầu
Sử dụng Unmanaged RAP khi:
- Bạn đang bao bọc BAPI hoặc module chức năng hiện có
- Logic ổn định của bạn phức tạp và liên quan đến nhiều bảng theo cách không chuẩn
- Bạn đang di chuyển một ứng dụng cũ và cần kiểm soát đầy đủ
Theo kinh nghiệm của tôi, Managed RAP với bổ sung lưu (nơi bạn tích hợp logic lưu tùy chỉnh) mang lại sự cân bằng tốt nhất cho khoảng 80% trường hợp sử dụng. Đừng chạm vào Unmanaged trừ khi bạn thực sự cần nó — chi phí mã sườn là thật.
Kiểm thử hành vi RAP: Đừng bỏ qua điều này
RAP có khả năng kiểm thử xuất sắc được tích hợp sẵn. Bạn có thể kiểm thử đơn vị các triển khai hành vi bằng cách sử dụng CL_ABAP_BEHV_TEST_ENVIRONMENT, điều này cung cấp một mô phỏng trong bộ nhớ của thời gian chạy RAP.
CLASS ltc_SalesOrder DEFINITION FINAL FOR TESTING
DURATION SHORT RISK LEVEL HARMLESS.
PRIVATE SECTION.
CLASS-DATA:
environment TYPE REF TO if_abap_behv_test_environment.
CLASS-METHODS:
class_setup,
class_teardown.
METHODS:
validate_negative_net_value FOR TESTING.
ENDCLASS.
CLASS ltc_SalesOrder IMPLEMENTATION.
METHOD class_setup.
environment = cl_abap_behv_test_environment=>create(
entity_name = 'ZI_SALESORDER' ).
ENDMETHOD.
METHOD class_teardown.
environment->destroy( ).
ENDMETHOD.
METHOD validate_negative_net_value.
" Arrange: Insert test data
environment->insert_test_data( VALUE #(
( salesorder = '0000000001' netvalue = -100 currency = 'EUR' )
) ).
" Act: Trigger save validation
MODIFY ENTITIES OF ZI_SalesOrder
ENTITY SalesOrder
EXECUTE ValidateNetValue
FROM VALUE #( ( salesorder = '0000000001' ) )
FAILED DATA(lt_failed)
REPORTED DATA(lt_reported).
" Assert: Expect a failure message
cl_abap_unit_assert=>assert_not_initial(
act = lt_failed-salesorder
msg = 'Validation should fail for negative net value' ).
ENDMETHOD.
ENDCLASS.
Nếu bạn muốn đi sâu hơn về chiến lược kiểm thử, bài viết của chúng ta về ABAP Unit Testing in SAP S/4HANA bao quát triết lý kiểm thử rộng hơn mà phù hợp hoàn hảo với phát triển RAP.
Các lỗi RAP phổ biến tôi đã thấy trong thực tế
Hãy để tôi cứu bạn khỏi nỗi đau tôi đã chứng kiến trên các dự án thực tế.
Sai lầm 1: Sử dụng truy cập cơ sở dữ liệu trong triển khai hành vi
Đừng sử dụng câu lệnh SELECT trực tiếp bên trong các phương thức BIL. Luôn sử dụng READ ENTITIES. Tại sao? Vì RAP duy trì một bộ đệm giao dịch. Nếu bạn lách qua nó bằng cách đọc DB trực tiếp, bạn sẽ đọc dữ liệu cũ và tạo các lỗi nhất quán cực kỳ khó gỡ lỗi.
Sai lầm 2: Không hiểu mô hình giao dịch RAP
RAP áp dụng một mô hình pha nghiêm ngặt: pha tương tác -> chuỗi lưu -> dọn dẹp. Hiểu rằng xác thực và xác định chạy theo một thứ tự cụ thể — và rằng khung framework gọi chúng, không phải bạn — là nền tảng. Đọc tài liệu của SAP về các pha thời gian chạy BO RAP trước khi viết BIL đầu tiên của bạn.
Sai lầm 3: Bỏ qua lớp View chiếu
Tôi đã thấy các nhà phát triển xuất bản view giao diện trực tiếp. Điều này tạo ra sự liên kết chặt chẽ giữa mô hình dữ liệu nội bộ và người tiêu dùng dịch vụ của bạn. Khi bạn cần thay đổi view giao diện cho một trường hợp sử dụng khác, bạn sẽ phá vỡ ứng dụng Fiori của mình. Luôn sử dụng view chiếu. Chúng không phải là gánh nặng overhead — chúng là bảo hiểm.
Sai lầm 4: Bỏ qua kiểm soát tính năng
RAP có cơ chế mạnh mẽ để kiểm soát các thao tác nào có sẵn tại thời gian chạy — được gọi là kiểm soát tính năng. Sử dụng chúng để bật/tắt hành động, trường hoặc thao tác CRUD dựa trên trạng thái doanh nghiệp. Quá nhiều nhà phát triển để mọi thứ bật và đặt logic điều kiện bên trong hành động đó, dẫn đến trải nghiệm người dùng hỗn loạn.
Các yếu tố hiệu suất trong RAP
Hiệu suất trong RAP xứng đáng với một bài viết riêng, nhưng một vài nguyên tắc quan trọng. Đầu tiên, các view giao diện CDS của bạn là nền tảng hiệu suất — một view CDS chậm có nghĩa là dịch vụ OData chậm. Áp dụng mọi thứ bạn biết về tối ưu hóa hiệu suất CDS ở đây.
Thứ hai, hãy cẩn thận với các xác định được kích hoạt trên thay đổi trường. Nếu bạn gắn một xác định cho mọi thay đổi trường, bạn sẽ kích hoạt logic tốn kém trên mỗi phím bấm trong biểu mẫu Fiori. Hẹp phạm vi các xác định.
Thứ ba, cho các tập thực thể lớn, hãy triển khai phân trang phía máy chủ thông qua cấu hình liên kết dịch vụ OData. Đừng để ứng dụng Fiori của bạn tải 10.000 bản ghi lần đầu tiên vì không ai nghĩ đến $top và $skip.
Những điểm chính
- RAP không chỉ là một khung framework khác — đó là một sự chuyển đổi mô hình khái niệm buộc kiến trúc tốt theo mặc định.
- Mô hình lớp (view giao diện -> view chiếu -> hành vi -> dịch vụ) không phải là nghi thức tùy chọn; nó là điều gì giữ cho ứng dụng của bạn có thể bảo trì ở quy mô.
- Managed RAP với bản nháp là điểm bắt đầu mặc định cho các ứng dụng giao dịch mới. Đi tắt khi bạn có lý do cụ thể.
- EML (
READ ENTITIES/MODIFY ENTITIES) là cách duy nhất chính xác để tương tác với BO bên trong triển khai hành vi. - Kiểm thử các triển khai hành vi bằng cách sử dụng môi trường kiểm thử RAP — nó được xây dựng cho mục đích này và hoạt động tốt.
- Các view chiếu không phải là overhead — chúng là ranh giới hợp đồng người tiêu dùng của bạn.
Nếu bạn đang bắt đầu một ứng dụng Fiori mới hôm nay và không sử dụng RAP, bạn có nghĩa vụ với bản thân và đội ngũ của mình là hiểu tại sao. Các cải thiện năng suất là thật, code dễ bảo trì hơn và SAP rõ ràng đang đầu tư vào mô hình này trong dài hạn.
Bắt đầu với một đối tượng doanh nghiệp Managed đơn giản. Xây dựng các lớp. Kiểm thử chúng. Và kháng cám muốn thêm sự phức tạp cho đến khi bạn cần nó. Đó là bài học từ mọi dự án RAP thành công mà tôi đã tham gia.
Bạn đã bắt đầu làm việc với ABAP RAP trong các dự án của mình chưa? Thách thức lớn nhất bạn đã gặp phải là gì — đó là mô hình tâm trí mới, công cụ trong ADT hay điều gì đó hoàn toàn khác? Hãy chia sẻ trải nghiệm của bạn trong các bình luận bên dưới. Nếu bạn thấy hướng dẫn này hữu ích, hãy chia sẻ nó với đội ngũ của bạn — có khả năng vẫn còn ai đó đang xây dựng dịch vụ OData theo cách cũ và không biết có một con đường tốt hơn.



