Kaixo! Programatzaile askok Objektuei Orientatutako Programazioaren (OOP) oinarrizko lau zutabeak ikasten dituzte: Enkapsulazioa, Abstrakzioa, Herentzia eta Polimorfismoa. Baina definizio horiek ezagutzearen eta software garbi, ulergarri eta mantentze erraza sortzeko modu eraginkorrean aplikatzearen artean alde handia dago. Osagaiak ezagutzea eta sukaldari trebea izatea bezalakoa da.
Gaur, benetan objektuetara orientatuta pentsatzen lagunduko dizuten bost diseinu-printzipio eta "eztizko aholku" partekatuko ditut.
1. Aholkua: Pentsatu "Da" vs. "Du". Herentzia baino, Konposizioa hobe
Hau da OOP diseinuan hasiberriek egiten duten akats ohikoenetako bat: herentzia gehiegi erabiltzea.
- Herentzia ("Da" harreman bat): Klase bat beste baten mota espezifiko bat denean erabiltzen da. Adibidez, Txakurra Animalia da. Hemen herentzia egokia da.
- Konposizioa ("Du" harreman bat): Klase batek beste klase bateko instantzia bat duenean erabiltzen da, harekin elkarlanean aritzeko. Adibidez, Kotxe batek Motor bat du. Kotxe klasea ez da Motor klasearen ondorengoa izan behar.
Aholkua: Zalantza duzunean, lehenetsi konposizioa herentziaren gainetik. Zergatik? Herentziak hierarkia zurrunak sortzen ditu. Kotxe klaseak Motor klasetik heredatzen badu, beti izango da motor mota horri lotua. Konposizioarekin, ordea, Kotxe klaseak Motor interfaze bat izan dezake, eta exekuzio-garaian motor desberdinak (elektrikoa, gasolina...) trukatu ahal izango ditugu.
Onura: Konposizioak diseinu malguagoak, modularragoak eta berrerabilgarriagoak sortzen ditu.
2. Aholkua: Enkapsulatu aldatzen dena
Hau "Design Patterns" (GoF) liburu ospetsuaren printzipio klasiko bat da.
Arazoa: Zure aplikazioaren zati batzuk maiz aldatzeko joera dute (adibidez, zerga-kalkuluaren arauak herrialdearen arabera, datu-basearen motorra, kanpoko API baten inplementazioa...). Aldaketa bakoitzak zure kodearen zati asko ukitzea eskatzen badu, arazo bat duzu.
Irtenbidea: Identifikatu zure sistemaren portaera aldakorrak eta isolatu itzazu interfaze egonkor baten atzean.
Adibidea: Faktura klase baten barruan if/else egitura erraldoi bat izan beharrean zerga desberdinak kalkulatzeko, sortu ZergaKalkulatzailea izeneko interfaze bat.
public interface ZergaKalkulatzailea {
double kalkulatuZergak(double zenbatekoa);
}
public class BEZKalkulatzailea implements ZergaKalkulatzailea { ... }
public class AEBZergaKalkulatzailea implements ZergaKalkulatzailea { ... }
Orain, zure Faktura klaseak ZergaKalkulatzailea interfazearekin bakarrik hitz egingo du, eta ez inplementazio zehatzekin.
Onura: Aldaketak isolatzen ditu, sistema mantentzeko eta hedatzeko askoz errazagoa bihurtuz, lehendik dagoen funtzionalitatea apurtu gabe.
3. Aholkua: Programatu interfaze batera, ez inplementazio batera
Aurreko aholkuarekin erabat lotuta dago. Hau da kode desakoplatua, malgua eta probatzeko erraza idazteko oinarrietako bat.
Arazoa: Zure kodea klase konkretuekin josita dago. ArrayList<String> nireZerrenda = new ArrayList<>();
Irtenbidea: Erabili beti interfazea aldagaiaren mota gisa, posible denean. List<String> nireZerrenda = new ArrayList<>();
Zergatik da hobea? Aldaketa txiki honek esan nahi du nireZerrenda aldagaiari lotutako kode guztiak List interfazearen metodoak bakarrik ezagutzen dituela, eta ez ArrayList-en metodo espezifikoak. Bihar, errendimenduagatik, LinkedList bat erabili behar baduzu, lerro bakar bat aldatu beharko duzu, eta gainerako kode guztiak funtzionatzen jarraituko du.
Onura: Kode desakoplatua sortzen du. Inplementazioak erraz truka ditzakezu (adibidez, datu-baseko driver-a aldatu, probetarako "mock" objektu bat erabili) bezero-kodean eragin gabe.
4. Aholkua: Klase bakoitzak, ardura bakarra (SRP)
Hau SOLID printzipioen artean garrantzitsuena eta ulertzeko errazena da: Erantzukizun Bakarraren Printzipioa (Single Responsibility Principle).
Definizioa: "Klase batek aldatzeko arrazoi bakarra izan beharko luke".
Arazoa: Dena egiten saiatzen diren "Jainko Klaseak" (God Classes). Klase bakar batek datu-basearekin konektatzen du, JSON-a parseatzen du, erabiltzailearen sarrera kudeatzen du eta fitxategiak idazten ditu. Klase hauek mantentzea amesgaizto bat da.
Irtenbidea: Klaseak ardura txiki eta fokalizatuetan banatzea. Erabiltzailea objektu batek ez luke bere burua datu-basean gordetzeaz arduratu behar. Hori ErabiltzaileRepositorioa baten lana da. Erabiltzailea klaseak erabiltzailearen datuak eta horiei lotutako negozio-logika kudeatzeaz bakarrik arduratu beharko litzateke.
Onura: Klase txikiagoak, ulergarriagoak, probatzeko errazagoak eta berrerabilgarriagoak lortzen dira.
5. Aholkua: Esan, ez galdetu (Tell, Don't Ask)
Printzipio honek enkapsulazio sendoagoa eta objektu adimentsuagoak sustatzen ditu.
Arazoa ("Galdetzea"): Objektu bati bere datuak eskatzen dizkion kodea, eta gero, datu horiekin, objektutik kanpo erabakiak hartzen dituena.
// Estilo hau saihestu
if (kontua.getBalantzea() > zenbatekoa) {
kontua.setBalantzea(kontua.getBalantzea() - zenbatekoa);
}
Irtenbidea ("Esatea"): Logika hori datuen jabe den objektuaren barrura eramatea. Objektuak bere egoeraren arduraduna izan behar du.
// Estilo hau nahiago
// Kontu klasearen barruan, withdraw metodoak logika du
public class Kontua {
private double balantzea;
public void withdraw(double zenbatekoa) {
if (this.balantzea > zenbatekoa) {
this.balantzea -= zenbatekoa;
} else {
// throw new Exception...
}
}
}
// Bezero-kodea
kontua.withdraw(zenbatekoa);
Onura: Enkapsulazio sendoa sustatzen du eta objektu "adimentsuagoak" sortzen ditu, beren portaeraren arduradun direnak.
Amaiera: Pentsatu Objektuetan, ez bakarrik klaseetan
Objektuei Orientatutako Programazioa ez da lengoaiaren ezaugarri multzo bat soilik; softwarearen diseinuari buruz pentsatzeko modu bat da. Printzipio hauek aplikatuz, klaseak idaztetik haratago joan eta sistema sendo, malgu eta mantentze errazak eraikitzera pasako zara.
댓글