Partea 2 – WordPress și programarea orientată pe obiecte: un exemplu din lumea reală

Publicat: 2021-07-29

În Prezentarea noastră de ansamblu despre WordPress și programarea orientată pe obiecte, am analizat teoria din spatele programării orientate pe obiecte (OOP) și la ce să ne așteptăm când o folosim.

Înainte de a continua cu exemple de codare mai specifice utilizând OOP, în acest articol vom încerca să explicăm cum poate fi abordat un scenariu din lumea reală cu mentalitatea diferită necesară pentru OOP și cum este analizat acest lucru folosind obiecte și clase.

Un scenariu de viață reală: trimiterea unui SMS

Acesta este mai degrabă un scenariu de viață „anterior”, de fapt, deoarece SMS-ul este folosit din ce în ce mai puțin în zilele noastre, dar după cum veți vedea, există un motiv pentru care folosim asta ca exemplu!

Să presupunem că aveți un dispozitiv mobil și doriți să trimiteți un mesaj text uneia dintre persoanele dvs. de contact. Păstrând exemplul cât mai simplu posibil, succesiunea acțiunilor ar fi:

  1. Pregătiți mesajul
  2. Selectați unul dintre contactele dvs. și adăugați-l ca destinatar
  3. Trimite mesajul

Deci, haideți să vedem pașii pe care i-ați urma pentru a trimite mesajul dvs.:

Am adăugat câteva descrieri mai detaliate ale acțiunilor, dar mai mult sau mai puțin tot ceea ce faci sunt 3 pași de bază. Pregătiți mesajul în editorul dispozitivului, selectați destinatarul din contactele dvs. și apoi trimiteți mesajul. Și ai terminat! Mesajul dvs. este acum trimis.

Acum, dacă ar fi să reprezentăm în cod o aplicație care trimite un mesaj SMS ar trebui să analizăm ce rută este mai bine de urmat; abordarea procedurală sau POO.

Aplicația cu abordare procedurală

Dacă sunteți un dezvoltator de pluginuri WordPress, cel mai probabil sunteți familiarizat cu programarea procedurală .

După cum am descris anterior, programarea procedurală este un tip de programare imperativă, în care programele noastre constau din una sau mai multe proceduri. Deci, în calitate de dezvoltator, vă descompuneți pluginul într-o mulțime de variabile care vă dețin datele și funcții care operează pe date.

În exemplul nostru de mai sus cu mesajul SMS, ați efectua o serie de acțiuni care ar duce la rezultatul dorit. După cum probabil ați ghicit deja, ați avea, de exemplu, o variabilă care deține conținutul text al mesajului, o funcție cu un parametru $contact care returnează numărul de telefon și, în final, o funcție care trimite mesajul. În cod ar arăta astfel:

 function get_phone_number( $contact ) { // Code that finds the contact's number in the list of contacts return $phone_number; } function send_sms( $contact, $message ) { $phone_number = get_phone_number( $contact ); // Code that sends the message to this number print "Message Sent!"; }

Și l-ai folosi așa:

 $text = "Hello John"; function send_message( "John Doe", $text );

Așadar, vei finaliza o serie de sarcini care te vor conduce la rezultatul dorit.

În acest exemplu foarte simplu, desigur, care are cerințe limitate și foarte specifice, nu există niciun motiv să luați în considerare utilizarea OOP. Programarea procedurală este mai mult decât suficientă pentru a vă atinge obiectivul. Dar, dacă te gândești la unele scenarii cu privire la modul în care această aplicație s-ar putea extinde în viitor, s-ar putea să realizezi că, pe termen lung, ai putea avea probleme în ceea ce privește scalabilitatea. Vom încerca să explicăm de ce mai jos.

Extinderea aplicației cu abordare procedurală

Să presupunem că doriți să îmbunătățiți această aplicație și să oferiți posibilitatea de a trimite și alte tipuri de mesaje, cum ar fi un e-mail, de exemplu. Funcția care transmite mesajul ar fi diferită în fiecare caz.

Când trimiteți un e-mail, aveți nevoie de adresa de e-mail a persoanei de contact, nu de numărul de telefon. În afară de aceasta, va trebui să adăugăm un parametru în funcția finală send_message() care să corespundă tipului de tehnologie pe care o folosim; e-mail sau SMS.

Codul corespunzător ar putea arăta cam așa:

 function get_phone_number( $contact ) { // Code that finds the contact's number return $phone_number; } function get_email_address( $contact ) { // Code that finds the contact's email address return $email_address; } function send_sms( $contact, $message ) { $phone_number = get_phone_number( $contact ); // Code that sends the message to this number print "SMS Sent!"; } function send_email( $contact, $message ) { $email_address = get_email_address( $contact ); // Code that sends the email to this number print "Email Sent!"; } function send_message( $contact, $message, $technology ) { if ( $technology == "SMS") { send_sms( $phone_number, $message ); } else if ( $technology == "Email") { send_email( $email_address, $message ); } }

Deci, nu este ca și cum acest lucru nu ar putea fi implementat cu o abordare procedurală. Dar dacă sunteți un dezvoltator cu experiență, probabil că ați înțeles deja cum acest lucru ar putea deveni dezordonat în viitor.

Dezavantajele unei abordări procedurale

Ce se întâmplă dacă am avea mai multe tipuri de mesaje? Declarațiile if ar deveni enervant de mari. Și, cel mai important, ce se întâmplă dacă ai avea funcții care folosesc funcția send_message() ? În acest caz, ar trebui să adăugați parametrul $technology și în toate acele funcții.

Pe măsură ce codul dvs. crește, funcțiile vor fi peste tot, ceea ce înseamnă că veți începe să copiați/lipiți bucăți de cod (niciodată de dorit), iar efectuarea unei mici modificări la o funcție ar putea rupe câteva alte funcții. Cu toții am fost acolo. Ați dori să evitați acest lucru și să puteți adăuga cu ușurință caracteristici la codul dvs. fără a interfera prea mult în structură.

Găzduiește-ți site-ul web cu Pressidium

GARANTIE 60 DE ZILE BANI RAPIS

VEZI PLANUL NOSTRU

Programarea orientată pe obiecte (sau POO) este o paradigmă de programare care încearcă să rezolve această problemă, permițându-ne să ne structurem pluginul în bucăți mici de cod reutilizabile, numite clase . După cum am descris în articolul nostru OOP Overview, o clasă este practic un șablon pe care îl folosim pentru a crea instanțe individuale ale clasei, numite obiecte .

Un obiect conține date și cod. Mai avem variabile care pot stoca informații, numite proprietăți . Și proceduri care operează pe date, numite metode .

Aplicația cu abordare OOP

Acum să analizăm același scenariu ca mai sus cu o abordare OOP.

În primul rând, vom defini ce obiecte avem aici, ce caracteristici are fiecare și ce acțiuni efectuează. Caracteristicile sunt ceea ce mai târziu vor fi proprietățile noastre, iar acțiunile vor fi funcțiile sau metodele noastre așa cum sunt numite în OOP.

Să ne gândim la ce avem în primul scenariu de a trimite un SMS în cel mai simplu mod posibil. Există un dispozitiv care are o interfață pe care o folosim pentru a trimite mesajul SMS. Avem conținutul mesajului, alegem un contact ca destinatar și în final mesajul.

 <?php /** * Plugin Name: Send Message */ interface MessagingCapable { public function send_message( $contact, $message ); } class Phone implements MessagingCapable { public function send_message( $contact, $message ) { print "You sent" . $message ; } } function say_hi( MessagingCapable $device, $contact, $message ) { $device->send_message( $contact, $message ); }

Declaram clasa Phone care implementeaza interfata MessagingCapable . Deci trebuie să implementăm toate metodele declarate în el. Funcția say_hi() necesită 3 parametri:

  1. Un dispozitiv care acceptă mesageria
  2. Un contact
  3. Mesajul

Pentru a trimite efectiv un mesaj folosim această funcție astfel:

 $phone = new Phone(); say_hi( $phone, "John Doe", "Hello John" );

Practic, creăm un obiect prin instanțierea clasei Telefon și transmiterea conținutului de contact și mesaj. Aceasta ar scoate:

 You sent "Hello John"

Am demonstrat acest scenariu simplu de trimitere a unui mesaj text folosind clase. În secțiunea următoare, vom vedea cum putem extinde capacitățile aplicației urmând abordarea OOP și, în timp ce creștem, vom examina unde funcțiile OOP își joacă rolul, precum și beneficiile utilizării acestei tehnici.

Extinderea aplicației cu abordarea OOP

Să adăugăm și posibilitatea de a trimite e-mailuri, așa cum am făcut înainte procedural.

Indiferent de dispozitiv, în mod ideal am dori să folosim funcția say_hi() în același mod. Aruncă o privire la codul de mai jos:

 <?php /** * Plugin Name: Send Message */ interface MessagingCapable { public function send_message( $contact, $message ); } class Phone implements MessagingCapable { public function send_message( $contact, $message ) { print ('You sent a "' . $message . '" SMS to ' . $contact ); } } class Computer implements MessagingCapable { public function send_message( $contact, $message ) { print ('You sent a "' . $message . '" email to ' . $contact ); } } function say_hi( MessagingCapable $device, $contact, $message ) { $device->send_message( $contact, $message ); }

Când folosim această bucată de cod, vom ridica dispozitivul mobil pentru a trimite un SMS și computerul pentru a trimite un e-mail. Am fi fie:

 say_hi ( new Phone(), "John Doe", "Hello John" );

sau:

 say_hi ( new Computer(), "John Doe", "Hello John" );

care ar rezulta. You sent a "Hello John" SMS to John Doe și, în mod corespunzător, i You sent a "Hello John" email to John Doe .

Aici începem deja să detectăm unele caracteristici OOP. Am introdus interfețele utilizând interfața MessagingCapable .

O interfață declară un set de metode care trebuie implementate de clasă fără a defini modul în care aceste metode sunt implementate. Toate metodele declarate într-o interfață trebuie să fie publice.

PHP nu acceptă moștenirea multiplă, ceea ce înseamnă că o clasă nu poate moșteni proprietățile/metodele mai multor clase părinte.

Deși poate extinde doar o clasă, poate implementa mai multe interfețe.

Utilizarea unui telefon pentru a trimite un mesaj va fi diferită de utilizarea unui computer. Instanțele de clase diferite acționează diferit atunci când li se cere să efectueze aceeași acțiune (adică send_message() ). Acesta este un exemplu de polimorfism. Dacă mai târziu creăm un nou dispozitiv, nu va trebui să ne modificăm codul pentru a-l acomoda, atâta timp cât toți au aceeași interfață.

De asemenea, am dori să subliniem aici că deja vedem diferența în ceea ce privește lizibilitatea. Modul în care în cele din urmă folosim acest script doar prin codificare:

 say_hi( new Computer(), "John", "Hi" );

Acest lucru este absolut simplu pentru orice dezvoltator care lucrează la proiect. Și, desigur, cu cât pluginul este mai complex, devine mai evident cât de util este acest lucru, mai ales când lucrezi în echipă.

Pentru a încerca și a explica mai bine cât de ușor este să vă extindeți pluginul în Programarea orientată pe obiecte, să încercăm să adăugăm mai multe funcționalități.

Adăugarea de mai multe funcționalități

Dacă vrem să adăugăm posibilitatea de a naviga pe internet, am adăuga doar o interfață suplimentară pentru orice dispozitiv care ar putea răspunde la această abilitate, cum ar fi un computer, de exemplu.

 interface InternetBrowsingCapable { public function visit_website( $url ); }

Implementarea acestei interfețe va fi codificată astfel:

 class Computer implements MessagingCapable, InternetBrowsingCapable { public function send_message( $contact, $message ) { print ('You sent a "' . $message . '" email to ' . $contact ); } public function visit_website( $url ) { print ('You visited "' . $url ); } }

Deci, în clasa actuală Computer am adăugat doar interfața suplimentară care trebuie implementată, deoarece un computer poate trimite un mesaj și naviga pe internet, și metoda visit_website( $url ) .

NOTĂ: Desigur, deoarece vizitarea unei adrese URL este total irelevantă cu funcția say_hi() , vom introduce și o nouă funcție, ceva de genul:

 function visit_url( InternetBrowsingCapable $device, $url ) { $device->visit_website( $url ); }

Si asta e! Pentru orice dispozitiv care poate vizita o adresă URL, putem folosi această funcție așa cum am făcut-o cu computerul. Nu există griji că veți sparge restul funcționalității. Aceasta arată scalabilitatea disponibilă atunci când se utilizează OOP în comparație cu programarea procedurală.

Să adăugăm un dispozitiv smartphone doar pentru a demonstra câteva funcții suplimentare. Iată întregul cod, cu adăugarea clasei smartphone, astfel încât să puteți avea o imagine mai bună a ceea ce se întâmplă:

 <?php /* * Plugin Name: Communication Plugin */ interface MessagingCapable { public function send_message( $contact, $message ); } interface InternetBrowsingCapable { public function visit_website( $url ); } class Phone implements MessagingCapable { public function send_message( $contact, $message ) { print 'You sent a "' . $message . '" SMS to ' . $contact; } } class Computer implements MessagingCapable, InternetBrowsingCapable { public function send_message( $contact, $message ) { print 'You sent a "' . $message . '" email to ' . $contact; } public function visit_website( $url ) { print 'You visited "' . $url; } } class Smartphone extends Phone implements InternetBrowsingCapable { public function visit_website( $url ) { print 'You visited "' . $url; } public function send_message( $contact, $message ) { parent::send_message( $contact, $message ); print ' from your smartphone'; } } function say_hi( MessagingCapable $device, $contact, $message ) { $device->send_message( $contact, $message ); } function visit_url( InternetBrowsingCapable $device, $url ) { $device->visit_website( $url ); }

Clasa Smartphone extinde clasa părinte Phone și implementează interfața InternetBrowsingCapable . Aceasta înseamnă că poate trimite un mesaj și poate vizita o adresă URL. Aici detectăm caracteristica Moștenire. Cu alte cuvinte, avem o ierarhie de clase, o clasă părinte (Telefon) și o subclasă (Smartphone).

Deci, un obiect Smartphone moștenește toate proprietățile și comportamentele clasei părinte Phone. Astfel, în interiorul clasei copil putem adăuga o metodă sau suprascrie o metodă a clasei părinte, așa cum am făcut cu send_message() din clasa Smartphone. Am făcut asta pentru a schimba rezultatul. Am putea ignora total această metodă și să folosim send_message() al clasei părinte așa cum este.

Puteți încerca singur codul lipindu-l în blocul de cod în acest minunat instrument online PHP. Sub cod, încercați oricare dintre aceste linii de cod și vedeți diferitele rezultate.

 say_hi ( new Phone(), "John Doe", "Hello John" ); say_hi ( new Computer(), "John Doe", "Hello John" ); say_hi ( new Smartphone(), "John Doe", "Hello John" ); visit_url ( new Smartphone(), "https://www.pressidium.com" ); visit_url ( new Computer(), "https://www.pressidium.com" );

Pentru o înțelegere și mai bună a întregului concept, aruncați o privire la diagrama de clasă a codului de mai sus.

După cum este descris mai sus, atunci când proiectăm relațiile dintre clase, nu includem elementele comune în clasa copil. Mai mult, nu uitați să acordați atenție ghidului din stânga pentru a putea identifica relațiile și vizibilitatea proprietăților și metodelor acestora.

Dacă doriți să vedeți și funcția de Encapsulare în acțiune, încercați să includeți o clasă Contact în oricare dintre exemplele de scripturi de mai sus pe care le-am furnizat. Clasa ar arăta astfel:

 class Contact { private $name; private $phone_number; private $email_address; public function __construct( $name, $phone_number, $email_address ) { $this->name = $name; $this->phone_number = $phone_number; $this->email_address = $email_address; } public function get_name() { return $this->name; } public function get_phone_number() { return $this->phone_number; } public function get_email_address() { return $this->email_address; } }

Metoda __construct() , prin proiectare, este apelată automat la crearea unui obiect. Acum, când instanțiem clasa Contact, constructorul acesteia este apelat și stabilește valorile proprietăților sale private. Apoi folosim metodele publice get_name() , get_phone_number() și get_email_address() pentru a prelua aceste valori.

Încapsularea este gruparea datelor cu metodele care operează pe date, restricționând în același timp accesul direct, prevenind expunerea detaliilor ascunse de implementare.

Concluzie

Sperăm că acest articol v-a ajutat să înțelegeți programarea orientată pe obiecte într-un mod mai practic. OOP ajută cu adevărat să faciliteze extinderea aplicației în viitor, dacă este necesar, fiind clară și reutilizabilă.

În plus, un plugin care utilizează OOP va fi mai rapid și mai ușor de executat. Asta pentru că metodele care sunt comune pentru toate obiectele unei clase consumă memorie o singură dată, în timpul declarației lor.

Securitatea este, de asemenea, îmbunătățită datorită încapsulării. Pe de altă parte, în programarea procedurală, toate datele sunt globale, ceea ce înseamnă că accesul este disponibil de oriunde.

Ca urmare a celor de mai sus, întreținerea codului, productivitatea, scalabilitatea și depanarea devin, de asemenea, mult mai ușoare pentru tine și echipa ta.

În următoarele articole din această serie vom vedea acest stil de programare în acțiune prin aplicarea lui unui plugin WordPress. Mai exact, vom crea o copie a pluginului Limit Login Attempts, versiunea 1.7.1, creată de Johan Eenfeldt, dar convertită pe cât posibil cu o abordare orientată pe obiecte.

În timpul acestui proces, vom descompune fluxul de plugin și vom stabili cerințele. În continuare, vom încerca primele noastre gânduri cu privire la designul pluginului și, în etapa de implementare, vom scrie codul. În timpul procesului de implementare vom face câteva retrogradări și reproiectăm, dacă este necesar, pentru a obține rezultatele dorite.

Totuși, nu vom intra în detalii despre toate părțile codului. În schimb, am dori să ne concentrăm pe partajarea modului în care pluginurile sunt construite în modul orientat pe obiecte. Suntem încrezători că, odată ce ați terminat de citit această serie de articole, vă puteți crea foarte bine un plugin OOP.

Faceți clic aici pentru a citi partea 3 din seria noastră de programare orientată pe obiecte

Vezi si

  • WordPress și programarea orientată pe obiecte – O prezentare generală