"RAP Side Effects : Mises à jour automatiques de l

Catégorie
RAP
Publié
Auteur
Johannes

Les Side Effects dans RAP définissent quels éléments de l’UI doivent être actualisés lorsque les valeurs des champs changent ou que des actions sont exécutées. Ils assurent une interface utilisateur réactive sans rechargement manuel.

Pourquoi les Side Effects ?

Les Side Effects répondent à des questions telles que :

  • Quels champs doivent être actualisés lorsque le prix change ?
  • Quelles zones de l’UI doivent être rechargées après une action ?
  • Comment les champs calculés sont-ils automatiquement actualisés ?

Cas d’usage typiques

ScénarioDéclencheurChamps affectés
Calcul de prixQuantité, Prix unitairePrix total
Calcul de dateDate de début ou de finDurée, Jours ouvrables
Conversion de deviseDeviseTous les champs de montant
Changement de statutExécution d’actionStatut, Disponibilité

Side Effects dans la Behavior Definition

Les Side Effects sont définis de manière déclarative dans la Behavior Definition :

managed implementation in class zbp_i_travel unique;
strict ( 2 );
define behavior for ZI_Travel alias Travel
persistent table ztravel
lock master
authorization master ( instance )
etag master LastChangedAt
{
create;
update;
delete;
// Side Effects Block
side effects
{
// Field-Level Side Effects
field BeginDate affects field Duration;
field EndDate affects field Duration;
// Action-Level Side Effects
action calculatePrice affects field TotalPrice, field Currency;
// Determination Side Effects
determine action Prepare affects field Status;
}
}

Side Effects au niveau des champs

Les Side Effects au niveau des champs définissent quels champs sont actualisés lorsqu’un champ spécifique change.

Side Effect de champ simple

side effects
{
// Wenn BeginDate sich ändert, aktualisiere Duration
field BeginDate affects field Duration;
// Wenn EndDate sich ändert, aktualisiere Duration
field EndDate affects field Duration;
}

Plusieurs champs déclencheurs

side effects
{
// Mehrere Felder triggern die gleiche Aktualisierung
field ( BeginDate, EndDate ) affects field Duration;
// Preis-Berechnung bei Mengen- oder Preisänderung
field ( Quantity, UnitPrice ) affects field TotalPrice;
}

Plusieurs champs affectés

side effects
{
// Ein Trigger-Feld beeinflusst mehrere Zielfelder
field Quantity affects field TotalPrice, field TaxAmount, field NetPrice;
// Währungsänderung beeinflusst alle Betragsfelder
field CurrencyCode affects field TotalPrice, field TaxAmount, field Discount;
}

$self - L’instance entière

Avec $self, l’instance entière est marquée comme affectée :

side effects
{
// Währungsänderung: Alle Felder neu laden
field CurrencyCode affects $self;
// Kundenänderung: Gesamte Instanz aktualisieren
field CustomerId affects $self;
}

Side Effects au niveau des actions

Les Side Effects au niveau des actions définissent quels champs sont actualisés après une action.

define behavior for ZI_Travel alias Travel
{
// Aktionen definieren
action calculatePrice result [1] $self;
action applyDiscount result [1] $self;
action setStatus result [1] $self;
side effects
{
// Nach Preisberechnung diese Felder aktualisieren
action calculatePrice affects field TotalPrice, field TaxAmount;
// Nach Rabatt-Anwendung
action applyDiscount affects field TotalPrice, field DiscountAmount;
// Statusänderung beeinflusst Status-Feld
action setStatus affects field Status;
}
}

Action avec Side Effects complexes

side effects
{
// Action beeinflusst mehrere Bereiche
action recalculateAll affects
field TotalPrice,
field TaxAmount,
field NetPrice,
field Currency,
entity _Bookings; // Auch Assoziationen
// Action beeinflusst gesamte Entität
action copyFromTemplate affects $self;
}

Side Effects de détermination

Lorsque les Determinations sont exécutées, les Side Effects peuvent informer l’UI des valeurs calculées.

Behavior Definition

define behavior for ZI_Travel alias Travel
{
// Determination für Preisberechnung
determination calculateTotalPrice on modify { field Quantity; field UnitPrice; }
// Determination für Status
determination setInitialStatus on modify { create; }
side effects
{
// Wenn calculateTotalPrice auf Quantity-Änderung ausgeführt wird
determine action calculateTotalPrice executed on field Quantity
affects field TotalPrice;
// Wenn calculateTotalPrice auf UnitPrice-Änderung ausgeführt wird
determine action calculateTotalPrice executed on field UnitPrice
affects field TotalPrice;
}
}

Exemple complet avec Determination

managed implementation in class zbp_i_travel unique;
strict ( 2 );
define behavior for ZI_Travel alias Travel
persistent table ztravel
{
create;
update;
delete;
// Determinations
determination calculateDuration on modify { field BeginDate; field EndDate; }
determination calculatePrice on modify { field Quantity; field UnitPrice; field CurrencyCode; }
side effects
{
// Duration-Berechnung
determine action calculateDuration executed on field BeginDate
affects field Duration;
determine action calculateDuration executed on field EndDate
affects field Duration;
// Preis-Berechnung
determine action calculatePrice executed on field Quantity
affects field TotalPrice, field TaxAmount;
determine action calculatePrice executed on field UnitPrice
affects field TotalPrice, field TaxAmount;
determine action calculatePrice executed on field CurrencyCode
affects field TotalPrice, field TaxAmount, field Currency;
}
}

Implémentation de la Determination

CLASS lhc_travel DEFINITION INHERITING FROM cl_abap_behavior_handler.
PRIVATE SECTION.
METHODS calculateDuration FOR DETERMINE ON MODIFY
IMPORTING keys FOR Travel~calculateDuration.
METHODS calculatePrice FOR DETERMINE ON MODIFY
IMPORTING keys FOR Travel~calculatePrice.
ENDCLASS.
CLASS lhc_travel IMPLEMENTATION.
METHOD calculateDuration.
READ ENTITIES OF zi_travel IN LOCAL MODE
ENTITY Travel
FIELDS ( BeginDate EndDate )
WITH CORRESPONDING #( keys )
RESULT DATA(lt_travel).
MODIFY ENTITIES OF zi_travel IN LOCAL MODE
ENTITY Travel
UPDATE FIELDS ( Duration )
WITH VALUE #( FOR ls_travel IN lt_travel
WHERE ( BeginDate IS NOT INITIAL AND EndDate IS NOT INITIAL )
( %tky = ls_travel-%tky
Duration = ls_travel-EndDate - ls_travel-BeginDate ) )
REPORTED reported.
ENDMETHOD.
METHOD calculatePrice.
READ ENTITIES OF zi_travel IN LOCAL MODE
ENTITY Travel
FIELDS ( Quantity UnitPrice CurrencyCode )
WITH CORRESPONDING #( keys )
RESULT DATA(lt_travel).
MODIFY ENTITIES OF zi_travel IN LOCAL MODE
ENTITY Travel
UPDATE FIELDS ( TotalPrice TaxAmount Currency )
WITH VALUE #( FOR ls_travel IN lt_travel
LET lv_total = ls_travel-Quantity * ls_travel-UnitPrice
lv_tax = lv_total * '0.19"
IN
( %tky = ls_travel-%tky
TotalPrice = lv_total
TaxAmount = lv_tax
Currency = ls_travel-CurrencyCode ) )
REPORTED reported.
ENDMETHOD.
ENDCLASS.

Side Effects avec associations

Les Side Effects peuvent également affecter les associations :

define behavior for ZI_Travel alias Travel
{
association _Bookings { create; }
side effects
{
// Änderungen an Bookings beeinflussen Travel
field _Bookings affects field TotalPrice, field BookingCount;
// Währungsänderung in Travel beeinflusst alle Bookings
field CurrencyCode affects entity _Bookings;
}
}
define behavior for ZI_Booking alias Booking
{
association _Travel;
side effects
{
// Preis in Booking beeinflusst Gesamtpreis in Travel
field Price affects field _Travel.TotalPrice;
}
}

Side Effects hiérarchiques

define behavior for ZI_Travel alias Travel
{
side effects
{
// Alle Bookings aktualisieren wenn sich Währung ändert
field CurrencyCode affects entity _Bookings, entity _Passengers;
// Nach Copy-Action alle Child-Entitäten neu laden
action copyWithDetails affects $self, entity _Bookings, entity _Passengers;
}
}

Champs cibles et $self

Champs cibles individuels

side effects
{
field Quantity affects field TotalPrice;
}

Plusieurs champs cibles

side effects
{
field Quantity affects field TotalPrice, field TaxAmount, field NetPrice;
}

Entité complète ($self)

side effects
{
// Bei Statusänderung: Komplette Instanz neu laden
field Status affects $self;
// Bei Kopie: Alles aktualisieren
action copy affects $self;
}

Entity (Associations)

side effects
{
// Child-Entitäten aktualisieren
field CurrencyCode affects entity _Bookings;
// Parent-Entität aktualisieren
field BookingPrice affects entity _Travel;
}

Exemple complet

managed implementation in class zbp_i_travel unique;
strict ( 2 );
define behavior for ZI_Travel alias Travel
persistent table ztravel
draft table zdraft_travel
lock master total etag LastChangedAt
authorization master ( instance )
etag master LastChangedAt
{
create;
update;
delete;
// Felder
field ( readonly ) TravelId, CreatedBy, CreatedAt;
field ( mandatory ) CustomerId;
// Assoziationen
association _Bookings { create; }
// Determinations
determination calculateDuration on modify { field BeginDate; field EndDate; }
determination calculateTotalPrice on modify { field _Bookings; }
determination setInitialStatus on modify { create; }
// Actions
action ( features: instance ) acceptTravel result [1] $self;
action recalculatePrice result [1] $self;
// Side Effects
side effects
{
// Field-Level
field BeginDate affects field Duration, field DaysUntilStart;
field EndDate affects field Duration;
field CustomerId affects field CustomerName, field CustomerRating;
// Währung beeinflusst alle Betragsfelder
field CurrencyCode affects
field TotalPrice,
field TaxAmount,
entity _Bookings;
// Determination Side Effects
determine action calculateDuration executed on field BeginDate
affects field Duration;
determine action calculateDuration executed on field EndDate
affects field Duration;
determine action calculateTotalPrice executed on field _Bookings
affects field TotalPrice, field BookingCount;
// Action Side Effects
action acceptTravel affects field Status, field ApprovedAt, field ApprovedBy;
action recalculatePrice affects field TotalPrice, field TaxAmount, entity _Bookings;
}
}
define behavior for ZI_Booking alias Booking
persistent table zbooking
draft table zdraft_booking
lock dependent by _Travel
authorization dependent by _Travel
etag master LastChangedAt
{
create;
update;
delete;
association _Travel;
side effects
{
// Preis-Änderung in Booking aktualisiert Travel-Summe
field Price affects field _Travel.TotalPrice;
}
}

Bonnes pratiques

  1. Side Effects minimaux : Définissez uniquement les Side Effects réellement nécessaires - trop nombreux peuvent affecter la performance

  2. Champs spécifiques au lieu de $self : Utilisez $self uniquement si l’entité entière est vraiment affectée

  3. Determination + Side Effect : Combinez Determinations avec Side Effects pour les calculs automatiques

  4. Associations bidirectionnelles : Faites attention à la direction correcte des Side Effects dans les relations Parent-Child

  5. Performance : Les Side Effects déclenchent des requêtes UI - testez la performance dans des scénarios complexes

  6. Cohérence : Assurez-vous que les définitions de Side Effect correspondent à la logique réelle

" RICHTIG: Side Effect passt zur Determination
determination calculateTotal on modify { field Quantity; field Price; }
side effects
{
determine action calculateTotal executed on field Quantity affects field TotalPrice;
determine action calculateTotal executed on field Price affects field TotalPrice;
}
" FALSCH: Side Effect ohne entsprechende Berechnung
side effects
{
field Quantity affects field TotalPrice; " Wer berechnet TotalPrice?
}

Sujets avancés