rss
    System.out.println("Hello World");

marți, 23 noiembrie 2010

Constrangeri, procese si specificatii in java: Partea II Specificatii - Validarea

Ati vazut ce nume de site are bunul meu prieten?
Inchipuitiva prin ce calvar trebuie sa trec cand strig dupa el pe strada:
„bai anunturicl, ba anunturicl, stai dracu sa ne luam si noi o saorma”!

Aveti deci mai jos, prin bunavointa gazdei noastre, o aplicatie exemplu, cei dintre voi care doriti sa aveti ceva asemanator, dar mai evoluat, puteti sa ne contactati si vom fi mai mult decat bucurosi sa adaugam aplicatiei cerintele voastre.

Revenim la continuarea serialului nostru despre subiectele incepute ieri!

prezentam postarea trecuta, constrangerile si procesele si va promiteam ca vom reveni cu un model, cu un patern, care sa rezolve aceasta problema a constrangerilor si a proceselor.
Trecand prin tot procesul anterior prezentat, am ajuns noi la concluzia ca ne-ar trebui un concept de modelare care sa ne permita urmatoarele:
- Validarea: O modalitate prin care sa pot verifica constrangerile, sau anumite caracteristici importante;
- Selectia: Fiind date mai multe obiecte de acelas tip, ma intereseaza sa le obtin pe acelea care respecta constrangerea/regula, sau din potriva, sa le aleg pe acelea care nu respecta constrangerea/regula;
- Constructia: As dori sa pot construi un obiect, dupa niste reguli date si regulile respective sa fie verificabile. Mai precis as dori sa pot construi un obiect dupa un plan dat, adica, spre exemplu, la o masina stiu ca trebuie sa ii pun mai intai motorul si apoi caroseria, sau invers. Sa am un numar de pasi dupa care sa ma ghidez in constructia unui obiect.
Mai mult, constructia unui obiect se poate realiza in diferite conditii:
Obiectul abia a fost creat, deci e un obiect nou;
Obiectul se afla in baza de date, deci el trebuie luat de acolo si adus in aplicatie;
Alte cazuri.
Daca s-ar putea, am zis noi, ar fi chiar tare daca acest concept de modelare ne-ar oferi si posibilitatea de a combina aceste constrangeri intr-un lant de constrangeri aplicate.
Un cuvant ne-a venit la amindoi in minte:
- Frate, asta suna ca si cum ai construi specificatia unui produs;

Am inceput sa cautam febril daca exista un astfel de concept de modelare.
Si l-am gasit intr-un articol de Evans si Fovler din anul 1997, dar si mai tarziu intr-o carte a lui Evens.

Ne intoarcem putin la exemplul cu facturi.
Cum am aratat mai sus, avem tendinta de a testa cu metode booleene toate constrangerile care ne apar pe un obiect.
Acest lucru merge perfect atita timp cat regulile sunt simple.
Deci la o clasa pentru factura, verificarea faptului ca o factura a depasit data scadenta ar fi:

public boolean isOverdue() {
Date currentDate = new Date();
return currentDate.after(dueDate);
}

Ce ne facem insa daca vrem sa verificam ca o factura este „delicventa” adica a depasit orice urma de bun simt.
Pentru aceasta, verificarea ar incepe mai intai cu constrangerea faptului ca factura trebuie sa fi depasit data scadenta.
Dar, mai departe trebuie sa ne bazam verificarea pe un plan de gratiere (acea perioada de gratie acordata la o factura), plan de gratiere care poate fi diferit de la client la client, in functie de statusul contului clientului respectiv, de ofertele pe care clientul le poate primi si de comportamentul financiar si nu numai al clientului.
Mai mult, e vorba si de procesul de dupa (vedeti, ajungem iar la procese).
Unele facturi pot fi gata pentru un al doilea avertisment care sa fie trimis clientului, pe cand altele abia se afla la primul avertisment, sau mai rau, sunt gata de a fi trimise la recuperatori.
Este clar ca, functionalitatea de baza a unei facturi, aceea de a fi un document de cerere de plata, se va pierde printre tonele de cod de verificare de reguli.
Clasa factura va dezvolta de asemenea o multime de dependente fata de alte clase, care la baza, nu aveau treaba cu acest concept.
Acum, multi dintre voi, ati lua acest cod de verificare al regulilor si l-ati pune in partea de prezentare a aplicatiei.
Ati lua factura asa cum e ea din baza de date, ati aduce-o in cod si de acolo abia la prezentarea ei sau la salvarea ei ati verifica datele.
Din pacate, acest comportament, lasa in urma un obiect cu date mort, care nu stie sa se verifice singur pentru regulile elementare din domeniu specific.
Verificarea regulilor si a constrangerilor, trebuie sa ramana in modelarea domeniului specific (ceea ce se cheama in design business layer), dar daca nu se potriveste in cadrul definitiei unui obiect, cum ar fi factura, modelati-l ca obiect separat.
Nu doar atit, dar evaluarea regulilor cu metode conditionale, va face regulile sa fie greu de citit.
Dezvoltatorii care lucreaza cu paradigma programarii logice, ar scapa usor.
Ei ar construi predicate pentru fiecare regula si ar evalua factura cu aceste predicate.
Predicatele sunt functii care returneaza adevarat sau fals bazat pe o anumita regula.
Acestea, predicatele, pot fi combinate folosind operatori logici cum ar fi conjunctia si disjunctia.
Numai ca noi, avem o mica problema, una mica de tot, aproape de detaliu as putea spune.
Nu suntem in paradigma de programare logica.
Din fericire, nici nu ne trebuie intreaga paradigma logica de programare, ci avem nevoie doar de conceptul de predicat.
Vom modela acest concept de predicat prin obiecte separate, de sine statatoare, care pot primi si evalua starea unui alt obiect.
Informatiile de care acest predicat are nevoie, ii vor fi date la creiere de catre un factory.
In acest fel, obiectul factura isi va pastra functionalitatea sa de baza.
Vom lua pe rand cele trei cerinte ale noastre de mai sus, prezentandu-le pe rand in cate o postare, astazi validarea:

Despre validare!

Ne intoarcem la exemplul cu factura, sa o verificam daca este” delicventa”...

class DelinquentInvoiceSpecification extends
InvoiceSpecification {
private Date currentDate;
//o instanta este utilizata si apoi distrusa intr-o singura zi

public DelinquentInvoiceSpecification(Date currentDate) {
this.currentDate = currentDate;
}

public boolean isSatisfiedBy(Invoice candidate) {
int gracePeriod =
candidate.customer().getPaymentGracePeriod();
Date firmDeadline =
DateUtility.addDaysToDate(candidate.dueDate(),
gracePeriod);
return currentDate.after(firmDeadline);
}

}

Pentru a vedea cum sa utilizam aceasta clasa/specificatie, presupunem acum ca va trebui sa aratam in aplicatie un semn distinctiv ori de cate ori un vanzator aduce persoane rau platnice.

Codul ar arata cam asa:

public boolean accountIsDelinquent(Customer customer) {
Date today = new Date();
Specification delinquentSpec =
new DelinquentInvoiceSpecification(today);
Iterator it = customer.getInvoices().iterator();
while (it.hasNext()) {
Invoice candidate = (Invoice) it.next();
if (delinquentSpec.isSatisfiedBy(candidate)) return true;
}
return false;
}


In felul acesta, regulile de verificare ale unei facturi, sunt in propriul lor obiect, iar factura isi vede linistita de functionalitatea ei.


Va urma


In elaborarea acestui articol ne-am sprijinit pe:

Domain-driven design : tackling complexity in the heart of software / Eric
Evans.
p. cm.
Includes bibliographical references and index.
ISBN 0-321-12521-5

Evans, E., and M. Fowler. 1997. "Specifications." Proceedings of PLoP 97 Conference.

Niciun comentariu:

Trimiteți un comentariu

Va rugam lasati un comentariu!