RAP Side Effects: Actualizaciones automáticas de UI

Kategorie
RAP
Veröffentlicht
Autor
Johannes

Side Effects en RAP definen qué elementos de UI deben actualizarse cuando cambian valores de campos o se ejecutan acciones. Aseguran una interfaz de usuario reactiva sin necesidad de recargar manualmente.

¿Para qué Side Effects?

Los Side Effects responden preguntas como:

  • ¿Qué campos deben actualizarse cuando cambia el precio?
  • ¿Qué áreas de la UI deben recargarse después de una acción?
  • ¿Cómo se actualizan automáticamente los campos calculados?

Casos de uso típicos

EscenarioTriggerCampos afectados
Cálculo de precioCantidad, precio unitarioPrecio total
Cálculo de fechasFecha inicio o finDuración, días laborables
Conversión de monedaMonedaTodos los campos de monto
Cambio de estadoEjecutar ActionEstado, disponibilidad

Side Effects en la Behavior Definition

Los Side Effects se definen declarativamente en 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;
// Bloque Side Effects
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;
}
}

Field-Level Side Effects

Los Field-Level Side Effects definen qué campos se actualizan cuando cambia un campo específico.

Simple Field Side Effect

side effects
{
// Cuando BeginDate cambia, actualizar Duration
field BeginDate affects field Duration;
// Cuando EndDate cambia, actualizar Duration
field EndDate affects field Duration;
}

Múltiples campos trigger

side effects
{
// Múltiples campos disparan la misma actualización
field ( BeginDate, EndDate ) affects field Duration;
// Cálculo de precio con cambio de cantidad o precio
field ( Quantity, UnitPrice ) affects field TotalPrice;
}

Múltiples campos afectados

side effects
{
// Un campo trigger afecta múltiples campos destino
field Quantity affects field TotalPrice, field TaxAmount, field NetPrice;
// Cambio de moneda afecta todos los campos de monto
field CurrencyCode affects field TotalPrice, field TaxAmount, field Discount;
}

$self - La instancia completa

Con $self se marca toda la instancia como afectada:

side effects
{
// Cambio de moneda: Recargar todos los campos
field CurrencyCode affects $self;
// Cambio de cliente: Actualizar instancia completa
field CustomerId affects $self;
}

Action-Level Side Effects

Los Action-Level Side Effects definen qué campos se actualizan después de una acción.

define behavior for ZI_Travel alias Travel
{
// Definir acciones
action calculatePrice result [1] $self;
action applyDiscount result [1] $self;
action setStatus result [1] $self;
side effects
{
// Después de cálculo de precio, actualizar estos campos
action calculatePrice affects field TotalPrice, field TaxAmount;
// Después de aplicar descuento
action applyDiscount affects field TotalPrice, field DiscountAmount;
// Cambio de estado afecta campo Status
action setStatus affects field Status;
}
}

Action con Side Effects complejos

side effects
{
// Action afecta múltiples áreas
action recalculateAll affects
field TotalPrice,
field TaxAmount,
field NetPrice,
field Currency,
entity _Bookings; // También asociaciones
// Action afecta entidad completa
action copyFromTemplate affects $self;
}

Determination Side Effects

Cuando se ejecutan Determinations, los Side Effects pueden informar a la UI sobre valores calculados.

Behavior Definition

define behavior for ZI_Travel alias Travel
{
// Determination para cálculo de precio
determination calculateTotalPrice on modify { field Quantity; field UnitPrice; }
// Determination para estado
determination setInitialStatus on modify { create; }
side effects
{
// Cuando calculateTotalPrice se ejecuta por cambio de Quantity
determine action calculateTotalPrice executed on field Quantity
affects field TotalPrice;
// Cuando calculateTotalPrice se ejecuta por cambio de UnitPrice
determine action calculateTotalPrice executed on field UnitPrice
affects field TotalPrice;
}
}

Ejemplo completo con 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
{
// Cálculo de duración
determine action calculateDuration executed on field BeginDate
affects field Duration;
determine action calculateDuration executed on field EndDate
affects field Duration;
// Cálculo de precio
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;
}
}

Implementación 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 con Asociaciones

Los Side Effects también pueden afectar asociaciones:

define behavior for ZI_Travel alias Travel
{
association _Bookings { create; }
side effects
{
// Cambios en Bookings afectan Travel
field _Bookings affects field TotalPrice, field BookingCount;
// Cambio de moneda en Travel afecta todos los Bookings
field CurrencyCode affects entity _Bookings;
}
}
define behavior for ZI_Booking alias Booking
{
association _Travel;
side effects
{
// Precio en Booking afecta precio total en Travel
field Price affects field _Travel.TotalPrice;
}
}

Side Effects jerárquicos

define behavior for ZI_Travel alias Travel
{
side effects
{
// Actualizar todos los Bookings cuando cambia moneda
field CurrencyCode affects entity _Bookings, entity _Passengers;
// Después de Copy-Action recargar todas las entidades hijas
action copyWithDetails affects $self, entity _Bookings, entity _Passengers;
}
}

Campos destino y $self

Campos destino individuales

side effects
{
field Quantity affects field TotalPrice;
}

Múltiples campos destino

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

Entidad completa ($self)

side effects
{
// Con cambio de estado: Recargar instancia completa
field Status affects $self;
// Con copia: Actualizar todo
action copy affects $self;
}

Entity (Asociaciones)

side effects
{
// Actualizar entidades hijas
field CurrencyCode affects entity _Bookings;
// Actualizar entidad padre
field BookingPrice affects entity _Travel;
}

Ejemplo completo

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;
// Campos
field ( readonly ) TravelId, CreatedBy, CreatedAt;
field ( mandatory ) CustomerId;
// Asociaciones
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;
// Moneda afecta todos los campos de monto
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
{
// Cambio de precio en Booking actualiza suma en Travel
field Price affects field _Travel.TotalPrice;
}
}

Mejores prácticas

  1. Side Effects mínimos: Define solo los Side Effects realmente necesarios - demasiados pueden afectar el rendimiento

  2. Campos específicos en lugar de $self: Usa $self solo cuando realmente toda la entidad está afectada

  3. Determination + Side Effect: Combina Determinations con Side Effects para cálculos automáticos

  4. Asociaciones bidireccionales: Presta atención a la dirección correcta de Side Effects en relaciones Parent-Child

  5. Rendimiento: Los Side Effects disparan requests de UI - prueba el rendimiento en escenarios complejos

  6. Consistencia: Asegúrate de que las definiciones de Side Effect coincidan con la lógica real

" CORRECTO: Side Effect coincide con 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;
}
" INCORRECTO: Side Effect sin cálculo correspondiente
side effects
{
field Quantity affects field TotalPrice; " ¿Quién calcula TotalPrice?
}

Temas relacionados