Bölüm 2 – WordPress ve Nesne Yönelimli Programlama: Gerçek Bir Dünya Örneği

Yayınlanan: 2021-07-29

WordPress ve Nesne Yönelimli Programlamaya Genel Bakış bölümünde, Nesne Yönelimli Programlamanın (OOP) arkasındaki teoriyi ve onu kullanırken ne bekleyebileceğimizi inceledik.

OOP kullanarak daha spesifik kodlama örneklerine geçmeden önce, bu yazıda OOP için gereken farklı zihniyet ile gerçek dünya senaryosuna nasıl yaklaşılabileceğini ve bunun nesneler ve sınıflar kullanılarak nasıl analiz edildiğini açıklamaya çalışacağız.

Gerçek Hayat Senaryosu: SMS Gönderme

Bu daha çok bir “geçmiş” yaşam senaryosu gibi aslında çünkü günümüzde SMS giderek daha az kullanılıyor ama göreceğiniz gibi, bunu örnek olarak kullanmamızın bir nedeni var!

Bir mobil cihazınız olduğunu ve kişilerinizden birine kısa mesaj göndermek istediğinizi varsayalım. Örneği mümkün olduğunca basit tutmak, eylemlerin sırası şöyle olacaktır:

  1. Mesajı hazırlayın
  2. Kişilerinizden birini seçin ve alıcı olarak ekleyin
  3. mesajı gönder

Öyleyse, mesajınızı göndermek için izleyeceğiniz adımları görselleştirmeye çalışalım:

Eylemlerin bazı daha ayrıntılı açıklamalarını ekledik, ancak az ya da çok yaptığınız tek şey 3 temel adım. Mesajı cihaz düzenleyicide hazırlarsınız, kişilerinizden alıcıyı seçersiniz ve ardından mesajı gönderirsiniz. Ve işin bitti! Mesajınız şimdi gönderildi.

Şimdi, SMS mesajı gönderen bir uygulamayı kodda temsil edeceksek, hangi rotayı izlemenin daha iyi olduğunu analiz etmeliyiz; prosedürel veya OOP yaklaşımı.

Usul Yaklaşımıyla Başvuru

Bir WordPress eklenti geliştiricisiyseniz, büyük olasılıkla prosedürel programlamaya aşinasınızdır.

Daha önce tanımladığımız gibi, prosedürel programlama, programlarımızın bir veya daha fazla prosedürden oluştuğu bir tür zorunlu programlamadır. Bu nedenle, bir geliştirici olarak eklentinizi, verilerinizi tutan bir dizi değişkene ve veriler üzerinde çalışan işlevlere bölersiniz.

Yukarıdaki örneğimizde SMS mesajı ile istenen sonuca götürecek bir dizi işlem gerçekleştireceksiniz. Tahmin edebileceğiniz gibi, örneğin, mesajın metin içeriğini tutan bir değişkene, telefon numarasını döndüren $contact parametreli bir fonksiyona ve son olarak mesajı gönderen bir fonksiyona sahip olacaksınız. Kodda şöyle görünecektir:

 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!"; }

Ve bunu şu şekilde kullanırsın:

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

Böylece, sizi istenen sonuca götürecek bir dizi görevi tamamlarsınız.

Sınırlı ve çok özel gereksinimleri olan bu çok basit örnekte, elbette, OOP kullanmayı düşünmek için hiçbir neden yoktur. Prosedürel programlama, hedefinize ulaşmak için fazlasıyla yeterlidir. Ancak, bu uygulamanın gelecekte nasıl genişleyebileceğine dair bazı senaryolar düşünürseniz, uzun vadede ölçeklenebilirlik açısından sorunlarınızın olabileceğini fark edebilirsiniz. Nedenini aşağıda açıklamaya çalışacağız.

Prosedürel Yaklaşımla Uygulamayı Genişletme

Diyelim ki bu uygulamayı geliştirmek ve örneğin bir e-posta gibi başka türde mesajlar gönderme yeteneği sağlamak istiyorsunuz. Mesajı ileten işlev her durumda farklı olacaktır.

Bir e-posta gönderirken, telefon numarasına değil, kişinin e-posta adresine ihtiyacınız vardır. Bunun dışında, son send_message() işlevinde kullandığımız teknolojinin türüne karşılık gelecek bir parametre eklememiz gerekecek; e-posta veya SMS.

Karşılık gelen kod şöyle görünebilir:

 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 ); } }

Yani prosedürel bir yaklaşımla uygulanamayacak bir şey değil. Ancak deneyimli bir geliştiriciyseniz, bunun gelecekte nasıl dağınık hale gelebileceğini muhtemelen zaten anlamışsınızdır.

Prosedürel Yaklaşımın Sakıncaları

Ya birden fazla türde mesajımız olsaydı? if ifadeleri can sıkıcı bir şekilde büyüyecekti. Ve en önemlisi, ya send_message() işlevini kullanan işlevleriniz olsaydı? Bu durumda, tüm bu işlevlere $technology parametresini de eklemeniz gerekir.

Kodunuz büyüdükçe, işlevler her yerde olacak, yani kod parçalarını kopyalamaya/yapıştırmaya başlayacaksınız (asla istenmez) ve bir işlevde küçük bir değişiklik yapmak diğer birçok işlevi bozabilir. Hepimiz oradaydık. Bundan kaçınmak ve yapıya çok fazla müdahale etmeden kodunuza kolayca özellikler ekleyebilmek istersiniz.

Pressidium ile web sitenizi barındırın

60 GÜN PARA GERİ GARANTİSİ

PLANLARIMIZI GÖRÜN

Nesne yönelimli programlama (veya OOP), eklentimizi class adı verilen küçük, yeniden kullanılabilir kod parçalarına yapılandırmamıza izin vererek bu sorunu çözmeye çalışan bir programlama paradigmasıdır. OOP'ye Genel Bakış makalemizde açıkladığımız gibi, sınıf temel olarak, sınıfın nesneler adı verilen bireysel örneklerini oluşturmak için kullandığımız bir şablondur.

Bir nesne veri ve kod içerir. Hâlâ özellikler adı verilen bilgileri depolayabilen değişkenlerimiz var. Ve yöntemler adı verilen veriler üzerinde çalışan prosedürler.

OOP Yaklaşımıyla Uygulama

Şimdi yukarıdakiyle aynı senaryoyu bir OOP yaklaşımıyla analiz edelim.

İlk olarak, burada hangi nesnelere sahip olduğumuzu, her birinin hangi özelliklere sahip olduğunu ve hangi eylemleri gerçekleştirdiklerini tanımlayacağız. Karakteristikler, daha sonra özelliklerimiz olacaklardır ve eylemler, OOP'de çağrıldıkları gibi işlevlerimiz veya yöntemlerimiz olacaktır.

Mümkün olan en basit şekilde SMS göndermenin ilk senaryosunda nelere sahip olduğumuzu düşünelim. SMS mesajı göndermek için kullandığımız arayüze sahip bir cihaz var. Mesaj içeriğine sahibiz, alıcı olarak bir kişiyi ve son olarak mesajı seçiyoruz.

 <?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 ); }

MessagingCapable arabirimini uygulayan Phone sınıfını ilan ediyoruz. Bu yüzden içinde açıklanan tüm yöntemleri uygulamak zorundayız. say_hi() işlevi 3 parametre gerektirir:

  1. Mesajlaşmayı destekleyen bir cihaz
  2. Bir kişi
  3. Mesaj

Gerçekten bir mesaj göndermek için bu işlevi şu şekilde kullanırız:

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

Temel olarak Phone sınıfını başlatarak ve iletişim ve mesaj içeriğini ileterek bir nesne oluşturuyoruz. Bu çıktı:

 You sent "Hello John"

Sınıfları kullanarak kısa mesaj göndermenin bu basit senaryosunu gösterdik. Bir sonraki bölümde, OOP yaklaşımını izleyerek uygulamanın yeteneklerini nasıl genişletebileceğimizi göreceğiz ve ölçeklendirirken, OOP özelliklerinin nerede rol oynadığını ve bu tekniği kullanmanın faydalarını inceleyeceğiz.

Uygulamanın OOP yaklaşımıyla genişletilmesi

Daha önce prosedürel olarak yaptığımız gibi, e-posta gönderme özelliğini de ekleyelim.

Cihazdan bağımsız olarak, ideal olarak say_hi() işlevini aynı şekilde kullanmak isteriz. Aşağıdaki koda bir göz atın:

 <?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 ); }

Bu kod parçasını kullandığımızda, SMS göndermek için mobil cihazı ve e-posta göndermek için bilgisayarı alırdık. Biz de:

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

veya:

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

You sent a "Hello John" SMS to John Doe You sent a "Hello John" email to John Doe .

Burada zaten bazı OOP özelliklerini tespit etmeye başladık. Arayüzleri MessagingCapable arayüzünü kullanarak tanıttık.

Bir arabirim, bu yöntemlerin nasıl uygulanacağını tanımlamadan sınıf tarafından uygulanması gereken bir dizi yöntem bildirir. Bir arabirimde bildirilen tüm yöntemler genel olmalıdır.

PHP çoklu kalıtımı desteklemez, yani bir sınıf birden çok ebeveyn sınıfın özelliklerini/yöntemlerini devralamaz.

Yalnızca bir sınıfı genişletebilirken, birden çok arabirim uygulayabilir.

Mesaj göndermek için Telefon kullanmak Bilgisayar kullanmaktan farklı olacaktır. Aynı eylemi gerçekleştirmeleri istendiğinde farklı sınıfların örnekleri farklı davranır (yani send_message() ). Bu bir Polimorfizm örneğidir. Daha sonra yeni bir cihaz oluşturursak, hepsi aynı arayüzü paylaştığı sürece kodumuzu buna uyum sağlayacak şekilde değiştirmemiz gerekmeyecektir.

Okunabilirlikteki farkı zaten gördüğümüzü de burada belirtmek isteriz. Sonunda bu betiği sadece kodlayarak kullanma şeklimiz:

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

Bu, proje üzerinde çalışan herhangi bir geliştirici için tamamen basittir. Ve elbette, eklenti ne kadar karmaşıksa, bunun ne kadar yararlı olduğu, özellikle bir ekipte çalışırken daha belirgin hale geliyor.

Eklentinizi Nesne Yönelimli Programlama'da genişletmenin ne kadar kolay olduğunu daha iyi denemek ve açıklamak için biraz daha işlevsellik eklemeyi deneyelim.

Daha Fazla İşlevsellik Ekleme

İnternette gezinme özelliğini eklemek istersek, örneğin bir bilgisayar gibi bu yeteneğe yanıt verebilecek herhangi bir cihaz için fazladan bir arayüz ekleriz.

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

Bu arayüzün uygulanması şu şekilde kodlanacaktır:

 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 ); } }

Bu nedenle, mevcut Computer sınıfında, bir bilgisayar bir mesaj gönderip internette gezinebileceğinden, uygulanacak ekstra arayüzü ve visit_website( $url ) yöntemini ekledik.

NOT: Elbette, bir url'yi ziyaret etmek say_hi() işleviyle tamamen alakasız olduğundan, yeni bir işlev de tanıtacağız, buna benzer bir şey:

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

Ve bu kadar! Bir URL'yi ziyaret edebilen herhangi bir cihaz için bu işlevi bilgisayarda yaptığımız gibi kullanabiliriz. İşlevselliğin geri kalanını kıracağınız konusunda endişelenmenize gerek yok. Bu, prosedürel programlamaya kıyasla OOP kullanıldığında mevcut ölçeklenebilirliği gösterir.

Sadece daha fazla özellik göstermek için bir akıllı telefon cihazı ekleyelim. Neler olup bittiğini daha iyi görebilmeniz için akıllı telefon sınıfının eklenmesiyle birlikte kodun tamamı burada:

 <?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 ); }

Smartphone sınıfı, Phone üst sınıfını genişletir ve InternetBrowsingCapable arabirimini uygular. Bu, bir mesaj gönderebileceği ve bir URL'yi ziyaret edebileceği anlamına gelir. Burada Kalıtım özelliğini tespit ediyoruz. Başka bir deyişle, bir sınıf hiyerarşimiz var, bir üst sınıf(Telefon) ve bir alt sınıf(Akıllı telefon).

Böylece bir Smartphone nesnesi, üst Phone sınıfının tüm özelliklerini ve davranışlarını devralır. Bu şekilde, Smartphone sınıfındaki send_message() ile yaptığımız gibi, alt sınıf içinde bir yöntem ekleyebilir veya üst sınıfın bir yöntemini geçersiz kılabiliriz. Bunu çıktıyı değiştirmek için yaptık. Bu yöntemi tamamen yok sayabilir ve ana sınıfın send_message() olduğu gibi kullanabiliriz.

Bu harika PHP çevrimiçi aracının kod bloğuna yapıştırarak kodu kendiniz deneyebilirsiniz. Kodun altında, bu kod satırlarından herhangi birini deneyin ve farklı sonuçları görün.

 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" );

Tüm kavramı daha da iyi anlamak için yukarıdaki kodun Sınıf diyagramına bakın.

Yukarıda gösterildiği gibi, sınıflar arasındaki ilişkileri tasarlarken, alt sınıftaki ortak öğeleri dahil etmiyoruz. Ayrıca, bunların özelliklerinin ve yöntemlerinin ilişkilerini ve görünürlüğünü belirleyebilmeniz için soldaki kılavuza dikkat etmeyi unutmayın.

Kapsülleme özelliğini de çalışırken görmek istiyorsanız, sağladığımız yukarıdaki örnek komut dosyalarından herhangi birine bir Contact sınıfı eklemeyi deneyin. Sınıf şöyle görünecek:

 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; } }

__construct() yöntemi, tasarım gereği, bir nesne oluşturulduğunda otomatik olarak çağrılır. Şimdi Contact sınıfını başlattığımızda, yapıcısı çağrılır ve özel özelliklerinin değerlerini ayarlar. Sonra bu değerleri almak için get_name() , get_phone_number() ve get_email_address() genel yöntemleri olan “alıcılarımızı” kullanırız.

Kapsülleme, gizli uygulama ayrıntılarının açığa çıkmasını önleyen doğrudan erişimi kısıtlarken, veriler üzerinde çalışan yöntemlerle verileri bir araya getiriyor.

Çözüm

Umarım bu makale, Nesne Yönelimli programlamayı daha pratik bir şekilde anlamanıza yardımcı olmuştur. OOP, gerektiğinde net ve yeniden kullanılabilir olması sayesinde uygulamanın gelecekte genişletilmesini gerçekten kolaylaştırmaya yardımcı olur.

Ek olarak, OOP kullanan bir eklentinin yürütülmesi daha hızlı ve daha kolay olacaktır. Bunun nedeni, bir sınıfın tüm nesneleri için ortak olan yöntemlerin, bildirimleri sırasında yalnızca bir kez bellek tüketmesidir.

Kapsülleme nedeniyle güvenlik de artırılmıştır. Prosedürel programlamada ise, tüm veriler küreseldir, bu da erişime her yerden erişilebileceği anlamına gelir.

Yukarıdakilerin bir sonucu olarak, kod bakımı, üretkenlik, ölçeklenebilirlik ve sorun giderme de siz ve ekibiniz için çok daha kolay hale gelir.

Bu dizinin sonraki makalelerinde, bu programlama stilini bir WordPress eklentisine uygulayarak iş başında göreceğiz. Spesifik olarak, Johan Eenfeldt tarafından oluşturulan ancak mümkün olduğunca Nesne Yönelimli bir yaklaşımla dönüştürülen Limit Login Attempts eklentisi sürüm 1.7.1'in bir kopyasını oluşturacağız.

Bu işlem sırasında eklenti akışını parçalayacağız ve gereksinimleri belirleyeceğiz. İleride, eklentinin tasarımıyla ilgili ilk düşüncelerimizi deneyeceğiz ve uygulama adımında kodu yazacağız. Uygulama sürecinde, istenen sonuçları elde etmek için bazı ileri geri adımlar atacağız ve gerekirse yeniden tasarlayacağız.

Yine de kodun tüm bölümleriyle ilgili ayrıntılara girmeyeceğiz. Bunun yerine, eklentilerin Nesne Yönelimli şekilde oluşturulma şeklini paylaşmaya odaklanmak istiyoruz. Bu makale dizisini okumayı bitirdikten sonra, kendinize ait bir OOP eklentisi oluşturabileceğinizden eminiz.

Nesneye Yönelik Programlama Serimizdeki Bölüm 3'ü okumak için buraya tıklayın

Ayrıca bakınız

  • WordPress ve Nesne Yönelimli Programlama – Genel Bakış