Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
277 changes: 277 additions & 0 deletions lessons/ro/chapter_7.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,277 @@
- title: Capitolul 7 - Programare Orientată pe Obiecte
content_markdown: >
Exprimarea ideilor cu ajutorul funcțiilor este o metodă dovedită de a reprezenta
comportamente și date (Limbajul C o face de decenii!).

Din punct de vedere istoric, știință calculatoarelor a găsit alte agregatii și abstractizări
expresive folositoare pentru date.

Ați putea fi familiarizați cu programarea orientată pe obiecte (POO) ca fiind
una dintre acestea. În acest capitol vom explora limbajul Rust dincolo de funcții.
- title: Ce este POO?
content_markdown: >
Programarea orientată pe obiecte se referă, în linii mari, la limbajele de programare ce
prezintă anumite caracteristici reprezentative:

* Încapsularea - Asocierea datelor și funcțiilor într-o unitate conceptuală de un singur tip
numită *obiect*.

* Abstractizarea - Ascunderea datelor și funcțiilor pentru a acoperi detaliile
implementării unui obiect

* Polimorfismul - Abilitatea de a interacționa cu obiecte de tipuri diferite prin intermediul unei interfețe.

* Moștenirea - Abilitatea de a moșteni date și comportamente de la alte obiecte.
- title: Rust Nu Este POO
content_markdown: >
Rust nu dispune de o metodă semnificativă de moștenire a datelor și comportamentelor.

* Structurile nu pot moșteni câmpuri de la o structura părinte.

* Structurile nu pot moșteni funcții de la o structura părinte.

Acestea fiind spuse, Rust implementează o mulțime de caracteristici ale unui limbaj de programare,
deci probabail nu vă vor deranja aceste lipsuri.
- title: Încapsulare prin matode
code: >-
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&code=struct%20CreaturaMaritima%20%7B%0A%20%20%20%20zgomot%3A%20String%2C%0A%7D%0A%0Aimpl%20CreaturaMaritima%20%7B%0A%20%20%20%20fn%20luare_zgomot(%26self)%20-%3E%20%26str%20%7B%0A%20%20%20%20%20%20%20%20%26self.zgomot%0A%20%20%20%20%7D%0A%7D%0A%0Afn%20main()%20%7B%0A%20%20%20%20let%20creatura%20%3D%20CreaturaMaritima%20%7B%0A%20%20%20%20%20%20%20%20zgomot%3A%20String%3A%3Afrom(%22blub%22)%2C%0A%20%20%20%20%7D%3B%0A%20%20%20%20println!(%22%7B%7D%22%2C%20creatura.luare_zgomot())%3B%0A%7D%0A
content_markdown: >
Rust suportă conceptul de *obiect* ce reprezintă o structură asociată unor funcții (cunoscute și ca *metode*).

Primul parametru al oricărei metode trebuie să fie o referință la instanța asociată apelului de metodă
(exemplu: `instantaObiectului.foo()`). Rust folosește:

* `&self` - Referință imutabilă la instanța.

* `&mut self` - Referință mutabilă la instanța.

Metodele sunt definite în cadrul unuia sau mai multor blocuri de implementare prin cuvântul cheie `impl`:

```rust

impl StructuraMea {
...
fn foo(&self) {
...
}
}

```
- title: Abstracție prin Expunere Selectivă
code: >-
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&code=struct%20CreaturaMaritima%20%7B%0A%20%20%20%20pub%20nume%3A%20String%2C%0A%20%20%20%20zgomot%3A%20String%2C%0A%7D%0A%0Aimpl%20CreaturaMaritima%20%7B%0A%20%20%20%20pub%20fn%20luare_sunet(%26self)%20-%3E%20%26str%20%7B%0A%20%20%20%20%20%20%20%20%26self.zgomot%0A%20%20%20%20%7D%0A%7D%0A%0Afn%20main()%20%7B%0A%20%20%20%20let%20creatura%20%3D%20CreaturaMaritima%20%7B%0A%20%20%20%20%20%20%20%20nume%3A%20String%3A%3Afrom(%22Ferris%22)%2C%0A%20%20%20%20%20%20%20%20zgomot%3A%20String%3A%3Afrom(%22blub%22)%2C%0A%20%20%20%20%7D%3B%0A%20%20%20%20println!(%22%7B%7D%22%2C%20creatura.luare_sunet())%3B%0A%7D%0A
content_markdown: >
Rust poate ascude implementările interioare ale obiectelor.

În mod implicit, câmpurile și metodele sunt accesibile doar modulului de care aparțin.

Cuvântul cheie `pub` expune câmpurile și metodele structurii în afara modulului.
- title: Polimorfismul prin Trăsături
code: >-
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&code=struct%20CreaturaMaritima%20%7B%0A%20%20%20%20pub%20nume%3A%20String%2C%0A%20%20%20%20zgomot%3A%20String%2C%0A%7D%0A%0Aimpl%20CreaturaMaritima%20%7B%0A%20%20%20%20pub%20fn%20luare_zgomot(%26self)%20-%3E%20%26str%20%7B%0A%20%20%20%20%20%20%20%20%26self.zgomot%0A%20%20%20%20%7D%0A%7D%0A%0Atrait%20FacatorDeZgomot%20%7B%0A%20%20%20%20fn%20fa_zgomot(%26self)%3B%0A%7D%0A%0Aimpl%20FacatorDeZgomot%20for%20CreaturaMaritima%20%7B%0A%20%20%20%20fn%20fa_zgomot(%26self)%20%7B%0A%20%20%20%20%20%20%20%20println!(%22%7B%7D%22%2C%20%26self.luare_zgomot())%3B%0A%20%20%20%20%7D%0A%7D%0A%0Afn%20main()%20%7B%0A%20%20%20%20let%20creatura%20%3D%20CreaturaMaritima%20%7B%0A%20%20%20%20%20%20%20%20nume%3A%20String%3A%3Afrom(%22Ferris%22)%2C%0A%20%20%20%20%20%20%20%20zgomot%3A%20String%3A%3Afrom(%22blub%22)%2C%0A%20%20%20%20%7D%3B%0A%20%20%20%20creatura.fa_zgomot()%3B%0A%7D%0A
content_markdown: >
Rust suportă polimorfismul prin trăsături (în engleză *traits*). Trăsăturile ne permit asocierea unui set
de metode cu o structura.

Prima dată definim semnăturile metodelor unei trăsături în:

```

trait TrasaturaMea {
fn foo(&self);
...
}

```
Când o structură implementează o trăsătură, este stabilit un contract ce permite interacțiunea noastră
indirectă cu structura, prin tipul trăsăturii (exemplu: `&dyn TrasaturaMea` ), fără a fi nevoie
să cunoaștem tipul real al structurii.

Metodele trăsăturii implementate de structură sunt definite în cadrul unui bloc de implementare:

```rust

impl TrasaturaMea for StructuraMea {
fn foo(&self) {
...
}
...
}

```
- title: Metode Implementate Trăsăturilor
code: >-
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&code=struct%20CreaturaMaritima%20%7B%0A%20%20%20%20pub%20nume%3A%20String%2C%0A%20%20%20%20zgomot%3A%20String%2C%0A%7D%0A%0Aimpl%20CreaturaMaritima%20%7B%0A%20%20%20%20pub%20fn%20luare_zgomot(%26self)%20-%3E%20%26str%20%7B%0A%20%20%20%20%20%20%20%20%26self.zgomot%0A%20%20%20%20%7D%0A%7D%0A%0Atrait%20FacatorDeZgomot%20%7B%0A%20%20%20%20fn%20fa_zgomot(%26self)%3B%0A%20%20%20%20%0A%20%20%20%20fn%20fa_mult_zgomot(%26self)%7B%0A%20%20%20%20%20%20%20%20self.fa_zgomot()%3B%0A%20%20%20%20%20%20%20%20self.fa_zgomot()%3B%0A%20%20%20%20%20%20%20%20self.fa_zgomot()%3B%0A%20%20%20%20%7D%0A%7D%0A%0Aimpl%20FacatorDeZgomot%20for%20CreaturaMaritima%20%7B%0A%20%20%20%20fn%20fa_zgomot(%26self)%20%7B%0A%20%20%20%20%20%20%20%20println!(%22%7B%7D%22%2C%20%26self.luare_zgomot())%3B%0A%20%20%20%20%7D%0A%7D%0A%0Afn%20main()%20%7B%0A%20%20%20%20let%20creatura%20%3D%20CreaturaMaritima%20%7B%0A%20%20%20%20%20%20%20%20nume%3A%20String%3A%3Afrom(%22Ferris%22)%2C%0A%20%20%20%20%20%20%20%20zgomot%3A%20String%3A%3Afrom(%22blub%22)%2C%0A%20%20%20%20%7D%3B%0A%20%20%20%20creatura.fa_mult_zgomot()%3B%0A%7D%0A
content_markdown: >
Trăsăturile pot avea metode implementate.

Funcțiile nu au acces direct asupra câmpurilor interioare ale unei structuri, dar aceste metode implementate
trăsăturilor pot fi folositoare în distribuirea comportamentelor între mai mulți implementarori ai trăsăturilor.
- title: Moștenirea Trăsăturilor
code: >-
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&code=struct%20CreaturaMaritima%20%7B%0A%20%20%20%20pub%20nume%3A%20String%2C%0A%20%20%20%20zgomot%3A%20String%2C%0A%7D%0A%0Aimpl%20CreaturaMaritima%20%7B%0A%20%20%20%20pub%20fn%20luare_zgomot(%26self)%20-%3E%20%26str%20%7B%0A%20%20%20%20%20%20%20%20%26self.zgomot%0A%20%20%20%20%7D%0A%7D%0A%0Atrait%20FacatorDeZgomot%20%7B%0A%20%20%20%20fn%20fa_zgomot(%26self)%3B%0A%7D%0A%0Atrait%20FacatorDeZgomotGalagios%3A%20FacatorDeZgomot%20%7B%0A%20%20%20%20fn%20fa_mult_zgomot(%26self)%20%7B%0A%20%20%20%20%20%20%20%20self.fa_zgomot()%3B%0A%20%20%20%20%20%20%20%20self.fa_zgomot()%3B%0A%20%20%20%20%20%20%20%20self.fa_zgomot()%3B%0A%20%20%20%20%7D%0A%7D%0A%0Aimpl%20FacatorDeZgomot%20for%20CreaturaMaritima%20%7B%0A%20%20%20%20fn%20fa_zgomot(%26self)%20%7B%0A%20%20%20%20%20%20%20%20println!(%22%7B%7D%22%2C%20%26self.luare_zgomot())%3B%0A%20%20%20%20%7D%0A%7D%0A%0Aimpl%20FacatorDeZgomotGalagios%20for%20CreaturaMaritima%20%7B%7D%0A%0Afn%20main()%20%7B%0A%20%20%20%20let%20creatura%20%3D%20CreaturaMaritima%20%7B%0A%20%20%20%20%20%20%20%20nume%3A%20String%3A%3Afrom(%22Ferris%22)%2C%0A%20%20%20%20%20%20%20%20zgomot%3A%20String%3A%3Afrom(%22blub%22)%2C%0A%20%20%20%20%7D%3B%0A%20%20%20%20creatura.fa_mult_zgomot()%3B%0A%7D%0A
content_markdown: |
Trăsăturile pot moșteni metode de la alte trăsături.
- title: Expediere Dinamică vs Statică
code: >-
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&code=struct%20CreaturaMaritima%20%7B%0A%20%20%20%20pub%20nume%3A%20String%2C%0A%20%20%20%20zgomot%3A%20String%2C%0A%7D%0A%0Aimpl%20CreaturaMaritima%20%7B%0A%20%20%20%20pub%20fn%20luare_zgomot(%26self)%20-%3E%20%26str%20%7B%0A%20%20%20%20%20%20%20%20%26self.zgomot%0A%20%20%20%20%7D%0A%7D%0A%0Atrait%20FacatorDeZgomot%20%7B%0A%20%20%20%20fn%20fa_zgomot(%26self)%3B%0A%7D%0A%0Aimpl%20FacatorDeZgomot%20for%20CreaturaMaritima%20%7B%0A%20%20%20%20fn%20fa_zgomot(%26self)%20%7B%0A%20%20%20%20%20%20%20%20println!(%22%7B%7D%22%2C%20%26self.luare_zgomot())%3B%0A%20%20%20%20%7D%0A%7D%0A%0Afn%20static_fa_zgomot(creatura%3A%20%26CreaturaMaritima)%20%7B%0A%20%20%20%20%2F%2F%20cunoastem%20tipul%20real%0A%20%20%20%20creatura.fa_zgomot()%3B%0A%7D%0A%0Afn%20dinamic_fa_zgomot(facator_de_zgomot%3A%20%26dyn%20FacatorDeZgomot)%20%7B%0A%20%20%20%20%2F%2F%20nu%20cunoastem%20tipul%20real
content_markdown: >
Metodele sunt executate în două moduri:

* expediere statică (static dispatch)- Când tipul instanței este cunoscut,
știm în mod direct ce funcție să apelăm.

* expediere dinamică (dynamic dispatch)- Când tipul instanței nu este cunoscut trebuie
să găsim o modalitate de a apela funcția corectă.

Tipurile trăsăturilor `&dyn TrasaturaMea` ne dau abilitatea de a lucra cu instanțe ale obiectelor
în mod indirect, folosind expedierea dinamică.

Când expedierea dinamică este folosită, este necesar să puneți `dyn` înaintea trăsăturii.

Detalii cu privire la memorie:

* Expedierea dinamică este puțîn mai lentă, din cauza urmăririi prin pointeri pentru a determina
apelul de funcție real.
- title: Trait Objects
content_markdown: >
Când pasăm o instanța a unui obiect ca parametru de tipul `&dyn TrasaturaMea`,
pasăm ceea ce se numește obiect al trăsăturii (în engleză `trait object`).

Acestea sunt ceea ce ne permite să apelăm în mod indirect metodele corecte ale unei instanțe.

Un obiect al trăsăturii este o structura ce conține un pointer al instanței noastre, alături de o lista
de pointeri la funcții către metodele acesteia.

Detalii:

* Această lista de funcții este cunoscută în C++ sub denumirea de *vtable*.
- title: Manevrarea Tipurilor de Date Fără Dimensiune Fixă
content_markdown: >
Trăsăturile introduc o provocare interesantă când dorim să le stocăm în interiorul altei structuri.

Trăsăturile ascund structura originală, astfel ascunzând și dimensiunea originală. Tipurile de date fără
dimensiune fixa sunt manevrate în două moduri în Rust:

* tipuri generice - Folosind tipuri parametrizate creăm structuri/funcții cu tipuri de date generice,
a căror dimensiune va fi cunoscută în momentul folosirii lor, când programatorul va specifica un tip de date

efectiv, care va avea și dimensiuni cunoscute.

* indirecție - Punerea instanțelor pe heap ne oferă avantajul de a nu fi necesar să cunoaștem dimensiunea
tipului de date la compilare, aceasta fiind folosita doar în momentul rulării, când programatorul poate

folosi orice tip de date care se portivește. Accesarea valorii efective se realizează printr-un pointer
(presupune o indirectie), iar acest lucru poate fi considerat un dezavantaj.

Mai există și alte modalități!
- title: Funcții Generice
code: >-
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&code=struct%20CreaturaMaritima%20%7B%0A%20%20%20%20pub%20nume%3A%20String%2C%0A%20%20%20%20zgomot%3A%20String%2C%0A%7D%0A%0Aimpl%20CreaturaMaritima%20%7B%0A%20%20%20%20pub%20fn%20luare_zgomot(%26self)%20-%3E%20%26str%20%7B%0A%20%20%20%20%20%20%20%20%26self.zgomot%0A%20%20%20%20%7D%0A%7D%0A%0Atrait%20FacatorDeZgomot%20%7B%0A%20%20%20%20fn%20fa_zgomot(%26self)%3B%0A%7D%0A%0Aimpl%20FacatorDeZgomot%20for%20CreaturaMaritima%20%7B%0A%20%20%20%20fn%20fa_zgomot(%26self)%20%7B%0A%20%20%20%20%20%20%20%20println!(%22%7B%7D%22%2C%20%26self.luare_zgomot())%3B%0A%20%20%20%20%7D%0A%7D%0A%0Afn%20generic_fa_zgomot%3CT%3E(creatura%3A%20%26T)%0Awhere%0A%20%20%20%20T%3A%20FacatorDeZgomot%2C%0A%7B%0A%20%20%20%20%2F%2F%20cunoastem%20tipul%20real%20in%20momentul%20compilarii%0A%20%20%20%20creatura.fa_zgomot()%3B%0A%7D%0A%0Afn%20main()%20%7B%0A%20%20%20%20let%20creatura%20%3D%20CreaturaMaritima%20%7B%0A%20%20%20%20%20%20%20%20nume%3A%20String%3A%3Afrom(%22Ferris%22)%2C%0A%20%20%20%20%20%20%20%20zgomot%3A%20String%3A%3Afrom(%22blub%22)%2C%0A%20%20%20%20%7D%3B%0A%20%20%20%20generic_fa_zgomot(%26creatura)%3B%0A%7D%0A
content_markdown: >
Tipurile generice în Rust funcționează mâna în mâna cu trăsăturile. Când descriem un tip parametrizat `T`, putem
constrânge ce tipuri pot fi folosite ca argumente,

listând trăsăturile necesare (în engleză `trait bound`) pe care argumentul trebuie să le implementeze.

În acest exemplu, tipul `T` trebuie să implementeze trăsătură `Foo`:

```rust

fn functia_mea<T>(foo: T)

where
T:Foo
{
...
}

```

Folosind tipurile generice, creăm șabloane de funcții care au tipuri de date ce vor fi înlocuite la momentul
compilării cu tipuri de date cunoscute, permițându-ne să utilizăm apelarea statică.
- title: Prescurtare a Funcțiilor Generice
code: >-
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&code=struct%20CreaturaMaritima%20%7B%0A%20%20%20%20pub%20nume%3A%20String%2C%0A%20%20%20%20zgomot%3A%20String%2C%0A%7D%0A%0Aimpl%20CreaturaMaritima%20%7B%0A%20%20%20%20pub%20fn%20luare_zgomot(%26self)%20-%3E%20%26str%20%7B%0A%20%20%20%20%20%20%20%20%26self.zgomot%0A%20%20%20%20%7D%0A%7D%0A%0Atrait%20FacatorDeZgomot%20%7B%0A%20%20%20%20fn%20fa_zgomot(%26self)%3B%0A%7D%0A%0Aimpl%20FacatorDeZgomot%20for%20CreaturaMaritima%20%7B%0A%20%20%20%20fn%20fa_zgomot(%26self)%20%7B%0A%20%20%20%20%20%20%20%20println!(%22%7B%7D%22%2C%20%26self.luare_zgomot())%3B%0A%20%20%20%20%7D%0A%7D%0A%0Afn%20generic_fa_zgomot(creatura%3A%20%26impl%20FacatorDeZgomot)%0A%7B%0A%20%20%20%20%2F%2F%20cunoastem%20tipul%20real%20in%20momentul%20compilarii%0A%20%20%20%20creatura.fa_zgomot()%3B%0A%7D%0A%0Afn%20main()%20%7B%0A%20%20%20%20let%20creatura%20%3D%20CreaturaMaritima%20%7B%0A%20%20%20%20%20%20%20%20nume%3A%20String%3A%3Afrom(%22Ferris%22)%2C%0A%20%20%20%20%20%20%20%20zgomot%3A%20String%3A%3Afrom(%22blub%22)%2C%0A%20%20%20%20%7D%3B%0A%20%20%20%20generic_fa_zgomot(%26creatura)%3B%0A%7D%0A
content_markdown: >
Rust are o prescurtare pentru exprimarea tipurilor generice constrânse de o trăsătură:

```rust
fn functia_mea(foo: impl Foo) {
...
}
```

Este echivalent cu a scrie:

```rust
fn functia_mea<T>(foo: T)
where
T:Foo
{
...
}
```
- title: Box
code: >-
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&code=struct%20CreaturaMaritima%20%7B%0A%20%20%20%20pub%20nume%3A%20String%2C%0A%20%20%20%20zgomot%3A%20String%2C%0A%7D%0A%0Aimpl%20CreaturaMaritima%20%7B%0A%20%20%20%20pub%20fn%20luare_zgomot(%26self)%20-%3E%20%26str%20%7B%0A%20%20%20%20%20%20%20%20%26self.zgomot%0A%20%20%20%20%7D%0A%7D%0A%0Atrait%20FacatorDeZgomot%20%7B%0A%20%20%20%20fn%20fa_zgomot(%26self)%3B%0A%7D%0A%0Aimpl%20FacatorDeZgomot%20for%20CreaturaMaritima%20%7B%0A%20%20%20%20fn%20fa_zgomot(%26self)%20%7B%0A%20%20%20%20%20%20%20%20println!(%22%7B%7D%22%2C%20%26self.luare_zgomot())%3B%0A%20%20%20%20%7D%0A%7D%0A%0Astruct%20Ocean%20%7B%0A%20%20%20%20animale%3A%20Vec%3CBox%3Cdyn%20FacatorDeZgomot%3E%3E%2C%0A%7D%0A%0Afn%20main()%20%7B%0A%20%20%20%20let%20ferris%20%3D%20CreaturaMaritima%20%7B%0A%20%20%20%20%20%20%20%20nume%3A%20String%3A%3Afrom(%22Ferris%22)%2C%0A%20%20%20%20%20%20%20%20zgomot%3A%20String%3A%3Afrom(%22blub%22)%2C%0A%20%20%20%20%7D%3B%0A%20%20%20%20let%20sarah%20%3D%20CreaturaMaritima%20%7B%0A%20%20%20%20%20%20%20%20nume%3A%20String%3A%3Afrom(%22Sarah%22)%2C%0A%20%20%20%20%20%20%20%20zgomot%3A%20String%3A%3Afrom(%22swish%22)%2C%0A%20%20%20%20%7D%3B%0A%20%20%20%20let%20ocean%20%3D%20Ocean%20%7B%0A%20%20%20%20%20%20%20%20animale%3A%20vec!%5BBox%3A%3Anew(ferris)%2C%20Box%3A%3Anew(sarah)%5D%2C%0A%20%20%20%20%7D%3B%0A%20%20%20%20for%20a%20in%20ocean.animale.iter()%20%7B%0A%20%20%20%20%20%20%20%20a.fa_zgomot()%3B%0A%20%20%20%20%7D%0A%7D%0A
content_markdown: >
`Box` este o structura de date ce ne permite să mutăm date de pe stivă în heap.

`Box` este o structura cunoscută sub denumirea de *smart pointer*, ce conține pointerul către
datele noastre în heap.

Deoarece `Box` este o structură de dimensiune cunoscută (conține doar un pointer), este adesea folosit
atunci când o structură trebuie să cunoască dimensiunea câmpurilor sale. Astfel, în interiorul structurii,

vom stoca o referință prin intermediul lui `Box`.

`Box` este atât de comun încât poate fi utilizat de oriunde:

```rust

Box::new(Foo { ... })

```
- title: Structuri Generice Revizuite
content_markdown: >
Structurile generice pot, de asemenea, să-și aibă tipurile parametrizate constrânse de trăsături:

```rust

struct StructuraMea<T>

where
T: StructuraMea
{
foo: T
...
}

```

Structurile generice își au tipurile parametrizate în blocul lor de implementare:

```rust

impl<T> StructuraMea<T> {
...
}

```
- title: Capitolul 7 - Concluzie
content_markdown: >
Acum avem mai multe particularități ale limbajului prin care să ne exprimăm ideile într-un mod clar!

Abstractizările făcutre de limbajul pot fi simple, însă sunt suficient de puternice pentru a face lucrul cu codul o bucurie.

În acest capitol am aruncat o privire asupra smart pointerilor prin `Box`. În următorul capitol vom învață
despre cum aceștia ne pot ajuta în alte situații de memorie specializate.

Resurse:

* [Video - Object-oriented Programming in 7
minutes](https://www.youtube.com/watch?v=pTB0EiLXUC8)

* [Articol - "The faster you unlearn OOP, the better for you and your
software"](https://dpc.pw/the-faster-you-unlearn-oop-the-better-for-you-and-your-software)