IP11_Implementarea
IP11_Implementarea
Florin Leon
Universitatea Tehnică „Gheorghe Asachi” din Iași
Facultatea de Automatică și Calculatoare
[Link]
v2023.1
Faza de implementare
1. Introducere
2. Procesul de implementare
3. Refactorizarea
4. Analiza statică
5. Metrici de implementare
6. Anti-șabloane de implementare
7. Managementul configurației
8. Concluzii
5
Florin Leon, Ingineria programarii, [Link]
Clase de limbaje
Din punct de vedere al semanticii, sunt larg
recunoscute următoarele clase mari de limbaje:
Limbaje imperative (procedurale): cum se execută
prelucrările
Fortran, Basic, Pascal, C, C++, Python, Java, C#
Limbaje declarative: ce trebuie realizat
Subparadigma funcțională: Lisp (de exemplu, dialectele Scheme,
Common Lisp), Haskell, Scala, F#
Subparadigma logică: Prolog
Reguli și potrivirea modelelor (pattern matching): Clips, Jess, Drools
Multe limbaje folosite în prezent sunt multi-paradigmă
6
Florin Leon, Ingineria programarii, [Link]
Programarea: știință sau artă?
Știință
Adunarea de probe prin observații și experimente
măsurabile și repetabile
Formularea de ipoteze și testarea acestora
Artă
Construirea unor produse care pot acționa asupra
simțămintelor
Tradițional, orice talent sau măiestrie (gr. τέχνη)
7
Florin Leon, Ingineria programarii, [Link]
Programarea: știință sau artă?
8
Florin Leon, Ingineria programarii, [Link]
Programarea: știință sau artă?
9
Florin Leon, Ingineria programarii, [Link]
Programarea: știință sau artă?
Competiție de scripturi JavaScript de 1 KB
([Link]
10
Florin Leon, Ingineria programarii, [Link]
Programarea: știință sau artă?
12
Florin Leon, Ingineria programarii, [Link]
Programarea: știință sau artă?
Generator de numere pseudoaleatorii
Un generator liniar congruențial
13
Florin Leon, Ingineria programarii, [Link]
Faza de implementare
1. Introducere
2. Procesul de implementare
3. Refactorizarea
4. Analiza statică
5. Metrici de implementare
6. Anti-șabloane de implementare
7. Managementul configurației
8. Concluzii
15
Florin Leon, Ingineria programarii, [Link]
Experimentul lui Weinberg
Când programatorii primesc un obiectiv clar, de
obicei îl îndeplinesc
Îndeplinirea unui obiectiv afectează alte obiective
Compromisuri
16
Florin Leon, Ingineria programarii, [Link]
Implementarea incrementală
22
Florin Leon, Ingineria programarii, [Link]
Optimizarea metodelor
Adăugarea de parametri
Când o metodă trebuie să îndeplinească funcționalități
noi și are nevoie de mai multe informații
Ștergerea de parametri
Când nu toți parametrii sunt folosiți efectiv
23
Florin Leon, Ingineria programarii, [Link]
Optimizarea claselor
Scop: creșterea coeziunii și reducerea cuplării
Mutările de mai jos trebuie făcute doar dacă sunt corecte din punct de
vedere conceptual (o clasă reprezintă un concept)
Mutarea metodelor
Când o metodă din clasa A interacționează mult cu obiectele clasei B,
metoda poate fi mutată în clasa B
Dacă este posibil, metoda din clasa A trebuie eliminată cu totul
Mutarea câmpurilor
Dacă un câmp din clasa A este folosit mai des de către metodele clasei B,
câmpul poate fi mutat în clasa B
Câmpul fiind privat, referințele din clasa A trebuie modificate, iar în clasa B
trebuie să se introducă metode/proprietăți de tip accesor (get) și mutator (set)
Florin Leon, Ingineria programarii, [Link]
Optimizarea claselor
Extragerea de clase
De obicei, pe parcursul implementării, funcționalitatea
claselor este extinsă; o clasă poate ajunge să aibă prea
multe responsabilități
În acest caz, se creează o nouă clasă și apoi se aplică
refactorizările de metode și câmpuri
Dacă există o cuplare puternică între cele două clase
rezultate, înseamnă că partiționarea a fost artificială
Înlocuirea valorilor de date cu obiecte
Dacă asupra unor câmpuri se efectuează operații multiple,
acestea pot fi convertite în obiecte
25
Florin Leon, Ingineria programarii, [Link]
Optimizarea ierarhiilor
Scop: utilizarea polimorfismului pentru a facilita
extensiile ulterioare
Înlocuirea instrucțiunilor condiționale după flag-uri
sau tipul obiectelor cu clase polimorfice
„Ridicarea” sau „coborârea” câmpurilor și/sau
metodelor pe nivelurile unde sunt relevante
Elementele comune sunt incluse în clasele părinte
Elementele variabile sunt incluse în clasele fiu
26
Florin Leon, Ingineria programarii, [Link]
Exemplu
Situația matricolă a studenților
Structura inițială
28
Florin Leon, Ingineria programarii, [Link]
A doua refactorizare
Se elimină informațiile
redundante: Student
avea câmpurile DOB
(data nașterii) și Age
Funcționalitatea se
mută acolo unde
există cele mai multe
informații: clasa
CourseTaken are
metoda printGrade
29
Florin Leon, Ingineria programarii, [Link]
A treia refactorizare
Se înlocuiește câmpul
pg_or_ug cu o ierarhie
Thesis rămâne doar
pentru nivelul de licență
(UnderGrad)
30
Florin Leon, Ingineria programarii, [Link]
Utilitare
JetBrains Resharper, integrat cu mediul de dezvoltare
Visual Studio, care permite:
Evidențierea erorilor
Refactorizarea
Navigarea și căutarea mai ușoară
Formatarea și curățarea codului
Generarea automată de cod
Suport pentru testarea unităților
[Link]/resharper/features
32
Florin Leon, Ingineria programarii, [Link]
Analiza codului
IList : IEnumerable
Programul recomandă
lucrul cu clase mai
abstracte / generale
33
Florin Leon, Ingineria programarii, [Link]
Navigarea și căutarea
34
Florin Leon, Ingineria programarii, [Link]
Refactorizarea
Schimbarea semnăturii unei metode
Convertirea unei clase abstracte într-o interfață și
viceversa
Convertirea proprietăților sau indexatorilor în metode și
viceversa
Introducerea de câmpuri, variabile locale sau parametri
Extragerea de interfețe și metode
Mutarea membrilor mai sus sau mai jos în ierarhie
Încapsularea câmpurilor
Redenumiri
35
Florin Leon, Ingineria programarii, [Link]
Asistența la scrierea de cod
36
Florin Leon, Ingineria programarii, [Link]
Asistența la scrierea de cod
37
Florin Leon, Ingineria programarii, [Link]
Curățarea codului
38
Florin Leon, Ingineria programarii, [Link]
Curățarea codului
39
Florin Leon, Ingineria programarii, [Link]
Șabloane
40
Florin Leon, Ingineria programarii, [Link]
Faza de implementare
1. Introducere
2. Procesul de implementare
3. Refactorizarea
4. Analiza statică
5. Metrici de implementare
6. Anti-șabloane de implementare
7. Managementul configurației
8. Concluzii
42
Florin Leon, Ingineria programarii, [Link]
Analiza statică
Analiza automată a unui program pentru detectarea erorilor
potențiale și pentru generarea de informații utile la depanare
Și compilatoarele realizează o analiză statică restrânsă, în vederea
generării executabilului
Dar instrumentele dedicate au ca scop principal detectarea defectelor
Caracteristici ale analizoarelor statice:
Corectitudinea (soundness): sunt corecte dacă nu detectează situații
fals pozitive
Completitudinea (completeness): sunt complete dacă nu ratează
unele defecte existente
Este necesar un compromis
43
Florin Leon, Ingineria programarii, [Link]
Analiza statică automată
Analizoarele statice sunt instrumente software pentru
prelucrarea codului sursă
Ele parsează textul programului și încearcă să
descopere situații cu potențial de producere a unor erori
44
Florin Leon, Ingineria programarii, [Link]
Verificări în analiza statică
Defecte de date
Variabile utilizate înainte de inițializare; situația este
posibilă în C/C++, dar nu și în C#
Variabile declarate, dar nefolosite
Variabile atribuite de două ori, dar nefolosite între
atribuiri
Variabile nedeclarate
Posibile violări ale limitelor de vectori
45
Florin Leon, Ingineria programarii, [Link]
Verificări în analiza statică
Defecte de control
Cod care nu poate fi atins
Ramificări necondiționale în bucle
Defecte de intrare/ieșire
Variabile trimise la ieșire de două ori fără atribuiri
intermediare
46
Florin Leon, Ingineria programarii, [Link]
Verificări în analiza statică
Defecte de interfață
Neutilizarea rezultatelor unor metode
Metode neapelate
Nepotriviri de tip la parametri
Nepotriviri la numărul de parametri
Defecte de stocare
Pointeri neatribuiți
Aritmetică de pointeri
47
Florin Leon, Ingineria programarii, [Link]
Echivalent cu: a = pv[i]; pv[i] = a; a++;
Abordarea 1
Căutarea tiparelor neobișnuite în
cod:
Operații idempotente
O astfel de operație poate fi aplicată
de mai multe ori, dar are același efect
ca și când ar fi aplicată o singură dată
De exemplu: înmulțirea cu 0, setarea
unui flag, ștergerea unei înregistrări
cu un anumit ID dintr-o bază de date
Atribuiri neutilizate
Cod neexecutabil
Ramuri condiționale imposibil de
atins
48
Florin Leon, Ingineria programarii, [Link]
Abordarea 1
Experimentele asupra multor sisteme software utilizate
pe scară largă au indicat că 20-50% din atenționări sunt
fals pozitive
Există totuși o corelație puternică între problemele de
acest fel descoperite și erorile reale din programe
49
Florin Leon, Ingineria programarii, [Link]
Abordarea 2
Căutarea explicită a defectelor
Folosirea memoriei neinițializate
Dereferențierea pointerilor
neinițializați
Dereferențierea pointerilor nuli
Dereferențierea pointerilor invalizi
Dereferențierea sau returnarea
pointerilor la memorie eliberată
Scurgeri de memorie sau alte
resurse, de exemplu, fișiere
Returnarea pointerilor la variabile
locale de pe stivă: când variabila • Dacă size = 1, result nu este dezalocat
este distrusă, pointerul nu devine (scurgere de memorie)
nul, dar are un comportament • Dacă size ≤ 0, se dereferențiază
nedefinit (dangling pointer) (accesează) pointerul nul în linia 10
Împărțiri la 0 • Dacă malloc nu poate aloca memorie,
se dereferențiază pointerul nul
50
Florin Leon, Ingineria programarii, [Link]
Utilizarea analizei statice
Valoroasă mai ales când se folosește un limbaj slab
tipizat precum C, unde multe erori nu sunt detectate de
compilator
Mai puțin necesară în cazul limbajelor puternic tipizate
precum C# sau Java, care pot detecta multe erori la
compilare
51
Florin Leon, Ingineria programarii, [Link]
Faza de implementare
1. Introducere
2. Procesul de implementare
3. Refactorizarea
4. Analiza statică
5. Metrici de implementare
6. Anti-șabloane de implementare
7. Managementul configurației
8. Concluzii
53
Florin Leon, Ingineria programarii, [Link]
Metrici de complexitate
Complexitatea indică nivelul de dificultate la înțelegerea
unui modul
Metrici:
Dimensiunea: complexitatea crește cu dimensiunea codului și
cu numărul de decizii
Complexitatea ciclomatică: M = e – n + 2p
vezi cursul 4, Faza de proiectare, secțiunea Proiectarea detaliată
54
Florin Leon, Ingineria programarii, [Link]
Variabile vii
engl. “live variables”
Pentru a scrie sau citi instrucțiunile, un programator trebuie
să țină minte o serie de variabile, inclusiv altele decât cele
implicate direct în instrucțiunea curentă
O variabilă este vie de la prima până la ultima referențiere
dintr-un modul, incluzând toate instrucțiunile intermediare
Pentru o instrucțiune, numărul de variabile vii reprezintă o
măsură a dificultății de înțelegere a acelei instrucțiuni
Extindere la un modul: definirea numărului mediu de
variabile vii
55
Florin Leon, Ingineria programarii, [Link]
Anvergura
engl. “span”
Reprezintă numărul de instrucțiuni dintre două utilizări
succesive ale unei variabile; dacă o variabilă este
referențiată de n ori, atunci are n – 1 anverguri
Anvergura medie este numărul mediu de instrucțiuni
executabile dintre două referiri succesive ale unei variabile
Cu cât anvergura este mai mare, cu atât modulul este mai
complex
56
Florin Leon, Ingineria programarii, [Link]
Discuție
Complexitatea ciclomatică este definită doar pe baza
logicii de control
Variabilele vii și anvergura sunt definite doar din punct
de vedere al utilizării datelor
57
Florin Leon, Ingineria programarii, [Link]
Faza de implementare
1. Introducere
2. Procesul de implementare
3. Refactorizarea
4. Analiza statică
5. Metrici de implementare
6. Anti-șabloane de implementare
7. Managementul configurației
8. Concluzii
62
Florin Leon, Ingineria programarii, [Link]
Numerotarea versiunilor
Schema GNU: versiunea majoră, versiunea minoră și patch-ul
(tripletă de întregi)
Între două versiuni majore, în produs au loc schimbări majore ale
funcționalității și nu este garantată compatibilitatea înapoi
Între două versiuni minore ale aceleiași versiuni majore trebuie să existe
compatibilitate
Rolul unei versiuni minore este introducerea unor funcții noi. Funcțiile
vechi nu sunt îndepărtate; totuși documentația programului îl poate
avertiza pe utilizator că la anumite funcții se va renunța în viitor (sunt
marcate ca “obsolete” sau “deprecated”)
Patch-ul nu poate realiza decât schimbări în implementarea unor funcții.
De obicei, rolul său este corectarea unor defecte ale programului
Aceste reguli nu se aplică însă și pentru programele în versiuni alfa sau
beta (0.X)
Microsoft .NET: major, minor, build, revision
63
Florin Leon, Ingineria programarii, [Link]
Instrumente de control al
versiunilor
Alături de alte instrumente, menționăm:
Git
Microsoft Visual SourceSafe (VSS)
Concurent Versions System (CVS)
Subversion (SVN)
Microsoft Team Foundation Server (TFS)
64
Florin Leon, Ingineria programarii, [Link]
Git
Creat de Linus Torvalds (creatorul Linux) în 2005
Sistem de control al versiunilor destinat în special
dezvoltării software
Previne pierderea accidentală a fișierelor
Permite revenirea la o versiune anterioară
Permite partajarea și îmbinarea fișierelor
Permite colaborarea mai multor dezvoltatori la același
proiect
65
Florin Leon, Ingineria programarii, [Link]
Git
Este un sistem control al versiunilor distribuit: fiecare dezvoltator are
o copie completă a codului complet (repository) pe mașina locală
Într-un sistem centralizat, toate modificările se fac pe serverul central
Codul complet este stocat pe un server la distanță (remote), de
exemplu, GitHub
Acest cod este clonat de fiecare dezvoltator
După ce un dezvoltator face modificări în cod, acestea sunt copiate
pe server (push)
Ceilalți dezvoltatori preiau ultima versiune (pull)
Git folosește o structură de date eficientă pentru a stoca fișiere și a
urmări modificările, ceea ce îi permite să gestioneze proiecte mari
cu multe fișiere și istorice complexe
66
Florin Leon, Ingineria programarii, [Link]
GitHub Desktop
GitHub Desktop permite gestionarea acestui proces folosind o
interfață grafică cu utilizatorul
71
Florin Leon, Ingineria programarii, [Link]
Merge (îmbinarea)
75
Florin Leon, Ingineria programarii, [Link]
Florin Leon, Ingineria programarii, [Link]
Fluxuri de lucru (workflows)
Fluxul de lucru centralizat (centralized workflow)
Există un singur depozit central (repository) în/din care toți dezvoltatorii
salvează/descarcă modificările
Este util pentru echipele mici care lucrează la un singur proiect, în care
toată lumea trebuie să rămână sincronizată cu cele mai recente modificări
77
Florin Leon, Ingineria programarii, [Link]
Fluxuri de control (workflows)
Gitflow
Există două ramuri principale: master și develop
Ramura master conține codul de producție stabil, în timp ce ramura
develop conține cele mai recente modificări care nu sunt încă pregătite
pentru producție
Noile funcții sau cele de corectare a erorilor sunt dezvoltate pe ramuri
separate, care sunt îmbinate în ramura develop
Când ramura develop este gata pentru lansare, este îmbinată în ramura
master
Este util pentru proiectele care necesită un proces de lansare formalizat,
cu cicluri de lansare și numere de versiuni
78
Florin Leon, Ingineria programarii, [Link]
Recomandări
Sumarul commit-urilor trebuie să fie clar și concis și să reflecte modificările
făcute
Descrierea commit-urilor trebuie să includă un context privind motivul
modificărilor și informațiile relevante despre funcțiile noi sau erorile tratate
Toate mesajele trebuie să aibă un format consecvent
Trebuie evitate commit-urile de dimensiuni mari; modificările mari trebuie
împărțite
Trebuie utilizate ramurile pentru a izola modificările și pentru a menține curat
depozitul central
Ramurile trebuie îmbinate înapoi în depozitul central numai după ce
modificările au fost inspectate și testate
Trebuie utilizate nume descriptive ale ramurilor pentru a facilita înțelegerea
scopului acestora
Fluxul de lucru și cele mai bune practici trebuie documentate într-un
document sau wiki partajat
79
Florin Leon, Ingineria programarii, [Link]
Concluzii
Implementarea este faza în care este produs codul proiectat,
îndeplinind restricțiile de resurse, acuratețe și performanță
indicate de specificații
Există limbaje imperative și limbaje declarative; multe limbaje
actuale sunt multi-paradigmă
Alegerea unui limbaj trebuie să țină seama de natura
proiectului, de timpul dorit pentru implementare și de
experiența echipei
Structura programului trebuie optimizată ori de câte ori este
necesar prin refactorizare
Pentru organizațiile care dezvoltă produse software, este utilă
folosirea unui instrument pentru controlul versiunilor
80
Florin Leon, Ingineria programarii, [Link]