% Project: ECONET 
% Document: Prague07 Workshop Report
% Last writer: Andre Pascal 
% creation: 14/09/07 
% modification PA 02/10/07 
% *********************************** 
%\section{Metamodel Abstraction Subproject}
%\label{metamodel}

\textit{Writer: Dan Chiorean}\\

NB: \textit{currently in romanian, put in a latex format by pascal, it will be translated soon}.

\subsection{Objectives and Goals}
\subsection{Participants}
\subsection{Means}
\subsection{Tasks and Schedule}
\subsection{}

Utilizarea asertiunilor īn modelare - vazuta din perspectiva evaluarii lor


Īn cadrul acestei lucrari, vom analiza modul īn care specificarea asertiunilor īn modelare este influentata de felul īn care se realizeaza evaluarea lor: static, dupa construirea modelului sau dinamic, īn timpul construirii si modificarii lui.  Vom īncerca sa evidentiem unele aspecte sensibile de care trebuie sa tinem seama īn cazul unor astfel de specificari, chiar si īn cazul unor situatii simple.

Pentru a exemplifica afirmatiile noastre, vom considera un model relativ simplu, si anume metamodelul CoreComponents, care grupeaza trasaturile comune ale majoritatii limbajelor de modelare a componentelor [BuresHnetynkaPlasil].  Pentru o lizibilitate mai mare, īn figura 1 sunt prezentate numai elementele metamodelului referite īn cadrul asertiunilor analizate īn continuare.
 
\begin{figure}[ht]
\centerline{\epsfig{figure=\repFIGURES/metaCCM.eps,width=15cm}}
\caption{A part of the CoreComponent Metamodel}%[metaCCM]
\label{metaCCM}
\end{figure}

%Figure 1 - 
Validarea unui model, poate fi privita din doua puncte de vedere diferite, care, asa cum vom prezenta īn continuare, influenteaza modul de specificare a asertiunilor.

Validare statica - Constrāngerile permit corectarea si validarea unui model deja construit

Aceste modele reprezinta instantieri ale unui metamodel, obiectivul nostru fiind sa verificam daca toate constrāngerile asociate metamodelului sunt satisfacute de modelele care urmeaza a fi validate.
Problema este perfect similara celei īn care un model UML construit cu ajutorul unui instrument adecvat: Rational Rose, Poseidon, MagicDraw etc. este validat īn raport cu WFR-urile specificate pentru metamodelul UML.  Īn acest caz, constrāngerile sunt exprimate prin intermediul invariantilor.

Asa cum se mentioneaza īn diverse lucrari [x], pe parcursul construirii modelului, acesta nu este complet si īn unele cazuri este chiar incorect din punctul de vedere al constrāngerilor limbajului de modelare.  De aceea, īnainte de realizarea unor transformari ale modelului, este important sa verificam corectitudinea si completitudinea lui (compilabilitatea modelului).

Pentru metamodelul CoreComponents, constrāngerea specificata grafic īntre asocierile unidirectionale spre Frame, respectiv Architecture se poate exprima simplu sub forma urmatorului invariant:

\begin{verbatim}
context SubcomponentInstance
   inv FrameOrArchitectureAssoc:
      self.instantiateArchitecture.isUndefined xor self.instantiateFrame.isUndefined
\end{verbatim}

Īn cazul īn care invariantului este evaluat la false, simpla evaluare a celor 2 subexpresii ale lui xor permite identificarea cauzei eorii, permitānd modelatorului sa remedieze eroarea.

Īn cazul constrāgerii referitoare la unicitatea numelui pentru requiredInterfaces atasate unui Frame, invariantul:

\begin{verbatim}
context Frame
   inv requiredInterfacesName:
      self.requiredInterface.name->isUnique(n | n)
\end{verbatim}
 
\begin{figure}[ht]
\centerline{\epsfig{figure=\repFIGURES/sofaDB.eps,width=7cm}}
\caption{Components with provided and required Interfaces}%[sofaDB]
\label{sofaDB}
\end{figure}
%Figure 2 

nu sprijina suficient identificarea interfetelor care au determinat violarea invariantului.  Prin evaluarea numelor tuturor interfetelor, putem, dupa cautari repetate, sa identificam interfetele care au condus la violarea invariantului.  Īn cazul īn care numarul acestor interfete este mare, cautarea consuma timp si este neplacuta
O specificare mai potrivita pentru acest obiectiv (care permite identificarea rapida a interfetelor cu acelasi nume) este:

\begin{verbatim}
context Frame
   inv requiredInterfacesName:
      let ri = self.requiredInterface in
      (ri->reject(e | ri.name->count(e.name)=1))->isEmpty
\end{verbatim}

Īn cazul violarii invariantului, evaluarea colectiei de interfete ale caror nume nu sunt unice, ne permite sa parcurgem simplu (prin navigare - īn cazul utilizarii OCLE) interfetele care au violat invariantul si sa corectam modelul.  Īn cazul īn care conditia de unicitate se refera atāt la interfetele required cāt si la cele provided, specificarea este:

\begin{verbatim}
context Frame
   inv uniqueInterfacesName:
      let i = self.requiredInterface->union(self.providedInterface) in
      (ri->reject(e | ri.name->count(e.name)=1))->isEmpty
\end{verbatim}

[Imagine cu snapshot OCLE si explicatiile suplimentare - la fel si mai sus cand am nume]

Pentru constrāngerea referitoare la tipul elementelor ce pot fi asociate ca adnotari ale lui Frame, vom adopta o solutie similara celei precedente:

\begin{verbatim}
context Frame
   inv annotations_Type:
      self.annotation->select(e | not e.oclIsTypeOf(TopLevel))->isEmpty
\end{verbatim}

Evaluare a colectiei rezultata īn urma operatiei select, va permite identificarea adnotarilor care nu satisfac constrāngerea.

Constrāngeri care sprijina pastrarea validitatii modelului dupa fiecare operatie - Validare dinamica

Aceasta situatie este similara celei īn care avem o aplicatie orientata-obiect, aplicatie īn care obiectele sunt create, distruse sau īsi schimba starea.  Universul obiectelor trebuie sa fie īn permanenta valid.  Īn consecinta, trebuie sa luam masuri adecvate pentru ca īn urma fiecarui apel de constructor sau modificator care poate schimba starea sistemului, aceasta sa ramāna valida.  Politica adoptata va fi īn conformitate cu proverbul "better prevent than cure", īn consecinta, constrāngerile vor fi specificate preponderent cu ajutorul (folosind) preconditiilor si postconditiilor.

Ca si īn cazul verificarii statice, vom analiza mai īntāi constrāngerea dintre cele doua asocieri unidirectionale care pleaca din clasa SubcomponentInstance spre clasele Frame respectiv Architecture, fiecare avānd multiplicitatea 0..1 pentru capetele de asociere navigabile.  Constrāngerea XOR īntre cele 2 asocieri, exprimata grafic īn diagrama de clase, semnifica faptul ca dinspre SubcomponentInstance vom avea īntotdeauna o asociere spre una din clasele destinatie Frame sau Architecture si numai una.

Īn conformitate cu principiile "design by contract" [Meyer], invariantul trebuie sa fie satisfacut pe īntreaga durata de viata a obiectului, exceptānd momentele īn care asupra lui sunt aplicati modificatori.  O prima consecinta este ca, īntotdeauna obiectele de tip SubcomponentInstance vor trebui produse folosind constructori expliciti.  Īn cazul īn care vom avea un singur astfel de constructor, printre parametrii sai va trebui sa avem cāte o referinta spre Frame respectiv Architecture.  Doar una dintre aceste referinte va trebui sa fie valida, cealalta trebuind sa fie null (undefined).  O solutie este:

\begin{verbatim}
context SubcomponentInstance::SubcomponentInstance(a:Architecture, 
                                          f:Frame):SubcomponentInstance
   pre subcomponentInstance_connection:
      (a.isUndefined and f.oclIsTypeOf(Frame)) or 
      (f.isUndefined and a.oclIsTypeOf(Architecture))
   post subcomponentInstance_connection_:
      (result.instantiateFrame = f) and (result.instantiateArchitecture = a)
\end{verbatim}

Conform filosofiei OOP, apelul uneia dintre metodele setInstantiateFrame(f:Frame), respectiv setInstantiateArchitecture(a:Architecture) trebuie sa poata modifica numai referinta transmisa ca parametru.  Īn consecinta, pentru acesti modificatori preconditiile vor fi:

\begin{verbatim}
context SubcomponentInstance::setInstantiateFrame(f:Frame) 
   pre instantiate_Frame:
      self.instantiateArchitecture.isUndefined and f.oclIsTypeOf(Frame)
   post instantiate_Frame:
      self.instantiateFrame = f
\end{verbatim}

\begin{verbatim}
context SubcomponentInstance::setInstantiateArchitecture (a: Architecture) 
   pre instantiate_Architecture:
      self.instantiateFrame.isUndefined and a.oclIsTypeOf(Architecture)
   post instantiate_Architecture_:
      self.instantiate Architecture = a
\end{verbatim}

Īn cazul īn care se doreste ca un obiect SubcomponentInstance sa-si poata schimba unica asociere, dinspre un Frame spre un Architecture sau invers, aceasta shimbare va determina modificarea ambelor referinte, atāt cea spre Frame, cāt si cea spre Architecture.  Īn consecinta, pentru o astfel de operatie trebui construita o noua metoda, avānd acceasi preconditie ca si cea prezentata mai sus pentru constructorul explicit.  Īn corpul acestei metode va fi apelata metoda set corespunzatoare, dupa ce īn prealabil referintele spre Frame respectiv Architecture vor fi setate la null.

Pentru constrāgerea referitoare la unicitatea numelui unei requiredInterface atasate unui Frame, vom avea īn vedere ca aceasta cerinta poate fi modificata numai la adaugarea unei noi interfete, īn consecinta preconditia corespunzatoare va fi atasata operatiei addRequiredInterface(i:Interface):

\begin{verbatim}
context Frame::addRequiredInterface(i:Interface)
   pre uniqueName:
        i.name.size > 0 and self.requiredInterface.name->excludes(i.name)
   post uniqueName_:
      self.requiredInterface->size = self.requiredInterface@pre->size + 1 and 
      self.requiredInterface.name->includes(i.name)
\end{verbatim}

Daca luam īn considerare posibilitatea schimbarii numelui unei interfete dupa ce a fost atasata la un Frame, atunci, va trebui sa specificam o preconditie adecvata pentru metoda Interface::setName(n: String).

Īn cazul īn care exista constructori expliciti ai clasei Frame care seteaza legaturi spre Interface pentru rolul requiredInterface, atunci va trebui verificata constrāngerea asociata numelui īn cadrul respectivilor constructori.

Ultima constrāngere se refera la tipul elementelor ce pot fi atasate ca anotari ale lui Frame.  Si īn acest caz, asertiunea va fi specificata cu ajutorul unei preconditii.

\begin{verbatim}
context Frame
context Frame::addAnnotation(a:Annotation)
   pre param_s_type:
      a.oclIsKindOf(TopLevel)
\end{verbatim}

·	Asertiunile nu trebuie sa fie nici prea constrictive, nici prea permisive (ele trebuie sa exprime fidel conditiile ce trebuie indeplinite pentru un comportament predictibil si corect al obiectelor unei aplicatii).  De aceea evaluarea asertiunilor OCL pe un numar semnificativ de cazuri, trebuie sa conduca fie la validarea constrāngerilor specificate informal (īn limbaj natural) sau la corectarea lor.  Īn cadrul specificarii riguroase a constrāngerilor īntr-un limbaj formal si al evaluarii lor, trebuie sa raspundem la o serie de īntrebari care sa ne permita sa īntelegem mai bine si mai exact rolul constrāngerilor si comportamentul aplicatiei.
·	Asertiunile trebuie specificate īntr-un mod expresiv si cāt mai simplu cu putinta.  Evaluarea lor trebuie sa fie cāt mai simpla si daca se poate, sa fie realizata numai atunci cānd este nevoie.
·	Īn cazul specificarii invariantilor, trebuie sa avem īn vedere momentele evaluarii lor.  Evaluarea realizata dupa fiecare apel de constructor este obligatorie asa cum mentioneaza foarte clar Meyer [OOSC].  Pentru a evita efectuarea unor operatii redundante, invariantii vor trebui evaluati numai dupa apelul modificatorilor care ar putea altera starea obiectului, nu dupa apelul fiecarui modificator.

\endinput

