Publicat la https://blogs.devforum.ro/coding-tips-interfete/
Un concept cu care am avut ceva de furcă la început a fost folosirea interfețelor. Peste tot găseam o explicație vag sumară, eventual și ceva legat de un contract și rămâneam cel puțin la fel de confuz ca înainte. Din punctul meu de vedere, dacă nu plănuiești să ai un cod extensibil (e.g. prin plugin-uri),…
Iti dau un exemplu foarte simplu din c# din experienta:
Sa zic ca trebuie sa implementezi o metoda de lucru cu harta. Ai in prima faza de facut pentru google. Te apuci faci, dregi. Apoi iti dau pentru arcgis, sa le faci repede. Pui o gramada de if-uri ca nu te-ai gandit de la inceput.
Si colac peste pupaza zic ca mai ai si de pus open street maps.
Dauna totala!
Si acum metoda simpla: faci o interfata numita iMaps ii pui elegant metodele.
Si cand faci new folosesti activator.createinstance.
Astfel codul tranzactional va ramane curat, respectand astfel principiul open-closed.
TadAAaa!!
Corect?
Exemplele cu square sau circle sunt cele mai de cacat si m-am chinuit ani de zile pana am realizat cat de usoare sunt.
Asta e o combinatie interesanta cu activator: https://drive.google.com/file/d/1Z-DDVtn55sLeXEUCHpLPrLz6GKvpkR7T/view?usp=drivesdk
Cand vezi un legacy code cu if in if in if =>
Aia care au facut nu au fost prosti, doar cei care fac exemplele.
Faza cu Bear extends Animal
si alte exemple d’astea nerealiste e ca majoritatea oamenilor o sa invete despre mostenire, interfete si OOP spre inceputul carierei de programatori - prin liceu, facultate, primele job-uri etc. Si nu poti sa le dai exemple “real world” unde chiar vezi beneficii si unde este o metoda de modelare net superioara alternativelor. Degeaba le zici ca poti sa ai un BlobStore
care poate sa fie pentru S3, sau vre-un NAS sau o baza de date SQL, cand nici macar nu cunosc vre-unul dintre termeni.
Cred ca oricine care a petrecut minim cateva luni intr-o firma de dezvoltare software a auzit de acei termeni
La profilul de calculatoare, exista o materie care explica aceste lucruri. Ingineria programarii + design patterns
Un bun exemplu de folosire al interfetelor, este IRepository. Cel putin in asp .net mvc este destul de folosit
Ia in considerare, ca la facultate ai >100 de oameni si trebuie sa te asiguri ca macar inteleg bazele. Exemplele precum Bear extends Animal
se pot intelege usor de toata lumea.
De asemenea nici unii profesori nu sunt “pregatiti”.
Macar sa treaca examenul
PS: Eu la materia poo, aveam un profesor care nu stia cod. Stiu ca este ciudat. El ne vorbea de alte chestii care nu aveau treaba cu poo, la nivelul anului 2
@iamntz, felicitari pt articol. Foarte bine scris
Sunt si liceeni pe acest forum. Cred ca invata mai multe aici decat la liceu
Pai asta zic. Toata lumea astie de animale, masini, oameni etc. Asa ca e facil sa faci exemple. Dar nu reflecta cum ai folosi in practica tehnicile astea tho’.
hai ca poate nu de S3
Dar de SQL, NAS sigur
+1 pt cantec
Sau poate am asteptari prea mari !
Pentru cei ce nu știu despre ce vorbești (me included), poți explica în câteva cuvinte ce este/ce face IRepository
?
Din ce am inteles eu
Ai o interfata cu metode CRUD.
public interface IStudentRepository
{
//adaugam semanturile metodelor
GetStudents();
GetStudentsById(int id);
InsertStudent(Student st);
UpdateStundent(Student st);
DeleteStudent(int id);
}
//implementam aceste metode
public class StudentRepository : IStudentRepository
{
//aici implemntam logica metodelor definite in interfata
//putem accesa o baza de date sau alt mediu unde sunt stocate acele date
public Student GetStudentById(id)
{
//magia pt a selecta studentul dupa id.
}
//restul de implementari
}
public interface IRepository
{
//adaugam semanturile metodelor
Get();
GetsById(int id); //optionala
Insert(Object o);
Update(Object o);
Delete(int id);
}
//implementam aceste metode
public class Repository : IStudentRepository
{
//aici implemntam logica metodelor definite in interfata
//putem accesa o baza de date sau alt mediu unde sunt stocate acele date
public Student GetById(int id)
{
//magia pt a selecta studentul dupa id.
}
//restul de implementari
}
Eu cu acel IRepository am dat doar un exemplu de folosire al interfetelor
Exemplu adaptat de aici
Pe baza raspunsurui lui Catalin-Ionut, am actualizat raspunsul
Scuze daca am facut offtopic
Un lucru interesant de adaugat la postare ar fi conceptul de traits (https://secure.php.net/manual/en/language.oop5.traits.php) si in ce context ar fi mai util folosirea unei implementari propriu-zise pt composition vs. definirea unei interfete.
Ca ati adus vorba de IRepository …ar fi o problema daca as inregistra mai mult decat metodele CRUD? Adica am IUserRepository cu metodele :
- Create(UserModel user)
- GetUsers()
- GetUser(int id)
- Update/Edit(int id)
- Delete(int id)
- Login(string user, string pass)
Ma intereseaza daca este corect sa am Login() in aceasta interfata, iar Create() sa fie apelat de metoda Register() a controllerului. Sau pentru Login as putea avea separat o alta interfata IAuthRepository (inutila zic eu)
Adica, in Interfata User eu pun toate actiunile create pe User
In primul rand o interfata care e folosita doar o singura data nu isi are scopul ex. IUserRepository in cazul tau, sigur nu o sa mai ai o alta clasa care sa aiba aceleasi functii.
In al doilea rand ai putea modifica interfata sa fie IRepository si sa aiba functiile get(),update(),delete(),create() astfel interfata ar putea fi folosita pentru mai multe repositories.
In ultimul rand un repository ar trebuii sa se ocupe doar de operatiuni cu baza de date iar login, register sau alte chestii legate de autentificare sigur nu au ce sa caute in repository fie el si UserRepository.
De fiecare dată când explici un concept nou este important să te legi de ceva ce audiența cunoaște deja. Folosești metafore și analogii la îndemâna oricui, prin urmare poți face explicații simplificate de genul, indiferent că au sau nu legătură cu programarea (sau IT):
- blockchain funcționează ca un jurnal;
- un array este ca un tren, iar fiecare vagon este elementul unui array;
- un tranzistor funcționează ca un releu (acum 25 de ani, când mă interesa electronica, m-am aciuiat pe lângă un electronist, care îmi mai explica una-alta, dar nu a putut să explice în termeni destul de simpli pentru un copil de ~10 ani ce face un tranzistor, când, de fapt, explicația este banală)
șamd.
Când învățam conceptele OOP eram super frustrat de explicațiile astea: mașină, animal. Ce naiba îmi explică mie ăștia? Eu vreau să fac programare, nu grădină zoologică! Doar că, în momentul în care am înțeles cum funcționează lucrurile, am ajuns la concluzia că astea sunt cele mai apropiate analogii.
Nu sunt chiar perfecte, pentru că OOP nu este ceva natural, care are un corespondent 1:1 în viața reală, dar sunt cele mai potrivite.
Dacă știe cineva o modalitate mai bună de a explica concepte din OOP, chiar sunt curios
Oricum, am ajuns la concluzia că eu eram prea ocupat să fiu nemulțumit de explicație și prea puțin concentrat pe procesul efectiv de învățare, motiv pentru care am avut nevoie de câțiva ani pentru a pricepe (cu adevărat) OOP. Foloseam clase, dar era mai mult guess work. Cert este că a fost un moment (mi-l aduc aminte perfect) în care totul a căpătat brusc sens.
Mai mult sau mai puțin a fost așa:
Mi-a placut lectura !
Pachetul standard de Java introduce foarte Ok conceptul de intefete. Tin minte socul meu cand mi-am dat seama ca nu pot instantia Queue desi vazusem ca exista ca “tip” de date.
Vazusem undeva scris: “progrm to an interface” realy means “program to a supertype”
Un articol scurt dar interesant despre interfete in Go cu o paralela la PHP si un exemplu de utilizare reala in cryptocurrency.