パート2– WordPressとオブジェクト指向プログラミング:実際の例

公開: 2021-07-29

WordPressとオブジェクト指向プログラミングの概要では、オブジェクト指向プログラミング(OOP)の背後にある理論と、それを使用するときに何を期待できるかについて説明しました。

OOPを使用したより具体的なコーディング例に進む前に、この記事では、OOPに必要なさまざまな考え方で実際のシナリオにアプローチする方法と、オブジェクトとクラスを使用してこれを分析する方法について説明します。

実際のシナリオ:SMSの送信

これは、実際にはSMSの使用が少なくなっている「過去の」ライフシナリオに似ていますが、ご覧のとおり、これを例として使用する理由があります。

モバイルデバイスがあり、連絡先の1つにテキストメッセージを送信するとします。 例をできるだけ単純に保つと、アクションのシーケンスは次のようになります。

  1. メッセージを準備する
  2. 連絡先の1つを選択し、受信者として追加します
  3. メッセージを送信する

それでは、メッセージを送信するために従う手順を視覚化してみましょう。

アクションのより詳細な説明を追加しましたが、多かれ少なかれ、実行するのは3つの基本的なステップだけです。 デバイスエディタでメッセージを準備し、連絡先から受信者を選択して、メッセージを送信します。 そして、あなたは完了です! メッセージが送信されました。

ここで、SMSメッセージを送信するアプリケーションをコードで表す場合は、どのルートをたどるのがよいかを分析する必要があります。 手続き型またはOOPアプローチ。

手続き型アプローチによるアプリケーション

WordPressプラグインの開発者であれば、手続き型プログラミングに精通している可能性があります。

前に説明したように、手続き型プログラミングは命令型プログラミングの一種であり、プログラムは1つ以上の手続きで構成されています。 したがって、開発者は、プラグインをデータを保持する一連の変数と、データを操作する関数に分解します。

上記のSMSメッセージの例では、目的の結果につながる一連のアクションを実行します。 すでにお察しのとおり、たとえば、メッセージのテキストコンテンツを保持する変数、電話番号を返す$contactパラメータを持つ関数、そして最後にメッセージを送信する関数があります。 コードでは、次のようになります。

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

そして、あなたはそれをこのように使うでしょう:

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

したがって、目的の結果につながる一連のタスクを完了することになります。

もちろん、この非常に単純な例では、要件が限定的で非常に具体的であるため、OOPの使用を検討する理由はまったくありません。 手続き型プログラミングは、目標を達成するのに十分すぎるほどです。 ただし、このアプリケーションが将来どのように拡張されるかについていくつかのシナリオを考えると、長期的には、スケーラビリティの点で問題が発生する可能性があることに気付くかもしれません。 その理由を以下に説明します。

手続き型アプローチによるアプリケーションの拡張

このアプリケーションを改善し、たとえば電子メールなどの他の種類のメッセージも送信する機能を提供したいとします。 メッセージを配信する機能は、それぞれの場合で異なります。

メールを送信するときは、電話番号ではなく、連絡先のメールアドレスが必要です。 これとは別に、使用するテクノロジーのタイプに対応するパラメーターを最終的なsend_message()関数に追加する必要があります。 電子メールまたはSMS。

対応するコードは次のようになります。

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

したがって、これを手続き型アプローチで実装できなかったわけではありません。 しかし、経験豊富な開発者であれば、これが将来どのように厄介になる可能性があるかをすでに理解しているでしょう。

手続き型アプローチの欠点

複数の種類のメッセージがある場合はどうなりますか? ifステートメントは煩わしく大きくなります。 そして、最も重要なのは、 send_message()関数を使用する関数がある場合はどうなるでしょうか。 その場合、これらすべての関数にも$technologyパラメーターを追加する必要があります。

コードが大きくなるにつれて、関数はいたるところに存在するようになります。つまり、コードのチャンクをコピー/貼り付けし始めることになり(望ましくない)、関数に小さな変更を加えると、他のいくつかの関数が破損する可能性があります。 私たちは皆そこにいました。 これを回避し、構造にあまり干渉することなく、コードに機能を簡単に追加できるようにする必要があります。

Pressidiumであなたのウェブサイトをホストする

60日間の返金保証

私たちの計画を見る

オブジェクト指向プログラミング(またはOOP)は、プラグインをクラスと呼ばれる小さくて再利用可能なコードに構造化できるようにすることで、この問題を解決しようとするプログラミングパラダイムです。 OOPの概要の記事で説明したように、クラスは基本的に、オブジェクトと呼ばれるクラスの個々のインスタンスを作成するために使用するテンプレートです。

オブジェクトにはデータとコードが含まれています。 プロパティと呼ばれる、情報を格納できる変数がまだあります。 そして、メソッドと呼ばれる、データを操作するプロシージャ。

OOPアプローチによるアプリケーション

次に、OOPアプローチを使用して上記と同じシナリオを分析しましょう。

まず、ここにあるオブジェクト、それぞれにある特性、およびそれらが実行するアクションを定義します。 特性は、後でプロパティになり、アクションは、OOPで呼び出される関数またはメソッドになります。

可能な限り簡単な方法でSMSを送信する最初のシナリオで私たちが持っているものについて考えてみましょう。 SMSメッセージの送信に使用するインターフェイスを備えたデバイスがあります。 メッセージの内容があり、受信者として連絡先を選択し、最後にメッセージを選択します。

 <?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インターフェースを実装するPhoneクラスを宣言します。 したがって、そこで宣言されているすべてのメソッドを実装する必要があります。 say_hi()関数には3つのパラメーターが必要です。

  1. メッセージングをサポートするデバイス
  2. 連絡先
  3. メッセージ

実際にメッセージを送信するには、次のような関数を使用します。

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

基本的に、Phoneクラスをインスタンス化し、連絡先とメッセージのコンテンツを渡すことによってオブジェクトを作成しています。 これにより、次のように出力されます。

 You sent "Hello John"

クラスを使用してテキストメッセージを送信するこの単純なシナリオを示しました。 次のセクションでは、OOPアプローチに従ってアプリケーションの機能を拡張する方法を確認し、スケールアップしながら、OOP機能がその役割を果たす場所とこの手法を使用する利点を調べます。

OOPアプローチによるアプリケーションの拡張

以前の手順と同様に、メールを送信する機能も追加しましょう。

デバイスに関係なく、理想的には、 say_hi()関数を同じように使用する必要があります。 以下のコードを見てください:

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

このコードを使用する場合、SMSを送信するためにモバイルデバイスを取得し、電子メールを送信するためにコンピューターを取得します。 私たちは次のいずれかを行います:

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

また:

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

You sent a "Hello John" SMS to John DoeYou sent a "Hello John" email to John Doeに送信しました。

ここで、すでにいくつかのOOP機能の検出を開始しています。 MessagingCapableインターフェースを使用してインターフェースを導入しました。

インターフェイスは、これらのメソッドの実装方法を定義せずに、クラスで実装する必要のある一連のメソッドを宣言します。 インターフェイスで宣言されたすべてのメソッドはパブリックである必要があります。

PHPは多重継承をサポートしていません。つまり、クラスは複数の親クラスのプロパティ/メソッドを継承できません。

1つのクラスしか拡張できませんが、複数のインターフェースを実装できます。

電話を使用してメッセージを送信することは、コンピューターを使用することとは異なります。 異なるクラスのインスタンスは、同じアクション(つまり、 send_message() )を実行するように要求されたときに異なる動作をします。 これはポリモーフィズムの例です。 後で新しいデバイスを作成する場合、それらがすべて同じインターフェイスを共有している限り、それに対応するためにコードを変更する必要はありません。

また、読みやすさにも違いが見られることをここで指摘したいと思います。 コーディングするだけで最終的にこのスクリプトを使用する方法:

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

これは、プロジェクトに取り組む開発者にとっては完全に簡単です。 そしてもちろん、プラグインが複雑になるほど、特にチームで作業する場合に、これがどれほど役立つかが明らかになります。

オブジェクト指向プログラミングでプラグインを拡張するのがいかに簡単かをよりよく説明するために、さらにいくつかの機能を追加してみましょう。

機能の追加

インターネットを閲覧する機能を追加したい場合は、この機能に応答できるデバイス(たとえば、コンピューターなど)にインターフェイスを追加するだけです。

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

このインターフェイスの実装は、次のようにコーディングされます。

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

したがって、現在のComputerクラスでは、コンピューターがメッセージを送信してインターネットを閲覧できるため、実装する追加のインターフェイスと、 visit_website( $url )メソッドを追加しました。

注:もちろん、URLへのアクセスはsay_hi()関数とはまったく関係がないため、次のような新しい関数も導入します。

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

以上です! URLにアクセスできるすべてのデバイスで、コンピューターの場合と同じようにこの機能を使用できます。 残りの機能を壊してしまう心配はありません。 これは、手続き型プログラミングと比較して、OOPを使用するときに利用できるスケーラビリティを示しています。

さらにいくつかの機能を示すために、スマートフォンデバイスを追加しましょう。 これがコード全体であり、スマートフォンクラスが追加されているため、何が起こっているのかをより正確に把握できます。

 <?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クラスは、Phone親クラスを拡張し、 InternetBrowsingCapableインターフェイスを実装します。 つまり、メッセージを送信してURLにアクセスできるということです。 ここでは、継承機能を検出します。 つまり、クラスの階層、親クラス(Phone)とサブクラス(Smartphone)があります。

したがって、Smartphoneオブジェクトは、親Phoneクラスのすべてのプロパティと動作を継承します。 このようにして、Smartphoneクラスのsend_message()で行ったように、子クラス内でメソッドを追加したり、親クラスのメソッドをオーバーライドしたりできます。 これは、出力を変更するために行いました。 このメソッドを完全に無視して、親クラスのsend_message()をそのまま使用することができます。

この優れたPHPオンラインツールにコードブロックに貼り付けることで、自分でコードを試すことができます。 コードの下で、これらのコード行のいずれかを試して、さまざまな結果を確認してください。

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

概念全体をさらによく理解するには、上記のコードのクラス図を参照してください。

上に示したように、クラス間の関係を設計するとき、子クラスに共通の要素を含めません。 さらに、左側のガイドで注意を払うことを忘れないでください。そうすれば、それらのプロパティとメソッドの関係と可視性を識別できます。

カプセル化機能の動作も確認したい場合は、上記のスクリプト例のいずれかにContactクラスを含めてみてください。 クラスは次のようになります。

 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()メソッドは、設計上、オブジェクトの作成時に自動的に呼び出されます。 これで、Contactクラスをインスタンス化すると、そのコンストラクターが呼び出され、プライベートプロパティの値が設定されます。 次に、 get_name()get_phone_number() 、およびget_email_address()パブリックメソッドである「getters」を使用して、これらの値を取得します。

カプセル化とは、データを操作するメソッドとデータをバンドルする一方で、直接アクセスを制限して、隠された実装の詳細が公開されないようにすることです。

結論

この記事が、オブジェクト指向プログラミングをより実用的な方法で理解するのに役立つことを願っています。 OOPは、明確で再利用可能にすることにより、必要に応じてアプリケーションを将来拡張しやすくするのに役立ちます。

さらに、OOPを使用するプラグインは、より高速で簡単に実行できます。 これは、クラスのすべてのオブジェクトに共通のメソッドが、宣言中に1回だけメモリを消費するためです。

カプセル化により、セキュリティも向上します。 一方、手続き型プログラミングでは、すべてのデータがグローバルであるため、どこからでもアクセスできます。

上記の結果として、コードの保守、生産性、スケーラビリティ、およびトラブルシューティングも、あなたとあなたのチームにとってはるかに簡単になります。

このシリーズの次の記事では、WordPressプラグインに適用することで、このプログラミングスタイルの動作を確認します。 具体的には、JohanEenfeldtによって作成されたLimitLogin Attemptsプラグインバージョン1.7.1のコピーを作成しますが、可能な限りオブジェクト指向のアプローチで変換します。

このプロセスでは、プラグインフローを分析し、要件を設定します。 今後は、プラグインの設計について最初に考えてみて、実装ステップでコードを記述します。 実装プロセス中に、目的の結果を得るために、必要に応じて、いくつかの「n」を実行し、再設計します。

ただし、コードのすべての部分の詳細については説明しません。 代わりに、プラグインがオブジェクト指向の方法で構築される方法を共有することに焦点を当てたいと思います。 この一連の記事を読み終えたら、独自のOOPプラグインを非常にうまく作成できると確信しています。

オブジェクト指向プログラミングシリーズのパート3を読むには、ここをクリックしてください

関連項目

  • WordPressとオブジェクト指向プログラミング–概要