2부 – WordPress와 객체 지향 프로그래밍: 실제 사례

게시 됨: 2021-07-29

WordPress 및 객체 지향 프로그래밍 개요에서 객체 지향 프로그래밍(OOP)의 이면에 있는 이론과 이를 사용할 때 예상되는 사항을 살펴보았습니다.

OOP를 사용하여 보다 구체적인 코딩 예제를 진행하기 전에 이 기사에서는 OOP에 필요한 다양한 사고 방식으로 실제 시나리오에 접근하는 방법과 객체 및 클래스를 사용하여 이를 분석하는 방법을 설명하려고 합니다.

실제 시나리오: SMS 보내기

이것은 "과거" 삶의 시나리오와 비슷합니다. 실제로 SMS는 요즘 점점 덜 사용되지만, 보시다시피 이것을 예로 사용하는 이유가 있습니다!

모바일 장치가 있고 연락처 중 한 명에게 문자 메시지를 보내려고 한다고 가정합니다. 예제를 가능한 한 단순하게 유지하면 작업 순서는 다음과 같습니다.

  1. 메시지 준비
  2. 연락처 중 하나를 선택하고 수신자로 추가
  3. 메시지 보내기

메시지를 보내기 위해 따라야 할 단계를 시각화해 보겠습니다.

작업에 대한 좀 더 자세한 설명을 추가했지만 사용자가 수행하는 작업은 기본 3단계뿐입니다. 장치 편집기에서 메시지를 준비하고 연락처에서 수신자를 선택한 다음 메시지를 보냅니다. 그리고 당신은 끝났습니다! 이제 메시지가 전송되었습니다.

이제 SMS 메시지를 보내는 애플리케이션을 코드로 나타내려면 어떤 경로를 따라가는 것이 더 나은지 분석해야 합니다. 절차적 또는 OOP 접근 방식.

절차적 접근 방식의 적용

WordPress 플러그인 개발자라면 절차적 프로그래밍 에 익숙할 것입니다.

앞에서 설명한 것처럼 절차적 프로그래밍은 하나 이상의 절차로 구성된 프로그램이 있는 명령형 프로그래밍의 한 유형입니다. 따라서 개발자는 플러그인을 데이터를 보유하는 변수 묶음과 데이터에서 작동하는 기능 으로 나눕니다.

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 개요 기사에서 설명한 것처럼 클래스는 기본적으로 objects 라고 하는 클래스의 개별 인스턴스를 만드는 데 사용하는 템플릿입니다.

개체에는 데이터와 코드가 포함됩니다. 속성 이라고 하는 정보를 저장할 수 있는 변수가 여전히 있습니다. 그리고 데이터에 대해 작동하는 절차, 즉 메소드 .

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 Doe 보냈고 그에 You sent a "Hello John" email to John Doe .

여기에서 이미 일부 OOP 기능을 감지하기 시작했습니다. MessagingCapable 인터페이스를 사용하여 인터페이스를 도입했습니다.

인터페이스는 이러한 메서드가 구현되는 방법을 정의하지 않고 클래스에서 구현해야 하는 메서드 집합을 선언합니다. 인터페이스에 선언된 모든 메서드는 공용이어야 합니다.

PHP는 다중 상속을 지원하지 않습니다. 즉, 클래스는 여러 상위 클래스의 속성/메서드를 상속할 수 없습니다.

하나의 클래스만 확장할 수 있지만 여러 인터페이스를 구현할 수 있습니다.

전화를 사용하여 메시지를 보내는 것은 컴퓨터를 사용하는 것과 다릅니다. 다른 클래스의 인스턴스는 동일한 작업을 수행하도록 요청받을 때 다르게 작동합니다(예: 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 클래스의 모든 속성과 동작을 상속합니다. 그렇게 하면 스마트폰 클래스의 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 클래스를 인스턴스화하면 해당 생성자가 호출되고 private 속성 값을 설정합니다. 그런 다음 get_name() , get_phone_number()get_email_address() 공개 메서드인 "getters"를 사용하여 이러한 값을 검색합니다.

캡슐화는 숨겨진 구현 세부 정보의 노출을 방지하는 직접 액세스를 제한하면서 데이터에서 작동하는 메서드와 데이터를 묶는 것입니다.

결론

이 기사가 보다 실용적인 방식으로 객체 지향 프로그래밍을 이해하는 데 도움이 되었기를 바랍니다. OOP는 명확하고 재사용이 가능하여 향후 필요할 경우 애플리케이션을 보다 쉽게 ​​확장할 수 있도록 도와줍니다.

또한 OOP를 사용하는 플러그인은 더 빠르고 쉽게 실행할 수 있습니다. 클래스의 모든 개체에 공통적인 메서드는 선언 중에 메모리를 한 번만 사용하기 때문입니다.

캡슐화로 인해 보안도 향상됩니다. 반면에 절차적 프로그래밍에서는 모든 데이터가 전역적이므로 어디에서나 액세스할 수 있습니다.

위의 결과로 코드 유지 관리, 생산성, 확장성 및 문제 해결도 귀하와 귀하의 팀을 위해 훨씬 쉬워졌습니다.

이 시리즈의 다음 기사에서는 이 프로그래밍 스타일을 WordPress 플러그인에 적용하여 실제로 작동하는 것을 볼 것입니다. 특히, 우리는 Johan Eenfeldt에 의해 생성되었지만 가능한 한 객체 지향 접근 방식으로 변환된 Limit Login Attempts 플러그인 버전 1.7.1의 복사본을 생성할 것입니다.

이 과정에서 플러그인 흐름을 분석하고 요구 사항을 설정합니다. 앞으로 플러그인 디자인에 대한 첫 번째 생각을 시도하고 구현 단계에서 코드를 작성합니다. 구현 프로세스 동안 원하는 결과를 얻기 위해 필요한 경우 몇 가지 백앤포워드 및 재설계를 수행합니다.

하지만 코드의 모든 부분에 대해 자세히 설명하지는 않습니다. 대신 플러그인이 객체 지향 방식으로 구축되는 방식을 공유하는 데 중점을 두고자 합니다. 이 기사 시리즈를 다 읽고 나면 자신만의 OOP 플러그인을 아주 잘 만들 수 있다고 확신합니다.

객체 지향 프로그래밍 시리즈의 3부를 읽으려면 여기를 클릭하십시오.

또한보십시오

  • WordPress 및 객체 지향 프로그래밍 – 개요