@linkup-ai/abap-ai 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +389 -0
- package/dist/adt-client.js +383 -0
- package/dist/cli/activate.js +127 -0
- package/dist/cli/init.js +559 -0
- package/dist/cli/link.js +148 -0
- package/dist/cli/remove.js +83 -0
- package/dist/cli/status.js +231 -0
- package/dist/cli/systems.js +72 -0
- package/dist/cli.js +92 -0
- package/dist/index.js +1442 -0
- package/dist/knowledge/abap/abap-dictionary.md +199 -0
- package/dist/knowledge/abap/abap-sql.md +296 -0
- package/dist/knowledge/abap/amdp.md +273 -0
- package/dist/knowledge/abap/clean-code.md +293 -0
- package/dist/knowledge/abap/cloud-background-processing.md +250 -0
- package/dist/knowledge/abap/cloud-communication.md +265 -0
- package/dist/knowledge/abap/cloud-development.md +176 -0
- package/dist/knowledge/abap/cloud-extensibility.md +252 -0
- package/dist/knowledge/abap/cloud-released-apis.md +261 -0
- package/dist/knowledge/abap/constructor-expressions.md +289 -0
- package/dist/knowledge/abap/enhancements.md +232 -0
- package/dist/knowledge/abap/exceptions.md +271 -0
- package/dist/knowledge/abap/internal-tables.md +205 -0
- package/dist/knowledge/abap/object-orientation.md +298 -0
- package/dist/knowledge/abap/performance.md +216 -0
- package/dist/knowledge/abap/rap-abstract-entities.md +206 -0
- package/dist/knowledge/abap/rap-business-events.md +216 -0
- package/dist/knowledge/abap/rap-draft.md +191 -0
- package/dist/knowledge/abap/rap-eml.md +453 -0
- package/dist/knowledge/abap/rap-end-to-end.md +486 -0
- package/dist/knowledge/abap/rap-feature-control.md +185 -0
- package/dist/knowledge/abap/rap-numbering.md +280 -0
- package/dist/knowledge/abap/rap-service-exposure.md +163 -0
- package/dist/knowledge/abap/rap-unmanaged.md +468 -0
- package/dist/knowledge/abap/string-processing.md +180 -0
- package/dist/knowledge/abap/unit-testing.md +303 -0
- package/dist/knowledge/abap-cds/access-control.md +241 -0
- package/dist/knowledge/abap-cds/annotations.md +331 -0
- package/dist/knowledge/abap-cds/associations.md +254 -0
- package/dist/knowledge/abap-cds/expressions.md +230 -0
- package/dist/knowledge/abap-cds/functions.md +245 -0
- package/dist/knowledge/abap-cds/metadata-extensions.md +294 -0
- package/dist/knowledge/cap/authentication.md +278 -0
- package/dist/knowledge/cap/cdl-syntax.md +247 -0
- package/dist/knowledge/cap/cql-queries.md +266 -0
- package/dist/knowledge/cap/deployment.md +343 -0
- package/dist/knowledge/cap/event-handlers.md +287 -0
- package/dist/knowledge/cap/fiori-integration.md +303 -0
- package/dist/knowledge/cap/service-definitions.md +287 -0
- package/dist/knowledge/fiori/annotations.md +347 -0
- package/dist/knowledge/fiori/deployment.md +340 -0
- package/dist/knowledge/fiori/fiori-elements.md +332 -0
- package/dist/knowledge/fiori/fiori-side-effects.md +107 -0
- package/dist/knowledge/fiori/fiori-valuelist.md +144 -0
- package/dist/knowledge/fiori/ui5-controllers.md +358 -0
- package/dist/knowledge/fiori/ui5-data-binding.md +311 -0
- package/dist/knowledge/fiori/ui5-fragments-dialogs.md +330 -0
- package/dist/knowledge/fiori/ui5-manifest.md +411 -0
- package/dist/knowledge/fiori/ui5-routing.md +303 -0
- package/dist/knowledge/fiori/ui5-xml-views.md +294 -0
- package/dist/license-guard.js +81 -0
- package/dist/logger.js +114 -0
- package/dist/postinstall.js +165 -0
- package/dist/security-audit.js +136 -0
- package/dist/security-policy.js +322 -0
- package/dist/system-profile.js +207 -0
- package/dist/tools/abap-doc.js +72 -0
- package/dist/tools/abapgit.js +161 -0
- package/dist/tools/activate.js +71 -0
- package/dist/tools/atc-check.js +117 -0
- package/dist/tools/auth-object.js +56 -0
- package/dist/tools/breakpoints.js +76 -0
- package/dist/tools/call-hierarchy.js +84 -0
- package/dist/tools/cds-annotations.js +98 -0
- package/dist/tools/cds-dependencies.js +65 -0
- package/dist/tools/check.js +47 -0
- package/dist/tools/code-completion.js +70 -0
- package/dist/tools/code-coverage.js +111 -0
- package/dist/tools/create-amdp.js +111 -0
- package/dist/tools/create-dcl.js +81 -0
- package/dist/tools/create-transport.js +38 -0
- package/dist/tools/create.js +285 -0
- package/dist/tools/data-preview.js +37 -0
- package/dist/tools/delete.js +45 -0
- package/dist/tools/deploy-bsp.js +298 -0
- package/dist/tools/discovery.js +59 -0
- package/dist/tools/element-info.js +93 -0
- package/dist/tools/enhancements.js +186 -0
- package/dist/tools/extract-method.js +44 -0
- package/dist/tools/function-group.js +59 -0
- package/dist/tools/knowledge.js +275 -0
- package/dist/tools/lock-object.js +75 -0
- package/dist/tools/message-class.js +67 -0
- package/dist/tools/navigate.js +80 -0
- package/dist/tools/number-range.js +57 -0
- package/dist/tools/object-documentation.js +43 -0
- package/dist/tools/object-structure.js +78 -0
- package/dist/tools/object-versions.js +57 -0
- package/dist/tools/package-contents.js +60 -0
- package/dist/tools/pretty-printer.js +35 -0
- package/dist/tools/publish-binding.js +49 -0
- package/dist/tools/quick-fix.js +69 -0
- package/dist/tools/read.js +172 -0
- package/dist/tools/refactor-rename.js +60 -0
- package/dist/tools/release-transport.js +24 -0
- package/dist/tools/released-apis.js +51 -0
- package/dist/tools/repository-tree.js +90 -0
- package/dist/tools/scaffold-rap.js +642 -0
- package/dist/tools/search.js +73 -0
- package/dist/tools/shared/data-format.js +101 -0
- package/dist/tools/sql-console.js +17 -0
- package/dist/tools/system-info.js +271 -0
- package/dist/tools/traces.js +66 -0
- package/dist/tools/transport-contents.js +83 -0
- package/dist/tools/transports.js +68 -0
- package/dist/tools/unit-test.js +135 -0
- package/dist/tools/where-used.js +59 -0
- package/dist/tools/write.js +120 -0
- package/package.json +50 -0
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
# AMDP — ABAP Managed Database Procedures (HANA SQLScript)
|
|
2
|
+
|
|
3
|
+
## Basic AMDP Method
|
|
4
|
+
|
|
5
|
+
```abap
|
|
6
|
+
CLASS zcl_order_amdp DEFINITION PUBLIC FINAL CREATE PUBLIC.
|
|
7
|
+
PUBLIC SECTION.
|
|
8
|
+
INTERFACES if_amdp_marker_hdb. " marks class as AMDP-enabled for HANA
|
|
9
|
+
|
|
10
|
+
TYPES: BEGIN OF ty_order_summary,
|
|
11
|
+
customer_id TYPE kunnr,
|
|
12
|
+
order_count TYPE i,
|
|
13
|
+
total_amount TYPE netwr,
|
|
14
|
+
currency_code TYPE waers,
|
|
15
|
+
END OF ty_order_summary.
|
|
16
|
+
|
|
17
|
+
METHODS get_order_summary
|
|
18
|
+
IMPORTING VALUE(iv_min_amount) TYPE netwr
|
|
19
|
+
EXPORTING VALUE(et_result) TYPE STANDARD TABLE OF ty_order_summary.
|
|
20
|
+
|
|
21
|
+
ENDCLASS.
|
|
22
|
+
|
|
23
|
+
CLASS zcl_order_amdp IMPLEMENTATION.
|
|
24
|
+
|
|
25
|
+
METHOD get_order_summary BY DATABASE PROCEDURE FOR HDB
|
|
26
|
+
LANGUAGE SQLSCRIPT OPTIONS READ-ONLY
|
|
27
|
+
USING ztab_order.
|
|
28
|
+
|
|
29
|
+
et_result = SELECT customer_id,
|
|
30
|
+
COUNT(*) AS order_count,
|
|
31
|
+
SUM( total_amount ) AS total_amount,
|
|
32
|
+
currency_code
|
|
33
|
+
FROM ztab_order
|
|
34
|
+
WHERE total_amount >= :iv_min_amount
|
|
35
|
+
GROUP BY customer_id, currency_code
|
|
36
|
+
ORDER BY total_amount DESC;
|
|
37
|
+
|
|
38
|
+
ENDMETHOD.
|
|
39
|
+
|
|
40
|
+
ENDCLASS.
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## AMDP Function (Table Function for CDS)
|
|
44
|
+
|
|
45
|
+
```abap
|
|
46
|
+
CLASS zcl_order_amdp DEFINITION PUBLIC FINAL CREATE PUBLIC.
|
|
47
|
+
PUBLIC SECTION.
|
|
48
|
+
INTERFACES if_amdp_marker_hdb.
|
|
49
|
+
|
|
50
|
+
CLASS-METHODS get_ranked_orders
|
|
51
|
+
FOR TABLE FUNCTION ZTF_RankedOrders.
|
|
52
|
+
ENDCLASS.
|
|
53
|
+
|
|
54
|
+
CLASS zcl_order_amdp IMPLEMENTATION.
|
|
55
|
+
|
|
56
|
+
METHOD get_ranked_orders BY DATABASE FUNCTION FOR HDB
|
|
57
|
+
LANGUAGE SQLSCRIPT OPTIONS READ-ONLY
|
|
58
|
+
USING ztab_order ztab_customer.
|
|
59
|
+
|
|
60
|
+
RETURN SELECT o.order_id,
|
|
61
|
+
o.customer_id,
|
|
62
|
+
c.name AS customer_name,
|
|
63
|
+
o.total_amount,
|
|
64
|
+
o.currency_code,
|
|
65
|
+
ROW_NUMBER() OVER (
|
|
66
|
+
PARTITION BY o.customer_id
|
|
67
|
+
ORDER BY o.total_amount DESC
|
|
68
|
+
) AS rank
|
|
69
|
+
FROM ztab_order AS o
|
|
70
|
+
INNER JOIN ztab_customer AS c
|
|
71
|
+
ON o.customer_id = c.customer_id;
|
|
72
|
+
|
|
73
|
+
ENDMETHOD.
|
|
74
|
+
|
|
75
|
+
ENDCLASS.
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### CDS Table Function
|
|
79
|
+
|
|
80
|
+
```abap
|
|
81
|
+
@EndUserText.label: 'Ranked Orders'
|
|
82
|
+
define table function ZTF_RankedOrders
|
|
83
|
+
returns
|
|
84
|
+
{
|
|
85
|
+
key order_id : abap.numc(10);
|
|
86
|
+
customer_id : kunnr;
|
|
87
|
+
customer_name : abap.char(40);
|
|
88
|
+
total_amount : abap.curr(17,2);
|
|
89
|
+
currency_code : abap.cuky(5);
|
|
90
|
+
rank : abap.int4;
|
|
91
|
+
}
|
|
92
|
+
implemented by method zcl_order_amdp=>get_ranked_orders;
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Consume in CDS View
|
|
96
|
+
|
|
97
|
+
```abap
|
|
98
|
+
define view entity ZI_RankedOrders as select from ZTF_RankedOrders
|
|
99
|
+
{
|
|
100
|
+
key order_id as OrderID,
|
|
101
|
+
customer_id as CustomerID,
|
|
102
|
+
customer_name as CustomerName,
|
|
103
|
+
@Semantics.amount.currencyCode: 'CurrencyCode'
|
|
104
|
+
total_amount as TotalAmount,
|
|
105
|
+
currency_code as CurrencyCode,
|
|
106
|
+
rank as Rank
|
|
107
|
+
}
|
|
108
|
+
where rank <= 10
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## SQLScript Patterns
|
|
112
|
+
|
|
113
|
+
### Variables and Control Flow
|
|
114
|
+
|
|
115
|
+
```sql
|
|
116
|
+
DECLARE lv_count INTEGER;
|
|
117
|
+
DECLARE lv_threshold DECIMAL(17,2) := 1000.00;
|
|
118
|
+
|
|
119
|
+
SELECT COUNT(*) INTO lv_count FROM ztab_order;
|
|
120
|
+
|
|
121
|
+
IF lv_count > 0 THEN
|
|
122
|
+
-- process
|
|
123
|
+
ELSEIF lv_count = 0 THEN
|
|
124
|
+
-- empty
|
|
125
|
+
END IF;
|
|
126
|
+
|
|
127
|
+
WHILE lv_count > 0 DO
|
|
128
|
+
lv_count := lv_count - 1;
|
|
129
|
+
END WHILE;
|
|
130
|
+
|
|
131
|
+
FOR i IN 1..10 DO
|
|
132
|
+
-- loop body
|
|
133
|
+
END FOR;
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Temporary Tables (Table Variables)
|
|
137
|
+
|
|
138
|
+
```sql
|
|
139
|
+
lt_filtered = SELECT * FROM ztab_order WHERE status = 'O';
|
|
140
|
+
|
|
141
|
+
lt_enriched = SELECT f.order_id,
|
|
142
|
+
f.customer_id,
|
|
143
|
+
c.name AS customer_name,
|
|
144
|
+
f.total_amount
|
|
145
|
+
FROM :lt_filtered AS f
|
|
146
|
+
INNER JOIN ztab_customer AS c
|
|
147
|
+
ON f.customer_id = c.customer_id;
|
|
148
|
+
|
|
149
|
+
et_result = SELECT * FROM :lt_enriched WHERE total_amount > :iv_min;
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Window Functions
|
|
153
|
+
|
|
154
|
+
```sql
|
|
155
|
+
et_result = SELECT order_id,
|
|
156
|
+
customer_id,
|
|
157
|
+
total_amount,
|
|
158
|
+
ROW_NUMBER() OVER (ORDER BY total_amount DESC) AS row_num,
|
|
159
|
+
RANK() OVER (ORDER BY total_amount DESC) AS ranking,
|
|
160
|
+
SUM(total_amount) OVER () AS grand_total,
|
|
161
|
+
SUM(total_amount) OVER (PARTITION BY customer_id) AS customer_total,
|
|
162
|
+
AVG(total_amount) OVER (
|
|
163
|
+
ORDER BY created_at
|
|
164
|
+
ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
|
|
165
|
+
) AS moving_avg_3
|
|
166
|
+
FROM ztab_order;
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### String Functions
|
|
170
|
+
|
|
171
|
+
```sql
|
|
172
|
+
CONCAT(first_name, ' ', last_name)
|
|
173
|
+
UPPER(name)
|
|
174
|
+
LOWER(name)
|
|
175
|
+
LENGTH(description)
|
|
176
|
+
SUBSTR(text, 1, 10)
|
|
177
|
+
REPLACE(phone, '-', '')
|
|
178
|
+
LPAD(order_id, 10, '0')
|
|
179
|
+
TRIM(BOTH ' ' FROM name)
|
|
180
|
+
LOCATE(email, '@') -- position of @ (0 if not found)
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Date Functions
|
|
184
|
+
|
|
185
|
+
```sql
|
|
186
|
+
CURRENT_DATE
|
|
187
|
+
CURRENT_TIMESTAMP
|
|
188
|
+
ADD_DAYS(order_date, 7)
|
|
189
|
+
ADD_MONTHS(order_date, 1)
|
|
190
|
+
DAYS_BETWEEN(start_date, end_date)
|
|
191
|
+
EXTRACT(YEAR FROM order_date)
|
|
192
|
+
TO_DATE('2026-03-15', 'YYYY-MM-DD')
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## AMDP with OUT Parameter (Scalar)
|
|
196
|
+
|
|
197
|
+
```abap
|
|
198
|
+
METHODS get_order_count
|
|
199
|
+
IMPORTING VALUE(iv_status) TYPE char1
|
|
200
|
+
EXPORTING VALUE(ev_count) TYPE i.
|
|
201
|
+
|
|
202
|
+
METHOD get_order_count BY DATABASE PROCEDURE FOR HDB
|
|
203
|
+
LANGUAGE SQLSCRIPT OPTIONS READ-ONLY
|
|
204
|
+
USING ztab_order.
|
|
205
|
+
|
|
206
|
+
SELECT COUNT(*) INTO ev_count
|
|
207
|
+
FROM ztab_order
|
|
208
|
+
WHERE status = :iv_status;
|
|
209
|
+
|
|
210
|
+
ENDMETHOD.
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## AMDP with Multiple Results
|
|
214
|
+
|
|
215
|
+
```abap
|
|
216
|
+
METHODS get_order_report
|
|
217
|
+
IMPORTING VALUE(iv_year) TYPE numc4
|
|
218
|
+
EXPORTING VALUE(et_summary) TYPE tt_summary
|
|
219
|
+
VALUE(et_detail) TYPE tt_detail.
|
|
220
|
+
|
|
221
|
+
METHOD get_order_report BY DATABASE PROCEDURE FOR HDB
|
|
222
|
+
LANGUAGE SQLSCRIPT OPTIONS READ-ONLY
|
|
223
|
+
USING ztab_order ztab_order_item.
|
|
224
|
+
|
|
225
|
+
et_summary = SELECT customer_id, COUNT(*) AS cnt, SUM(total_amount) AS total
|
|
226
|
+
FROM ztab_order
|
|
227
|
+
WHERE EXTRACT(YEAR FROM created_at) = :iv_year
|
|
228
|
+
GROUP BY customer_id;
|
|
229
|
+
|
|
230
|
+
et_detail = SELECT o.order_id, o.customer_id, i.material, i.quantity, i.amount
|
|
231
|
+
FROM ztab_order AS o
|
|
232
|
+
INNER JOIN ztab_order_item AS i ON o.order_id = i.order_id
|
|
233
|
+
WHERE EXTRACT(YEAR FROM o.created_at) = :iv_year;
|
|
234
|
+
|
|
235
|
+
ENDMETHOD.
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
## Calling AMDP from ABAP
|
|
239
|
+
|
|
240
|
+
```abap
|
|
241
|
+
DATA(lo_amdp) = NEW zcl_order_amdp( ).
|
|
242
|
+
|
|
243
|
+
lo_amdp->get_order_summary(
|
|
244
|
+
EXPORTING iv_min_amount = 1000
|
|
245
|
+
IMPORTING et_result = DATA(lt_summary) ).
|
|
246
|
+
|
|
247
|
+
LOOP AT lt_summary INTO DATA(ls_sum).
|
|
248
|
+
" process
|
|
249
|
+
ENDLOOP.
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
## Rules
|
|
253
|
+
- Class MUST implement `if_amdp_marker_hdb`
|
|
254
|
+
- Method signature: `BY DATABASE PROCEDURE FOR HDB LANGUAGE SQLSCRIPT`
|
|
255
|
+
- `OPTIONS READ-ONLY` for read operations (enables parallel execution)
|
|
256
|
+
- `USING <table1> <table2>` — list ALL DB tables accessed (mandatory)
|
|
257
|
+
- Table function methods must be `CLASS-METHODS` (static)
|
|
258
|
+
- Parameters: always `VALUE(...)` (pass by value required)
|
|
259
|
+
- Use `:param_name` to reference ABAP parameters in SQLScript
|
|
260
|
+
- Use `:lt_variable` to reference table variables
|
|
261
|
+
- AMDP runs on HANA only — not available on other databases
|
|
262
|
+
|
|
263
|
+
## Anti-Patterns
|
|
264
|
+
| Anti-Pattern | Correct |
|
|
265
|
+
|---|---|
|
|
266
|
+
| Missing `if_amdp_marker_hdb` interface | Required for all AMDP classes |
|
|
267
|
+
| Missing `USING` clause for accessed tables | List every table accessed |
|
|
268
|
+
| `OPTIONS READ-ONLY` on methods that modify data | Remove for write operations |
|
|
269
|
+
| Complex logic that could be CDS | Use CDS for simple joins/aggregations |
|
|
270
|
+
| AMDP for simple SELECT | Use ABAP SQL — AMDP only for HANA-specific features |
|
|
271
|
+
| Instance method for table function | Must be `CLASS-METHODS` (static) |
|
|
272
|
+
| Passing internal table by reference | AMDP requires `VALUE(...)` |
|
|
273
|
+
| Using AMDP on non-HANA system | AMDP is HANA-only |
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
# ABAP Clean Code — naming, conventions, structure, readability
|
|
2
|
+
|
|
3
|
+
## Naming Conventions — Prefixes
|
|
4
|
+
|
|
5
|
+
### Objects (Repository)
|
|
6
|
+
|
|
7
|
+
| Prefix | Object Type | Example |
|
|
8
|
+
|--------|-------------|---------|
|
|
9
|
+
| `Z` or `Y` | Customer namespace | `ZORDER`, `YHR_PAYROLL` |
|
|
10
|
+
| `ZCL_` | Class | `ZCL_ORDER_PROCESSOR` |
|
|
11
|
+
| `ZIF_` | Interface | `ZIF_ORDER_SERVICE` |
|
|
12
|
+
| `ZCX_` | Exception class | `ZCX_ORDER_ERROR` |
|
|
13
|
+
| `ZCM_` | RAP message class (behavior) | `ZCM_ORDER` |
|
|
14
|
+
| `ZBP_` | RAP behavior pool | `ZBP_I_ORDER` |
|
|
15
|
+
| `ZBP_BX_` | RAP behavior extension pool | `ZBP_BX_I_SALESORDER` |
|
|
16
|
+
| `ZI_` | CDS Interface view (RAP) | `ZI_ORDER` |
|
|
17
|
+
| `ZC_` | CDS Projection/Consumption view | `ZC_ORDER` |
|
|
18
|
+
| `ZA_` | CDS Abstract entity | `ZA_REJECT_PARAMS` |
|
|
19
|
+
| `ZR_` | CDS Restricted reuse view | `ZR_ORDER_BASE` |
|
|
20
|
+
| `ZUI_` | Service Definition | `ZUI_ORDER` |
|
|
21
|
+
| `ZTAB_` or `Z` | Database table | `ZTAB_ORDER` |
|
|
22
|
+
| `ZS_` | Structure type (DDIC) | `ZS_ORDER_ITEM` |
|
|
23
|
+
| `ZTT_` | Table type (DDIC) | `ZTT_ORDER_ITEMS` |
|
|
24
|
+
| `ZDOM_` | Domain | `ZDOM_ORDER_STATUS` |
|
|
25
|
+
| `ZDTEL_` | Data element | `ZDTEL_ORDER_ID` |
|
|
26
|
+
|
|
27
|
+
### Variables (Local)
|
|
28
|
+
|
|
29
|
+
| Prefix | Scope | Example |
|
|
30
|
+
|--------|-------|---------|
|
|
31
|
+
| `lv_` | Local variable | `lv_order_id` |
|
|
32
|
+
| `lt_` | Local table | `lt_orders` |
|
|
33
|
+
| `ls_` | Local structure | `ls_order` |
|
|
34
|
+
| `lr_` | Local reference | `lr_data` |
|
|
35
|
+
| `lo_` | Local object reference | `lo_processor` |
|
|
36
|
+
| `lx_` | Local exception reference | `lx_error` |
|
|
37
|
+
|
|
38
|
+
### Variables (Method Parameters)
|
|
39
|
+
|
|
40
|
+
| Prefix | Direction | Example |
|
|
41
|
+
|--------|-----------|---------|
|
|
42
|
+
| `iv_` | IMPORTING value | `iv_order_id` |
|
|
43
|
+
| `ir_` | IMPORTING reference | `ir_data` |
|
|
44
|
+
| `io_` | IMPORTING object | `io_service` |
|
|
45
|
+
| `ev_` | EXPORTING value | `ev_result` |
|
|
46
|
+
| `et_` | EXPORTING table | `et_items` |
|
|
47
|
+
| `es_` | EXPORTING structure | `es_header` |
|
|
48
|
+
| `cv_` | CHANGING value | `cv_counter` |
|
|
49
|
+
| `ct_` | CHANGING table | `ct_items` |
|
|
50
|
+
| `rv_` | RETURNING value | `rv_success` |
|
|
51
|
+
| `rt_` | RETURNING table | `rt_items` |
|
|
52
|
+
| `rs_` | RETURNING structure | `rs_result` |
|
|
53
|
+
| `ro_` | RETURNING object | `ro_instance` |
|
|
54
|
+
|
|
55
|
+
### Variables (Class Attributes)
|
|
56
|
+
|
|
57
|
+
| Prefix | Scope | Example |
|
|
58
|
+
|--------|-------|---------|
|
|
59
|
+
| `mv_` | Instance attribute (value) | `mv_order_id` |
|
|
60
|
+
| `mt_` | Instance attribute (table) | `mt_items` |
|
|
61
|
+
| `ms_` | Instance attribute (structure) | `ms_config` |
|
|
62
|
+
| `mo_` | Instance attribute (object) | `mo_logger` |
|
|
63
|
+
| `gv_` | Static attribute (value) | `gv_counter` |
|
|
64
|
+
| `gt_` | Static attribute (table) | `gt_cache` |
|
|
65
|
+
| `go_` | Static attribute (object) | `go_singleton` |
|
|
66
|
+
|
|
67
|
+
### Constants
|
|
68
|
+
|
|
69
|
+
| Prefix | Example |
|
|
70
|
+
|--------|---------|
|
|
71
|
+
| `c_` or `mc_` | `c_status_open`, `mc_max_retries` |
|
|
72
|
+
| `gc_` | Static constant `gc_version` |
|
|
73
|
+
|
|
74
|
+
### Field Symbols and Data References
|
|
75
|
+
|
|
76
|
+
| Prefix | Example |
|
|
77
|
+
|--------|---------|
|
|
78
|
+
| `<ls_>` or `<fs_>` | `<ls_order>`, `<fs_item>` |
|
|
79
|
+
| `lr_` | Data reference `lr_data` |
|
|
80
|
+
|
|
81
|
+
## CDS Naming Conventions
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
Interface views: ZI_OrderHeader, ZI_OrderItem
|
|
85
|
+
Projection views: ZC_OrderHeader, ZC_OrderItem
|
|
86
|
+
Abstract entities: ZA_RejectParams, ZA_OrderResult
|
|
87
|
+
Service Definition: ZUI_ORDER
|
|
88
|
+
Service Binding: ZUI_ORDER_O4 (V4), ZUI_ORDER_O2 (V2)
|
|
89
|
+
Metadata Extension: ZC_OrderHeader (same name as projection)
|
|
90
|
+
Access Control: ZI_OrderHeader (same name as CDS view)
|
|
91
|
+
|
|
92
|
+
Field names: CamelCase in CDS → OrderID, CustomerName, TotalAmount
|
|
93
|
+
Association prefix: _Customer, _Items, _Currency (underscore prefix)
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Method Design
|
|
97
|
+
|
|
98
|
+
```abap
|
|
99
|
+
" GOOD: focused, single responsibility, < 30 lines
|
|
100
|
+
METHOD validate_customer.
|
|
101
|
+
IF iv_customer_id IS INITIAL.
|
|
102
|
+
RAISE EXCEPTION TYPE zcx_order_error
|
|
103
|
+
EXPORTING textid = zcx_order_error=>customer_required.
|
|
104
|
+
ENDIF.
|
|
105
|
+
IF NOT customer_exists( iv_customer_id ).
|
|
106
|
+
RAISE EXCEPTION TYPE zcx_order_error
|
|
107
|
+
EXPORTING textid = zcx_order_error=>customer_not_found
|
|
108
|
+
mv_customer_id = iv_customer_id.
|
|
109
|
+
ENDIF.
|
|
110
|
+
ENDMETHOD.
|
|
111
|
+
|
|
112
|
+
" BAD: doing too much
|
|
113
|
+
METHOD process_order.
|
|
114
|
+
" 200 lines: validates, calculates, saves, sends email, logs...
|
|
115
|
+
ENDMETHOD.
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
```abap
|
|
119
|
+
" Prefer RETURNING over EXPORTING for single outputs (enables chaining)
|
|
120
|
+
" GOOD:
|
|
121
|
+
METHODS get_status RETURNING VALUE(rv_status) TYPE char1.
|
|
122
|
+
DATA(lv_status) = lo_order->get_status( ).
|
|
123
|
+
|
|
124
|
+
" AVOID for single output:
|
|
125
|
+
METHODS get_status EXPORTING ev_status TYPE char1.
|
|
126
|
+
lo_order->get_status( IMPORTING ev_status = DATA(lv_status) ).
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Boolean Handling
|
|
130
|
+
|
|
131
|
+
```abap
|
|
132
|
+
" Use abap_bool / abap_true / abap_false
|
|
133
|
+
DATA lv_valid TYPE abap_bool.
|
|
134
|
+
lv_valid = abap_true.
|
|
135
|
+
|
|
136
|
+
IF lv_valid = abap_true.
|
|
137
|
+
" Or simply:
|
|
138
|
+
IF lv_valid IS NOT INITIAL.
|
|
139
|
+
|
|
140
|
+
" AVOID:
|
|
141
|
+
DATA lv_flag TYPE c LENGTH 1 VALUE 'X'.
|
|
142
|
+
IF lv_flag = 'X'.
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Modern ABAP Patterns
|
|
146
|
+
|
|
147
|
+
```abap
|
|
148
|
+
" Inline declarations — ALWAYS for local variables
|
|
149
|
+
DATA(lv_count) = lines( lt_items ).
|
|
150
|
+
DATA(lo_proc) = NEW zcl_processor( ).
|
|
151
|
+
LOOP AT lt_items ASSIGNING FIELD-SYMBOL(<ls_item>).
|
|
152
|
+
|
|
153
|
+
" NOT:
|
|
154
|
+
DATA lv_count TYPE i.
|
|
155
|
+
lv_count = lines( lt_items ).
|
|
156
|
+
DATA lo_proc TYPE REF TO zcl_processor.
|
|
157
|
+
CREATE OBJECT lo_proc.
|
|
158
|
+
|
|
159
|
+
" Constructor expressions over imperative
|
|
160
|
+
DATA(lt_filtered) = FILTER #( lt_items WHERE status = 'A' ).
|
|
161
|
+
DATA(lv_label) = COND string( WHEN lv_type = 'A' THEN 'Active' ELSE 'Other' ).
|
|
162
|
+
DATA(ls_copy) = CORRESPONDING zs_target( ls_source ).
|
|
163
|
+
|
|
164
|
+
" NOT:
|
|
165
|
+
LOOP AT lt_items INTO ls_item WHERE status = 'A'.
|
|
166
|
+
APPEND ls_item TO lt_filtered.
|
|
167
|
+
ENDLOOP.
|
|
168
|
+
|
|
169
|
+
" String templates over CONCATENATE
|
|
170
|
+
DATA(lv_msg) = |Order { lv_id } for { lv_customer }|.
|
|
171
|
+
" NOT:
|
|
172
|
+
CONCATENATE 'Order' lv_id 'for' lv_customer INTO lv_msg SEPARATED BY space.
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## Error Handling
|
|
176
|
+
|
|
177
|
+
```abap
|
|
178
|
+
" Specific exceptions, never cx_root
|
|
179
|
+
TRY.
|
|
180
|
+
lo_service->process( iv_data ).
|
|
181
|
+
CATCH zcx_order_error INTO DATA(lx_order).
|
|
182
|
+
" Handle business error
|
|
183
|
+
CATCH cx_sy_move_cast_error INTO DATA(lx_cast).
|
|
184
|
+
" Handle technical error
|
|
185
|
+
ENDTRY.
|
|
186
|
+
|
|
187
|
+
" Never empty CATCH
|
|
188
|
+
" BAD:
|
|
189
|
+
TRY.
|
|
190
|
+
lo_service->process( ).
|
|
191
|
+
CATCH cx_root. " Swallows everything silently
|
|
192
|
+
ENDTRY.
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## Class Structure
|
|
196
|
+
|
|
197
|
+
```abap
|
|
198
|
+
CLASS zcl_order_service DEFINITION PUBLIC FINAL CREATE PUBLIC.
|
|
199
|
+
PUBLIC SECTION.
|
|
200
|
+
" 1. Interfaces
|
|
201
|
+
INTERFACES zif_order_service.
|
|
202
|
+
|
|
203
|
+
" 2. Types and constants
|
|
204
|
+
TYPES ty_order_id TYPE numc10.
|
|
205
|
+
CONSTANTS c_max_items TYPE i VALUE 999.
|
|
206
|
+
|
|
207
|
+
" 3. Constructor
|
|
208
|
+
METHODS constructor IMPORTING io_repo TYPE REF TO zif_order_repo.
|
|
209
|
+
|
|
210
|
+
" 4. Public methods (business API)
|
|
211
|
+
METHODS create_order
|
|
212
|
+
IMPORTING is_order TYPE zs_order_data
|
|
213
|
+
RETURNING VALUE(rv_id) TYPE ty_order_id
|
|
214
|
+
RAISING zcx_order_error.
|
|
215
|
+
|
|
216
|
+
PRIVATE SECTION.
|
|
217
|
+
" 5. Instance attributes
|
|
218
|
+
DATA mo_repo TYPE REF TO zif_order_repo.
|
|
219
|
+
|
|
220
|
+
" 6. Private methods (internal helpers)
|
|
221
|
+
METHODS validate IMPORTING is_order TYPE zs_order_data RAISING zcx_order_error.
|
|
222
|
+
METHODS calculate_total IMPORTING it_items TYPE ztt_items RETURNING VALUE(rv_total) TYPE netwr.
|
|
223
|
+
ENDCLASS.
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
## RAP Naming
|
|
227
|
+
|
|
228
|
+
```abap
|
|
229
|
+
" Handler methods — match BDEF names
|
|
230
|
+
METHODS validateDates FOR VALIDATE ON SAVE IMPORTING keys FOR Travel~validateDates.
|
|
231
|
+
METHODS setTravelID FOR DETERMINE ON MODIFY IMPORTING keys FOR Travel~setTravelID.
|
|
232
|
+
METHODS acceptTravel FOR MODIFY IMPORTING keys FOR ACTION Travel~acceptTravel.
|
|
233
|
+
METHODS get_instance_features FOR INSTANCE FEATURES IMPORTING keys ... FOR Travel RESULT result.
|
|
234
|
+
METHODS get_global_authorizations FOR GLOBAL AUTHORIZATION IMPORTING REQUEST ... FOR Travel RESULT result.
|
|
235
|
+
|
|
236
|
+
" Local handler class naming
|
|
237
|
+
CLASS lhc_travel DEFINITION INHERITING FROM cl_abap_behavior_handler.
|
|
238
|
+
" lhc_ = local handler class
|
|
239
|
+
" lsc_ = local saver class
|
|
240
|
+
|
|
241
|
+
CLASS lsc_travel DEFINITION INHERITING FROM cl_abap_behavior_saver.
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
## Comments
|
|
245
|
+
|
|
246
|
+
```abap
|
|
247
|
+
" Comment WHAT, not HOW (code should be self-documenting)
|
|
248
|
+
|
|
249
|
+
" GOOD:
|
|
250
|
+
" Check credit limit before order confirmation
|
|
251
|
+
IF ls_order-total > get_credit_limit( ls_order-customer ).
|
|
252
|
+
|
|
253
|
+
" BAD:
|
|
254
|
+
" If total is greater than credit limit
|
|
255
|
+
IF ls_order-total > get_credit_limit( ls_order-customer ).
|
|
256
|
+
|
|
257
|
+
" GOOD: explain WHY for non-obvious decisions
|
|
258
|
+
" RFC module returns status in legacy format (1=open, 2=closed)
|
|
259
|
+
" Must map to our domain values
|
|
260
|
+
DATA(lv_status) = SWITCH #( lv_rfc_status WHEN 1 THEN 'O' WHEN 2 THEN 'C' ).
|
|
261
|
+
|
|
262
|
+
" No comments needed for self-evident code:
|
|
263
|
+
DATA(lv_total) = REDUCE netwr( INIT s = 0 FOR wa IN lt_items NEXT s = s + wa-amount ).
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
## Rules
|
|
267
|
+
- BEFORE modifying existing objects, check version history (abap_object_versions) to verify alignment with PRD and detect pending transports from other developers
|
|
268
|
+
- ALWAYS use Hungarian notation prefixes (lv_, lt_, iv_, mv_, etc.)
|
|
269
|
+
- ALWAYS use `FINAL` on classes unless inheritance is explicitly needed
|
|
270
|
+
- ALWAYS use inline declarations: `DATA( )`, `FIELD-SYMBOL( )`
|
|
271
|
+
- ALWAYS use constructor expressions over imperative statements
|
|
272
|
+
- ALWAYS use string templates `| |` over CONCATENATE
|
|
273
|
+
- Methods: max ~30 lines, single responsibility
|
|
274
|
+
- Prefer RETURNING over EXPORTING for single output
|
|
275
|
+
- Prefer interfaces over concrete class references (dependency injection)
|
|
276
|
+
- Use `abap_bool` / `abap_true` / `abap_false` for booleans
|
|
277
|
+
- CDS: CamelCase fields, _Underscore associations
|
|
278
|
+
|
|
279
|
+
## Anti-Patterns
|
|
280
|
+
| Anti-Pattern | Correct |
|
|
281
|
+
|---|---|
|
|
282
|
+
| `DATA lv_x TYPE string. lv_x = 'hello'.` | `DATA(lv_x) = 'hello'.` |
|
|
283
|
+
| `CREATE OBJECT lo_ref TYPE zcl_class` | `DATA(lo_ref) = NEW zcl_class( )` |
|
|
284
|
+
| `MOVE-CORRESPONDING src TO tgt` | `tgt = CORRESPONDING #( src )` |
|
|
285
|
+
| `CONCATENATE a b INTO c` | `c = \|{ a }{ b }\|` |
|
|
286
|
+
| `IF lv_flag = 'X'` | `IF lv_flag = abap_true` |
|
|
287
|
+
| Variable name `lv_x`, `lv_tmp`, `lv_data` | Descriptive: `lv_order_status`, `lv_total_amount` |
|
|
288
|
+
| Method with 200+ lines | Split into focused helper methods |
|
|
289
|
+
| Public attributes modified externally | Private attributes + getter/setter methods |
|
|
290
|
+
| `CATCH cx_root` silently | Catch specific exceptions, always handle |
|
|
291
|
+
| Comments describing WHAT code does | Comment WHY for non-obvious decisions |
|
|
292
|
+
| `DATA lo_ref TYPE REF TO zcl_concrete` | `DATA lo_ref TYPE REF TO zif_interface` |
|
|
293
|
+
| Class without FINAL | Add FINAL unless subclassing is explicitly needed |
|