@linkup-ai/abap-ai 2.0.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 +384 -0
- package/dist/adt-client.js +364 -0
- package/dist/cli/activate.js +113 -0
- package/dist/cli/init.js +333 -0
- package/dist/cli/remove.js +80 -0
- package/dist/cli/status.js +229 -0
- package/dist/cli/systems.js +68 -0
- package/dist/cli.js +81 -0
- package/dist/index.js +1318 -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/logger.js +114 -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 +68 -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 +167 -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 +270 -0
- package/dist/tools/traces.js +66 -0
- package/dist/tools/transport-contents.js +83 -0
- package/dist/tools/transports.js +67 -0
- package/dist/tools/unit-test.js +135 -0
- package/dist/tools/where-used.js +59 -0
- package/dist/tools/write.js +101 -0
- package/package.json +49 -0
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
# Object Orientation — classes, interfaces, inheritance, events
|
|
2
|
+
|
|
3
|
+
## Class Definition
|
|
4
|
+
|
|
5
|
+
```abap
|
|
6
|
+
CLASS zcl_order_processor DEFINITION
|
|
7
|
+
PUBLIC FINAL CREATE PUBLIC.
|
|
8
|
+
|
|
9
|
+
PUBLIC SECTION.
|
|
10
|
+
TYPES: ty_order_id TYPE char10.
|
|
11
|
+
CONSTANTS: c_max_items TYPE i VALUE 999.
|
|
12
|
+
|
|
13
|
+
METHODS:
|
|
14
|
+
constructor IMPORTING iv_order_id TYPE ty_order_id,
|
|
15
|
+
process IMPORTING iv_input TYPE string
|
|
16
|
+
RETURNING VALUE(rv_result) TYPE string
|
|
17
|
+
RAISING zcx_order_error,
|
|
18
|
+
get_id RETURNING VALUE(rv_id) TYPE ty_order_id.
|
|
19
|
+
|
|
20
|
+
CLASS-METHODS:
|
|
21
|
+
factory IMPORTING iv_id TYPE ty_order_id
|
|
22
|
+
RETURNING VALUE(ro_inst) TYPE REF TO zcl_order_processor.
|
|
23
|
+
|
|
24
|
+
PROTECTED SECTION.
|
|
25
|
+
DATA mv_status TYPE char1.
|
|
26
|
+
METHODS validate.
|
|
27
|
+
|
|
28
|
+
PRIVATE SECTION.
|
|
29
|
+
DATA mv_order_id TYPE ty_order_id.
|
|
30
|
+
METHODS helper.
|
|
31
|
+
|
|
32
|
+
ENDCLASS.
|
|
33
|
+
|
|
34
|
+
CLASS zcl_order_processor IMPLEMENTATION.
|
|
35
|
+
|
|
36
|
+
METHOD constructor.
|
|
37
|
+
mv_order_id = iv_order_id.
|
|
38
|
+
ENDMETHOD.
|
|
39
|
+
|
|
40
|
+
METHOD process.
|
|
41
|
+
rv_result = |Processed: { iv_input }|.
|
|
42
|
+
ENDMETHOD.
|
|
43
|
+
|
|
44
|
+
METHOD get_id.
|
|
45
|
+
rv_id = mv_order_id.
|
|
46
|
+
ENDMETHOD.
|
|
47
|
+
|
|
48
|
+
METHOD factory.
|
|
49
|
+
ro_inst = NEW #( iv_id ).
|
|
50
|
+
ENDMETHOD.
|
|
51
|
+
|
|
52
|
+
METHOD validate.
|
|
53
|
+
ENDMETHOD.
|
|
54
|
+
|
|
55
|
+
METHOD helper.
|
|
56
|
+
ENDMETHOD.
|
|
57
|
+
|
|
58
|
+
ENDCLASS.
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Visibility
|
|
62
|
+
|
|
63
|
+
| Modifier | Class | Subclass | External |
|
|
64
|
+
|---|---|---|---|
|
|
65
|
+
| PUBLIC | Yes | Yes | Yes |
|
|
66
|
+
| PROTECTED | Yes | Yes | No |
|
|
67
|
+
| PRIVATE | Yes | No | No |
|
|
68
|
+
|
|
69
|
+
## Instantiation Control
|
|
70
|
+
|
|
71
|
+
```abap
|
|
72
|
+
CREATE PUBLIC " Anyone can instantiate
|
|
73
|
+
CREATE PROTECTED " Only class + subclasses
|
|
74
|
+
CREATE PRIVATE " Only within the class (use factory)
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Object Creation
|
|
78
|
+
|
|
79
|
+
```abap
|
|
80
|
+
" NEW operator — preferred
|
|
81
|
+
DATA(zo_proc) = NEW zcl_order_processor( iv_order_id = '1000' ).
|
|
82
|
+
|
|
83
|
+
" Inline chain
|
|
84
|
+
DATA(lv_result) = NEW zcl_order_processor( '1000' )->process( `data` ).
|
|
85
|
+
|
|
86
|
+
" Factory method
|
|
87
|
+
DATA(zo_inst) = zcl_order_processor=>factory( '1000' ).
|
|
88
|
+
|
|
89
|
+
" Static method call
|
|
90
|
+
zcl_utility=>execute( ).
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Method Signatures
|
|
94
|
+
|
|
95
|
+
```abap
|
|
96
|
+
METHODS process
|
|
97
|
+
IMPORTING iv_required TYPE string
|
|
98
|
+
iv_optional TYPE string OPTIONAL
|
|
99
|
+
iv_default TYPE i DEFAULT 10
|
|
100
|
+
EXPORTING ev_output TYPE string
|
|
101
|
+
CHANGING cv_data TYPE string
|
|
102
|
+
RETURNING VALUE(rv_result) TYPE string
|
|
103
|
+
RAISING zcx_my_exception.
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Interfaces
|
|
107
|
+
|
|
108
|
+
```abap
|
|
109
|
+
INTERFACE zif_processable PUBLIC.
|
|
110
|
+
TYPES ty_result TYPE string.
|
|
111
|
+
METHODS:
|
|
112
|
+
process IMPORTING iv_input TYPE string
|
|
113
|
+
RETURNING VALUE(rv_result) TYPE ty_result,
|
|
114
|
+
get_status RETURNING VALUE(rv_status) TYPE char1.
|
|
115
|
+
ENDINTERFACE.
|
|
116
|
+
|
|
117
|
+
CLASS zcl_impl DEFINITION PUBLIC FINAL CREATE PUBLIC.
|
|
118
|
+
PUBLIC SECTION.
|
|
119
|
+
INTERFACES zif_processable.
|
|
120
|
+
ALIASES process FOR zif_processable~process.
|
|
121
|
+
ALIASES get_status FOR zif_processable~get_status.
|
|
122
|
+
ENDCLASS.
|
|
123
|
+
|
|
124
|
+
CLASS zcl_impl IMPLEMENTATION.
|
|
125
|
+
METHOD zif_processable~process.
|
|
126
|
+
rv_result = |Done: { iv_input }|.
|
|
127
|
+
ENDMETHOD.
|
|
128
|
+
METHOD zif_processable~get_status.
|
|
129
|
+
rv_status = 'A'.
|
|
130
|
+
ENDMETHOD.
|
|
131
|
+
ENDCLASS.
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## Interface Usage + Polymorphism
|
|
135
|
+
|
|
136
|
+
```abap
|
|
137
|
+
" Program to interface, not implementation
|
|
138
|
+
DATA zo_proc TYPE REF TO zif_processable.
|
|
139
|
+
zo_proc = NEW zcl_impl_a( ).
|
|
140
|
+
zo_proc->process( `input` ). " Calls zcl_impl_a
|
|
141
|
+
|
|
142
|
+
zo_proc = NEW zcl_impl_b( ).
|
|
143
|
+
zo_proc->process( `input` ). " Calls zcl_impl_b
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Interface Inheritance
|
|
147
|
+
|
|
148
|
+
```abap
|
|
149
|
+
INTERFACE zif_extended PUBLIC.
|
|
150
|
+
INTERFACES zif_processable.
|
|
151
|
+
METHODS extended_method.
|
|
152
|
+
ENDINTERFACE.
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## Inheritance
|
|
156
|
+
|
|
157
|
+
```abap
|
|
158
|
+
CLASS zcl_child DEFINITION
|
|
159
|
+
INHERITING FROM zcl_parent
|
|
160
|
+
PUBLIC FINAL CREATE PUBLIC.
|
|
161
|
+
|
|
162
|
+
PUBLIC SECTION.
|
|
163
|
+
METHODS constructor IMPORTING iv_name TYPE string.
|
|
164
|
+
METHODS process REDEFINITION.
|
|
165
|
+
ENDCLASS.
|
|
166
|
+
|
|
167
|
+
CLASS zcl_child IMPLEMENTATION.
|
|
168
|
+
METHOD constructor.
|
|
169
|
+
super->constructor( iv_name ).
|
|
170
|
+
ENDMETHOD.
|
|
171
|
+
METHOD process.
|
|
172
|
+
super->process( ).
|
|
173
|
+
" Child-specific logic
|
|
174
|
+
ENDMETHOD.
|
|
175
|
+
ENDCLASS.
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Abstract Classes
|
|
179
|
+
|
|
180
|
+
```abap
|
|
181
|
+
CLASS zcl_base DEFINITION ABSTRACT PUBLIC.
|
|
182
|
+
PUBLIC SECTION.
|
|
183
|
+
METHODS concrete_method.
|
|
184
|
+
METHODS abstract_method ABSTRACT.
|
|
185
|
+
ENDCLASS.
|
|
186
|
+
|
|
187
|
+
CLASS zcl_concrete DEFINITION
|
|
188
|
+
INHERITING FROM zcl_base FINAL PUBLIC.
|
|
189
|
+
PUBLIC SECTION.
|
|
190
|
+
METHODS abstract_method REDEFINITION.
|
|
191
|
+
ENDCLASS.
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## Type Checking and Casting
|
|
195
|
+
|
|
196
|
+
```abap
|
|
197
|
+
" Instance check
|
|
198
|
+
IF zo_ref IS INSTANCE OF zif_processable.
|
|
199
|
+
DATA(zo_intf) = CAST zif_processable( zo_ref ).
|
|
200
|
+
ENDIF.
|
|
201
|
+
|
|
202
|
+
" Safe casting
|
|
203
|
+
TRY.
|
|
204
|
+
DATA(zo_specific) = CAST zcl_specific( zo_general ).
|
|
205
|
+
CATCH cx_sy_move_cast_error.
|
|
206
|
+
ENDTRY.
|
|
207
|
+
|
|
208
|
+
" RTTI
|
|
209
|
+
DATA(zo_descr) = CAST cl_abap_classdescr(
|
|
210
|
+
cl_abap_typedescr=>describe_by_object_ref( zo_ref ) ).
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## Events
|
|
214
|
+
|
|
215
|
+
```abap
|
|
216
|
+
" Publisher
|
|
217
|
+
CLASS zcl_publisher DEFINITION PUBLIC.
|
|
218
|
+
PUBLIC SECTION.
|
|
219
|
+
EVENTS data_changed
|
|
220
|
+
EXPORTING VALUE(ev_old) TYPE string
|
|
221
|
+
VALUE(ev_new) TYPE string.
|
|
222
|
+
METHODS set_data IMPORTING iv_data TYPE string.
|
|
223
|
+
PRIVATE SECTION.
|
|
224
|
+
DATA mv_data TYPE string.
|
|
225
|
+
ENDCLASS.
|
|
226
|
+
|
|
227
|
+
CLASS zcl_publisher IMPLEMENTATION.
|
|
228
|
+
METHOD set_data.
|
|
229
|
+
DATA(lv_old) = mv_data.
|
|
230
|
+
mv_data = iv_data.
|
|
231
|
+
RAISE EVENT data_changed
|
|
232
|
+
EXPORTING ev_old = lv_old ev_new = iv_data.
|
|
233
|
+
ENDMETHOD.
|
|
234
|
+
ENDCLASS.
|
|
235
|
+
|
|
236
|
+
" Subscriber
|
|
237
|
+
CLASS zcl_subscriber DEFINITION PUBLIC.
|
|
238
|
+
PUBLIC SECTION.
|
|
239
|
+
METHODS on_changed FOR EVENT data_changed OF zcl_publisher
|
|
240
|
+
IMPORTING ev_old ev_new sender.
|
|
241
|
+
ENDCLASS.
|
|
242
|
+
|
|
243
|
+
" Registration
|
|
244
|
+
SET HANDLER zo_subscriber->on_changed FOR zo_publisher.
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
## Exception Classes
|
|
248
|
+
|
|
249
|
+
```abap
|
|
250
|
+
CLASS zcx_order_error DEFINITION
|
|
251
|
+
INHERITING FROM cx_static_check
|
|
252
|
+
PUBLIC FINAL CREATE PUBLIC.
|
|
253
|
+
PUBLIC SECTION.
|
|
254
|
+
INTERFACES if_t100_message.
|
|
255
|
+
METHODS constructor
|
|
256
|
+
IMPORTING textid LIKE if_t100_message=>t100key OPTIONAL
|
|
257
|
+
previous LIKE previous OPTIONAL.
|
|
258
|
+
ENDCLASS.
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
## Friendship
|
|
262
|
+
|
|
263
|
+
```abap
|
|
264
|
+
CLASS zcl_private DEFINITION FRIENDS zcl_tester.
|
|
265
|
+
PRIVATE SECTION.
|
|
266
|
+
DATA mv_secret TYPE string.
|
|
267
|
+
ENDCLASS.
|
|
268
|
+
" zcl_tester can access mv_secret
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
---
|
|
272
|
+
|
|
273
|
+
## Rules
|
|
274
|
+
|
|
275
|
+
- Prefer FINAL unless inheritance is explicitly needed
|
|
276
|
+
- Program to interfaces, not implementations
|
|
277
|
+
- Use CREATE PRIVATE + factory method for controlled instantiation
|
|
278
|
+
- Use ALIASES to simplify interface method access
|
|
279
|
+
- Keep classes focused — Single Responsibility Principle
|
|
280
|
+
- Prefer composition over inheritance
|
|
281
|
+
- Use cx_static_check for expected errors, cx_no_check for programming errors
|
|
282
|
+
- RETURNING parameters enable functional chaining — prefer over EXPORTING when single output
|
|
283
|
+
- Use ABSTRACT for template method pattern
|
|
284
|
+
|
|
285
|
+
## Anti-Patterns
|
|
286
|
+
|
|
287
|
+
| Anti-Pattern | Correct Approach |
|
|
288
|
+
|---|---|
|
|
289
|
+
| `CREATE OBJECT oref TYPE zcl_class` | `NEW zcl_class( )` |
|
|
290
|
+
| Giant class with 50+ methods | Split into focused classes + interface |
|
|
291
|
+
| Public attributes modified externally | Use getter/setter methods |
|
|
292
|
+
| Deep inheritance hierarchy (3+ levels) | Composition + interfaces |
|
|
293
|
+
| Catching `cx_root` everywhere | Catch specific exception classes |
|
|
294
|
+
| Empty CATCH blocks | At minimum log the error |
|
|
295
|
+
| PROTECTED SECTION with many attributes | Keep PROTECTED minimal, prefer PRIVATE |
|
|
296
|
+
| Static methods accessing instance data | Use instance methods or pass data as parameters |
|
|
297
|
+
| Missing FINAL on leaf classes | Always add FINAL unless subclassing is intended |
|
|
298
|
+
| Using FRIENDS for production code | FRIENDS only for unit test access |
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
# ABAP Performance — SELECT, internal tables, buffering, code optimization
|
|
2
|
+
|
|
3
|
+
## SELECT Optimization
|
|
4
|
+
|
|
5
|
+
```abap
|
|
6
|
+
" ONLY needed fields (never SELECT *)
|
|
7
|
+
SELECT order_id, customer_id, status
|
|
8
|
+
FROM ztab_order
|
|
9
|
+
INTO TABLE @DATA(lt_orders).
|
|
10
|
+
|
|
11
|
+
" Use INTO TABLE (not ENDSELECT loop)
|
|
12
|
+
" BAD:
|
|
13
|
+
SELECT * FROM ztab_order INTO @DATA(ls_order).
|
|
14
|
+
" process row by row — very slow
|
|
15
|
+
ENDSELECT.
|
|
16
|
+
|
|
17
|
+
" GOOD:
|
|
18
|
+
SELECT * FROM ztab_order INTO TABLE @DATA(lt_orders).
|
|
19
|
+
LOOP AT lt_orders INTO DATA(ls_order).
|
|
20
|
+
" process in memory — much faster
|
|
21
|
+
ENDLOOP.
|
|
22
|
+
|
|
23
|
+
" Use JOIN instead of nested SELECT
|
|
24
|
+
" BAD:
|
|
25
|
+
SELECT * FROM ztab_order INTO TABLE @DATA(lt_orders).
|
|
26
|
+
LOOP AT lt_orders INTO DATA(ls_ord).
|
|
27
|
+
SELECT SINGLE name FROM ztab_customer
|
|
28
|
+
WHERE customer_id = @ls_ord-customer_id INTO @DATA(lv_name).
|
|
29
|
+
ENDLOOP.
|
|
30
|
+
|
|
31
|
+
" GOOD:
|
|
32
|
+
SELECT o~order_id, o~customer_id, c~name
|
|
33
|
+
FROM ztab_order AS o
|
|
34
|
+
INNER JOIN ztab_customer AS c ON o~customer_id = c~customer_id
|
|
35
|
+
INTO TABLE @DATA(lt_joined).
|
|
36
|
+
|
|
37
|
+
" Use FOR ALL ENTRIES (with empty check)
|
|
38
|
+
IF lt_keys IS NOT INITIAL.
|
|
39
|
+
SELECT * FROM ztab_detail
|
|
40
|
+
FOR ALL ENTRIES IN @lt_keys
|
|
41
|
+
WHERE order_id = @lt_keys-order_id
|
|
42
|
+
INTO TABLE @DATA(lt_details).
|
|
43
|
+
ENDIF.
|
|
44
|
+
|
|
45
|
+
" Use aggregation in SQL
|
|
46
|
+
" BAD:
|
|
47
|
+
SELECT * FROM ztab_order INTO TABLE @DATA(lt_all).
|
|
48
|
+
DATA(lv_sum) = REDUCE decfloat34( INIT s = 0
|
|
49
|
+
FOR wa IN lt_all NEXT s = s + wa-amount ).
|
|
50
|
+
|
|
51
|
+
" GOOD:
|
|
52
|
+
SELECT SINGLE SUM( amount ) FROM ztab_order INTO @DATA(lv_sum).
|
|
53
|
+
|
|
54
|
+
" PACKAGE SIZE for millions of rows
|
|
55
|
+
SELECT * FROM ztab_big INTO TABLE @DATA(lt_chunk) PACKAGE SIZE 10000.
|
|
56
|
+
" process chunk
|
|
57
|
+
CLEAR lt_chunk.
|
|
58
|
+
ENDSELECT.
|
|
59
|
+
|
|
60
|
+
" Existence check (not SELECT COUNT)
|
|
61
|
+
" BAD:
|
|
62
|
+
SELECT COUNT(*) FROM ztab_order WHERE order_id = @lv_id INTO @DATA(lv_cnt).
|
|
63
|
+
IF lv_cnt > 0.
|
|
64
|
+
|
|
65
|
+
" GOOD:
|
|
66
|
+
SELECT SINGLE @abap_true FROM ztab_order
|
|
67
|
+
WHERE order_id = @lv_id INTO @DATA(lv_exists).
|
|
68
|
+
IF lv_exists = abap_true.
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Internal Table Optimization
|
|
72
|
+
|
|
73
|
+
```abap
|
|
74
|
+
" Use correct table type for access pattern
|
|
75
|
+
" Sequential processing → STANDARD TABLE
|
|
76
|
+
" Frequent key lookup → SORTED TABLE (binary search O(log n))
|
|
77
|
+
" Hash lookup → HASHED TABLE (O(1))
|
|
78
|
+
|
|
79
|
+
" BAD: READ TABLE on STANDARD TABLE (linear scan O(n))
|
|
80
|
+
DATA lt_std TYPE STANDARD TABLE OF zs_item WITH EMPTY KEY.
|
|
81
|
+
READ TABLE lt_std WITH KEY order_id = lv_id INTO DATA(ls_found).
|
|
82
|
+
|
|
83
|
+
" GOOD: SORTED TABLE (binary search)
|
|
84
|
+
DATA lt_sorted TYPE SORTED TABLE OF zs_item WITH UNIQUE KEY order_id.
|
|
85
|
+
DATA(ls_found2) = lt_sorted[ order_id = lv_id ].
|
|
86
|
+
|
|
87
|
+
" GOOD: HASHED TABLE for large datasets
|
|
88
|
+
DATA lt_hashed TYPE HASHED TABLE OF zs_item WITH UNIQUE KEY order_id.
|
|
89
|
+
DATA(ls_found3) = lt_hashed[ order_id = lv_id ].
|
|
90
|
+
|
|
91
|
+
" Use FIELD-SYMBOL in LOOP (no copy)
|
|
92
|
+
" BAD:
|
|
93
|
+
LOOP AT lt_items INTO DATA(ls_item).
|
|
94
|
+
ls_item-amount = ls_item-amount * 1.1.
|
|
95
|
+
MODIFY lt_items FROM ls_item.
|
|
96
|
+
ENDLOOP.
|
|
97
|
+
|
|
98
|
+
" GOOD:
|
|
99
|
+
LOOP AT lt_items ASSIGNING FIELD-SYMBOL(<item>).
|
|
100
|
+
<item>-amount = <item>-amount * 1.1.
|
|
101
|
+
ENDLOOP.
|
|
102
|
+
|
|
103
|
+
" Use secondary keys for multiple access patterns
|
|
104
|
+
DATA lt_multi TYPE TABLE OF zs_item
|
|
105
|
+
WITH EMPTY KEY
|
|
106
|
+
WITH NON-UNIQUE SORTED KEY by_customer COMPONENTS customer_id
|
|
107
|
+
WITH UNIQUE HASHED KEY by_id COMPONENTS order_id.
|
|
108
|
+
|
|
109
|
+
DATA(ls_by_id) = lt_multi[ KEY by_id order_id = '1000' ].
|
|
110
|
+
LOOP AT lt_multi USING KEY by_customer ASSIGNING FIELD-SYMBOL(<fs>)
|
|
111
|
+
WHERE customer_id = 'CUST100'.
|
|
112
|
+
ENDLOOP.
|
|
113
|
+
|
|
114
|
+
" Use FILTER (requires sorted/hashed key)
|
|
115
|
+
DATA(lt_active) = FILTER #( lt_multi USING KEY by_customer
|
|
116
|
+
WHERE customer_id = 'CUST100' ).
|
|
117
|
+
|
|
118
|
+
" DELETE ADJACENT DUPLICATES — SORT first
|
|
119
|
+
SORT lt_items BY order_id.
|
|
120
|
+
DELETE ADJACENT DUPLICATES FROM lt_items COMPARING order_id.
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Avoid Nested Loops
|
|
124
|
+
|
|
125
|
+
```abap
|
|
126
|
+
" BAD: O(n*m) — nested LOOP
|
|
127
|
+
LOOP AT lt_orders INTO DATA(ls_order).
|
|
128
|
+
LOOP AT lt_items INTO DATA(ls_item) WHERE order_id = ls_order-order_id.
|
|
129
|
+
" process
|
|
130
|
+
ENDLOOP.
|
|
131
|
+
ENDLOOP.
|
|
132
|
+
|
|
133
|
+
" GOOD: O(n+m) — GROUP BY
|
|
134
|
+
LOOP AT lt_items INTO DATA(ls_rep)
|
|
135
|
+
GROUP BY ( order_id = ls_rep-order_id )
|
|
136
|
+
ASSIGNING FIELD-SYMBOL(<group>).
|
|
137
|
+
LOOP AT GROUP <group> ASSIGNING FIELD-SYMBOL(<member>).
|
|
138
|
+
" process
|
|
139
|
+
ENDLOOP.
|
|
140
|
+
ENDLOOP.
|
|
141
|
+
|
|
142
|
+
" GOOD: O(n*log m) — SORTED TABLE inner
|
|
143
|
+
DATA lt_items_sorted TYPE SORTED TABLE OF zs_item WITH NON-UNIQUE KEY order_id.
|
|
144
|
+
lt_items_sorted = lt_items.
|
|
145
|
+
LOOP AT lt_orders INTO ls_order.
|
|
146
|
+
LOOP AT lt_items_sorted INTO ls_item
|
|
147
|
+
WHERE order_id = ls_order-order_id.
|
|
148
|
+
" binary search on first access
|
|
149
|
+
ENDLOOP.
|
|
150
|
+
ENDLOOP.
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## String Optimization
|
|
154
|
+
|
|
155
|
+
```abap
|
|
156
|
+
" Use string templates (not CONCATENATE for multiple joins)
|
|
157
|
+
DATA(lv_msg) = |Order { lv_id } for { lv_customer }|.
|
|
158
|
+
|
|
159
|
+
" For large string building, use string_table + CONCATENATE LINES OF
|
|
160
|
+
DATA lt_lines TYPE string_table.
|
|
161
|
+
LOOP AT lt_data INTO DATA(ls_data).
|
|
162
|
+
APPEND |{ ls_data-field1 },{ ls_data-field2 }| TO lt_lines.
|
|
163
|
+
ENDLOOP.
|
|
164
|
+
CONCATENATE LINES OF lt_lines INTO DATA(lv_csv) SEPARATED BY cl_abap_char_utilities=>newline.
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## Buffering Hints
|
|
168
|
+
|
|
169
|
+
```abap
|
|
170
|
+
" CDS View — enable buffering
|
|
171
|
+
@AbapCatalog.buffering.status: #ACTIVE
|
|
172
|
+
@AbapCatalog.buffering.type: #FULL " Entire table cached
|
|
173
|
+
@AbapCatalog.buffering.type: #SINGLE " By primary key
|
|
174
|
+
@AbapCatalog.buffering.type: #GENERIC " By n key fields
|
|
175
|
+
@AbapCatalog.buffering.numberOfKeyFields: 2 " For GENERIC
|
|
176
|
+
|
|
177
|
+
" ABAP — bypass buffer when needed
|
|
178
|
+
SELECT SINGLE * FROM ztab BYPASSING BUFFER WHERE id = @lv_id INTO @DATA(ls).
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
## Parallel Processing
|
|
182
|
+
|
|
183
|
+
```abap
|
|
184
|
+
" AMDP / CDS for DB-level parallel processing
|
|
185
|
+
" Background jobs for long-running tasks
|
|
186
|
+
|
|
187
|
+
" NEW with async RFC (only when truly needed)
|
|
188
|
+
CALL FUNCTION 'ZFUNC' STARTING NEW TASK 'TASK1'
|
|
189
|
+
PERFORMING callback ON END OF TASK
|
|
190
|
+
EXPORTING iv_param = lv_value.
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## Rules
|
|
194
|
+
- SELECT only needed fields — `SELECT *` reads unnecessary data
|
|
195
|
+
- INTO TABLE, not ENDSELECT — avoid row-by-row processing
|
|
196
|
+
- JOIN instead of SELECT in LOOP — single DB roundtrip
|
|
197
|
+
- FOR ALL ENTRIES: always check IS NOT INITIAL before
|
|
198
|
+
- Aggregation in SQL, not in ABAP — let the DB do the math
|
|
199
|
+
- SORTED/HASHED tables for frequent key lookups
|
|
200
|
+
- FIELD-SYMBOL in LOOP for modification — no copy overhead
|
|
201
|
+
- PACKAGE SIZE for millions of rows — avoid memory overflow
|
|
202
|
+
- Existence check: `SELECT SINGLE @abap_true` instead of `COUNT(*)`
|
|
203
|
+
|
|
204
|
+
## Anti-Patterns
|
|
205
|
+
| Anti-Pattern | Correct |
|
|
206
|
+
|---|---|
|
|
207
|
+
| `SELECT *` in production | Select only needed fields |
|
|
208
|
+
| `SELECT ... ENDSELECT` (row by row) | `SELECT ... INTO TABLE` |
|
|
209
|
+
| SELECT inside LOOP | JOIN or FOR ALL ENTRIES |
|
|
210
|
+
| FOR ALL ENTRIES without empty check | `IF itab IS NOT INITIAL` |
|
|
211
|
+
| `LOOP INTO DATA(wa)` for modification | `LOOP ASSIGNING FIELD-SYMBOL(<fs>)` |
|
|
212
|
+
| Nested LOOP for lookup O(n*m) | HASHED/SORTED table or GROUP BY |
|
|
213
|
+
| `SELECT COUNT(*)` for existence | `SELECT SINGLE @abap_true` |
|
|
214
|
+
| Aggregation in ABAP LOOP | `SELECT SUM/AVG/COUNT` in SQL |
|
|
215
|
+
| STANDARD TABLE + READ TABLE (linear) | SORTED TABLE (binary) or HASHED (hash) |
|
|
216
|
+
| `CONCATENATE` in LOOP for large strings | Collect in string_table, join once |
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
# RAP Abstract Entities — action parameters and function returns
|
|
2
|
+
|
|
3
|
+
## What They Are
|
|
4
|
+
|
|
5
|
+
Abstract entities define structured types without DB persistence. Used for:
|
|
6
|
+
- Action input parameters
|
|
7
|
+
- Action/function return types
|
|
8
|
+
- Complex result structures
|
|
9
|
+
|
|
10
|
+
## Defining Abstract Entity
|
|
11
|
+
|
|
12
|
+
```abap
|
|
13
|
+
@EndUserText.label: 'Action Parameter: Reject Reason'
|
|
14
|
+
define abstract entity ZA_RejectParams
|
|
15
|
+
{
|
|
16
|
+
reason : abap.char(256);
|
|
17
|
+
note : abap.string;
|
|
18
|
+
reject_date : abap.dats;
|
|
19
|
+
}
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
```abap
|
|
23
|
+
@EndUserText.label: 'Action Result: Confirmation'
|
|
24
|
+
define abstract entity ZA_ConfirmResult
|
|
25
|
+
{
|
|
26
|
+
order_id : abap.numc(10);
|
|
27
|
+
status : abap.char(1);
|
|
28
|
+
message : abap.char(256);
|
|
29
|
+
changed_at : abp_lastchange_tstmpl;
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Using in BDEF — Action with Parameters
|
|
34
|
+
|
|
35
|
+
```abap
|
|
36
|
+
define behavior for ZI_Order alias Order
|
|
37
|
+
{
|
|
38
|
+
" Action with input parameter
|
|
39
|
+
action rejectOrder parameter ZA_RejectParams result [1] $self;
|
|
40
|
+
|
|
41
|
+
" Action with result type (not $self)
|
|
42
|
+
action confirmOrder result [1] ZA_ConfirmResult;
|
|
43
|
+
|
|
44
|
+
" Action with parameter AND custom result
|
|
45
|
+
action processOrder parameter ZA_ProcessParams result [1] ZA_ProcessResult;
|
|
46
|
+
|
|
47
|
+
" Action without parameter, with result
|
|
48
|
+
action acceptOrder result [1] $self;
|
|
49
|
+
|
|
50
|
+
" Action without parameter, without result
|
|
51
|
+
action cancelOrder;
|
|
52
|
+
|
|
53
|
+
" Static action with parameter
|
|
54
|
+
static action bulkProcess parameter ZA_BulkParams result [0..*] ZA_BulkResult;
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Handler — Action with Parameter
|
|
59
|
+
|
|
60
|
+
```abap
|
|
61
|
+
METHOD rejectOrder.
|
|
62
|
+
" req.data contains the parameter fields
|
|
63
|
+
" keys contains the entity keys
|
|
64
|
+
|
|
65
|
+
MODIFY ENTITIES OF ZI_Order IN LOCAL MODE
|
|
66
|
+
ENTITY Order
|
|
67
|
+
UPDATE FIELDS ( Status RejectReason RejectDate )
|
|
68
|
+
WITH VALUE #( FOR key IN keys
|
|
69
|
+
( %tky = key-%tky
|
|
70
|
+
Status = 'X'
|
|
71
|
+
RejectReason = key-%param-reason
|
|
72
|
+
RejectDate = key-%param-reject_date ) )
|
|
73
|
+
FAILED failed
|
|
74
|
+
REPORTED reported.
|
|
75
|
+
|
|
76
|
+
" Return updated instance
|
|
77
|
+
READ ENTITIES OF ZI_Order IN LOCAL MODE
|
|
78
|
+
ENTITY Order ALL FIELDS
|
|
79
|
+
WITH CORRESPONDING #( keys )
|
|
80
|
+
RESULT DATA(orders).
|
|
81
|
+
|
|
82
|
+
result = VALUE #( FOR order IN orders
|
|
83
|
+
( %tky = order-%tky %param = order ) ).
|
|
84
|
+
ENDMETHOD.
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Handler — Action with Custom Result
|
|
88
|
+
|
|
89
|
+
```abap
|
|
90
|
+
METHOD confirmOrder.
|
|
91
|
+
MODIFY ENTITIES OF ZI_Order IN LOCAL MODE
|
|
92
|
+
ENTITY Order
|
|
93
|
+
UPDATE FIELDS ( Status )
|
|
94
|
+
WITH VALUE #( FOR key IN keys
|
|
95
|
+
( %tky = key-%tky Status = 'A' ) )
|
|
96
|
+
FAILED failed
|
|
97
|
+
REPORTED reported.
|
|
98
|
+
|
|
99
|
+
READ ENTITIES OF ZI_Order IN LOCAL MODE
|
|
100
|
+
ENTITY Order FIELDS ( OrderID Status LastChangedAt )
|
|
101
|
+
WITH CORRESPONDING #( keys )
|
|
102
|
+
RESULT DATA(orders).
|
|
103
|
+
|
|
104
|
+
result = VALUE #( FOR order IN orders
|
|
105
|
+
( %tky = order-%tky
|
|
106
|
+
%param = VALUE ZA_ConfirmResult(
|
|
107
|
+
order_id = order-OrderID
|
|
108
|
+
status = order-Status
|
|
109
|
+
message = |Order { order-OrderID } confirmed|
|
|
110
|
+
changed_at = order-LastChangedAt ) ) ).
|
|
111
|
+
ENDMETHOD.
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Handler — Static Action with Parameter
|
|
115
|
+
|
|
116
|
+
```abap
|
|
117
|
+
METHOD bulkProcess.
|
|
118
|
+
" Static action — no entity keys, only parameter data
|
|
119
|
+
DATA(lv_params) = keys[ 1 ]-%param.
|
|
120
|
+
|
|
121
|
+
" Process based on parameter
|
|
122
|
+
SELECT * FROM ztab_order
|
|
123
|
+
WHERE status = @lv_params-filter_status
|
|
124
|
+
INTO TABLE @DATA(lt_orders).
|
|
125
|
+
|
|
126
|
+
" ... process orders ...
|
|
127
|
+
|
|
128
|
+
result = VALUE #( FOR order IN lt_orders
|
|
129
|
+
( %param = VALUE ZA_BulkResult(
|
|
130
|
+
order_id = order-order_id
|
|
131
|
+
processed = abap_true ) ) ).
|
|
132
|
+
ENDMETHOD.
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Abstract Entity with Associations (for complex results)
|
|
136
|
+
|
|
137
|
+
```abap
|
|
138
|
+
@EndUserText.label: 'Order Summary Result'
|
|
139
|
+
define abstract entity ZA_OrderSummary
|
|
140
|
+
{
|
|
141
|
+
order_id : abap.numc(10);
|
|
142
|
+
customer_id : kunnr;
|
|
143
|
+
total_amount : abap.curr(17,2);
|
|
144
|
+
currency_code : abap.cuky(5);
|
|
145
|
+
item_count : abap.int4;
|
|
146
|
+
status_text : abap.char(20);
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## Projection BDEF — Exposing Actions with Parameters
|
|
151
|
+
|
|
152
|
+
```abap
|
|
153
|
+
projection;
|
|
154
|
+
strict ( 2 );
|
|
155
|
+
use draft;
|
|
156
|
+
|
|
157
|
+
define behavior for ZC_Order alias Order
|
|
158
|
+
use etag
|
|
159
|
+
{
|
|
160
|
+
use create; use update; use delete;
|
|
161
|
+
use action Edit; use action Activate; use action Discard;
|
|
162
|
+
use action Resume; use action Prepare;
|
|
163
|
+
|
|
164
|
+
use action rejectOrder; " Parameter inherited from interface
|
|
165
|
+
use action confirmOrder; " Result type inherited from interface
|
|
166
|
+
use action acceptOrder;
|
|
167
|
+
use action bulkProcess;
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Fiori UI — Action Dialog for Parameters
|
|
172
|
+
|
|
173
|
+
When an action has a parameter, Fiori Elements automatically generates a dialog with input fields for the abstract entity's fields.
|
|
174
|
+
|
|
175
|
+
```abap
|
|
176
|
+
" Metadata Extension — customize action parameter dialog
|
|
177
|
+
@Metadata.layer: #CORE
|
|
178
|
+
annotate entity ZA_RejectParams with
|
|
179
|
+
{
|
|
180
|
+
@UI.defaultValue: 'Rejected by user'
|
|
181
|
+
reason;
|
|
182
|
+
|
|
183
|
+
@UI.hidden: true
|
|
184
|
+
reject_date;
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## Rules
|
|
189
|
+
- Abstract entities: `define abstract entity` — no DB table, no persistence
|
|
190
|
+
- Use for action parameters when more than 1-2 simple fields needed
|
|
191
|
+
- `$self` returns the entity itself; custom abstract entity returns different structure
|
|
192
|
+
- `result [1]` = exactly one result; `result [0..*]` = multiple results
|
|
193
|
+
- `%param` in handler: `key-%param-fieldname` for parameter fields
|
|
194
|
+
- Static actions: no entity key, parameter accessed via `keys[ 1 ]-%param`
|
|
195
|
+
- Abstract entities can use data elements for labels and search helps
|
|
196
|
+
- Fiori auto-generates dialog for action parameters based on abstract entity fields
|
|
197
|
+
|
|
198
|
+
## Anti-Patterns
|
|
199
|
+
| Anti-Pattern | Correct |
|
|
200
|
+
|---|---|
|
|
201
|
+
| Using STRING for action params that need structure | Define abstract entity |
|
|
202
|
+
| `result [1] $self` when return differs from entity | Use custom abstract entity as result |
|
|
203
|
+
| Accessing `keys-%param` without checking keys is not empty | Guard with `IF keys IS NOT INITIAL` |
|
|
204
|
+
| Abstract entity with too many fields (>10) | Keep focused — split into multiple if complex |
|
|
205
|
+
| Missing labels on abstract entity fields | Use data elements or `@EndUserText.label` |
|
|
206
|
+
| Forgetting to `use action` in projection BDEF | Action not available in Fiori |
|