Parte 2 – WordPress y Programación Orientada a Objetos: Un Ejemplo del Mundo Real

Publicado: 2021-07-29

En nuestra Descripción general de WordPress y la programación orientada a objetos, analizamos la teoría detrás de la programación orientada a objetos (POO) y qué esperar al usarla.

Antes de continuar con ejemplos de codificación más específicos usando OOP, en este artículo intentaremos explicar cómo se puede abordar un escenario del mundo real con la mentalidad diferente requerida para OOP y cómo se analiza esto usando objetos y clases.

Un escenario de la vida real: enviar un SMS

Esto es más como un escenario de vida "pasada" en realidad, ya que los SMS se usan cada vez menos hoy en día, pero como verá, ¡hay una razón por la que usamos esto como ejemplo!

Suponga que tiene un dispositivo móvil y desea enviar un mensaje de texto a uno de sus contactos. Manteniendo el ejemplo lo más simple posible, la secuencia de acciones sería:

  1. Prepara el mensaje
  2. Seleccione uno de sus contactos y agréguelo como destinatario
  3. Envía el mensaje

Así que intentemos visualizar los pasos que seguirías para enviar tu mensaje:

Agregamos algunas descripciones más detalladas de las acciones, pero más o menos todo lo que haces son 3 pasos básicos. Preparas el mensaje en el editor de dispositivos, seleccionas el destinatario de tus contactos y luego envías el mensaje. ¡Y listo! Su mensaje ya está enviado.

Ahora bien, si tuviéramos que representar en código una aplicación que envía un mensaje SMS deberíamos analizar qué ruta es mejor seguir; el enfoque procedimental o OOP.

La Solicitud con Enfoque Procesal

Si es un desarrollador de complementos de WordPress, lo más probable es que esté familiarizado con la programación de procedimientos .

Como describimos anteriormente, la programación procedimental es un tipo de programación imperativa, donde nuestros programas consisten en uno o más procedimientos. Entonces, como desarrollador, divide su complemento en un conjunto de variables que contienen sus datos y funciones que operan en los datos.

En nuestro ejemplo anterior con el mensaje SMS, realizaría una serie de acciones que conducirían al resultado deseado. Como ya habrás adivinado, tendrías, por ejemplo, una variable que contiene el contenido de texto del mensaje, una función con un parámetro $contact que devuelve el número de teléfono y, por último, una función que envía el mensaje. En código se vería así:

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

Y lo usarías así:

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

Entonces, completarías una serie de tareas que te llevarán al resultado deseado.

En este ejemplo muy simple, por supuesto, que tiene requisitos limitados y muy específicos, no hay ninguna razón para considerar el uso de programación orientada a objetos. La programación procedimental es más que suficiente para lograr su objetivo. Pero, si piensa en algunos escenarios sobre cómo esta aplicación podría expandirse en el futuro, podría darse cuenta de que, a la larga, podría tener problemas en términos de escalabilidad. Intentaremos explicar por qué a continuación.

Expansión de la aplicación con enfoque procesal

Supongamos que desea mejorar esta aplicación y brindar la capacidad de enviar otros tipos de mensajes también, como un correo electrónico, por ejemplo. La función que entrega el mensaje sería diferente en cada caso.

Al enviar un correo electrónico, necesita la dirección de correo electrónico del contacto, no el número de teléfono. Aparte de esto, necesitaremos agregar un parámetro en la función final send_message() que corresponderá al tipo de tecnología que usamos; correo electrónico o SMS.

El código correspondiente podría verse así:

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

Entonces, no es que esto no pueda implementarse con un enfoque procedimental. Pero si es un desarrollador experimentado, probablemente ya haya entendido cómo esto podría complicarse en el futuro.

Los inconvenientes con un enfoque procedimental

¿Qué pasaría si tuviéramos múltiples tipos de mensajes? Las declaraciones if se volverían molestamente grandes. Y, lo más importante, ¿qué pasaría si tuviera funciones que usan la función send_message() ? En ese caso, también deberá agregar el parámetro $technology en todas esas funciones.

A medida que su código crece, las funciones estarán por todas partes, lo que significa que comenzará a copiar/pegar fragmentos de código (nunca deseable), y hacer un pequeño cambio en una función podría romper varias otras funciones. Todos hemos estado allí. Le gustaría evitar esto y poder agregar funciones fácilmente a su código sin interferir demasiado en la estructura.

Aloje su sitio web con Pressidium

GARANTÍA DE DEVOLUCIÓN DE DINERO DE 60 DÍAS

VER NUESTROS PLANES

La programación orientada a objetos (o POO) es un paradigma de programación que intenta resolver este problema permitiéndonos estructurar nuestro complemento en pequeñas piezas de código reutilizables, llamadas clases . Como describimos en nuestro artículo de descripción general de OOP, una clase es básicamente una plantilla que usamos para crear instancias individuales de la clase, llamadas objetos .

Un objeto contiene datos y código. Todavía tenemos variables que pueden almacenar información, llamadas propiedades . Y los procedimientos que operan sobre los datos, llamados métodos .

La aplicación con un enfoque OOP

Ahora analicemos el mismo escenario que el anterior con un enfoque OOP.

Primero, definiremos qué objetos tenemos aquí, qué características tiene cada uno y qué acciones realizan. Las características son lo que luego serán nuestras propiedades y las acciones serán nuestras funciones o métodos como se les llama en POO.

Pensemos en lo que tenemos en el primer escenario de enviar un SMS de la forma más sencilla posible. Hay un dispositivo que tiene una interfaz que usamos para enviar el mensaje SMS. Tenemos el contenido del mensaje, elegimos un contacto como destinatario y finalmente el mensaje.

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

Declaramos la clase Phone que implementa la interfaz MessagingCapable . Entonces tenemos que implementar todos los métodos declarados en él. La función say_hi() requiere 3 parámetros:

  1. Un dispositivo que admita mensajería.
  2. Un contacto
  3. El mensaje

Para enviar un mensaje, usamos esta función de esta manera:

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

Básicamente estamos creando un objeto instanciando la clase Phone y pasando el contacto y el contenido del mensaje. Esto daría como resultado:

 You sent "Hello John"

Demostramos este escenario simple de enviar un mensaje de texto usando clases. En la siguiente sección, veremos cómo podemos expandir las capacidades de la aplicación siguiendo el enfoque de programación orientada a objetos y, mientras se amplía, examinaremos dónde desempeñan su función las funciones de programación orientada a objetos, así como los beneficios de usar esta técnica.

Expansión de la aplicación con el enfoque OOP

Agreguemos también la capacidad de enviar correos electrónicos, como lo hicimos antes en el procedimiento.

Independientemente del dispositivo, lo ideal sería utilizar la función say_hi() de la misma manera. Eche un vistazo al código a continuació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 ); }

Cuando usamos este fragmento de código, tomaríamos el dispositivo móvil para enviar un SMS y la computadora para enviar un correo electrónico. O bien:

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

o:

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

eso daría como resultado You sent a "Hello John" SMS to John Doe y You sent a "Hello John" email to John Doe correspondientemente.

Aquí ya empezamos a detectar algunas características OOP. Presentamos interfaces usando la interfaz MessagingCapable .

Una interfaz declara un conjunto de métodos que la clase debe implementar sin definir cómo se implementan estos métodos. Todos los métodos declarados en una interfaz deben ser públicos.

PHP no admite la herencia múltiple, lo que significa que una clase no puede heredar las propiedades/métodos de varias clases principales.

Si bien solo puede extender una clase, puede implementar múltiples interfaces.

Usar un teléfono para enviar un mensaje será diferente a usar una computadora. Las instancias de diferentes clases actúan de manera diferente cuando se les pide que realicen la misma acción (es decir send_message() ). Este es un ejemplo de polimorfismo. Si luego creamos un nuevo dispositivo, no necesitaremos modificar nuestro código para acomodarlo, siempre y cuando todos compartan la misma interfaz.

También nos gustaría señalar aquí que ya vemos la diferencia en la legibilidad también. La forma en que finalmente usamos este script simplemente codificando:

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

Esto es totalmente sencillo para cualquier desarrollador que trabaje en el proyecto. Y, por supuesto, cuanto más complejo es el complemento, se vuelve más obvio lo útil que es, especialmente cuando se trabaja en equipo.

Para tratar de explicar mejor lo fácil que es expandir su complemento en la programación orientada a objetos, intentemos agregar algunas funciones más.

Agregar más funcionalidad

Si queremos agregar la capacidad de navegar por Internet, solo agregaríamos una interfaz adicional para cualquier dispositivo que pueda responder a esta capacidad, como una computadora, por ejemplo.

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

La implementación de esta interfaz se codificará así:

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

Entonces, en la clase de Computadora actual, acabamos de agregar la interfaz adicional que se implementará, ya que una computadora puede enviar un mensaje y navegar por Internet, y el visit_website( $url ) .

NOTA: Por supuesto, dado que visitar una URL es totalmente irrelevante con la función say_hi() , también presentaremos una nueva función, algo como:

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

¡Y eso es! Para cualquier dispositivo que pueda visitar una URL, podemos usar esta función como lo hicimos con la computadora. No hay preocupaciones de que romperá el resto de la funcionalidad. Esto muestra la escalabilidad disponible cuando se usa OOP en comparación con la programación procedimental.

Agreguemos un dispositivo de teléfono inteligente solo para demostrar algunas características más. Aquí está el código completo, con la adición de la clase de teléfono inteligente para que pueda tener una mejor idea de lo que está pasando:

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

La clase Smartphone amplía la clase padre Teléfono e implementa la interfaz InternetBrowsingCapable . Eso significa que puede enviar un mensaje y visitar una URL. Aquí, detectamos la función de herencia. En otras palabras, tenemos una jerarquía de clases, una clase principal (teléfono) y una subclase (teléfono inteligente).

Entonces, un objeto Smartphone hereda todas las propiedades y comportamientos de la clase Teléfono principal. De esa manera, dentro de la clase secundaria podemos agregar un método o anular un método de la clase principal, como hicimos con send_message() en la clase Smartphone. Hicimos esto para cambiar la salida. Podríamos ignorar totalmente este método y usar send_message() de la clase principal tal como está.

Puede probar el código usted mismo pegándolo en el bloque de código de esta gran herramienta PHP en línea. Debajo del código, pruebe cualquiera de estas líneas de código y vea los diferentes resultados.

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

Para una mejor comprensión de todo el concepto, eche un vistazo al diagrama de clases del código anterior.

Como se muestra arriba, al diseñar las relaciones entre clases, no incluimos los elementos comunes en la clase secundaria. Además, no olvides prestar atención en la guía de la izquierda para que puedas identificar las relaciones y la visibilidad de sus propiedades y métodos.

Si también desea ver la función de encapsulación en acción, intente incluir una clase de contacto en cualquiera de los scripts de ejemplo anteriores que proporcionamos. La clase se vería así:

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

El método __construct() , por diseño, se llama automáticamente al crear un objeto. Ahora, cuando creamos una instancia de la clase Contact, se llama a su constructor y establece los valores de sus propiedades privadas. Luego usamos nuestros "captadores" que son los métodos públicos get_name() , get_phone_number() y get_email_address() para recuperar estos valores.

La encapsulación está agrupando los datos con los métodos que operan en los datos mientras restringe el acceso directo para evitar la exposición de los detalles de implementación ocultos.

Conclusión

Esperamos que este artículo te haya ayudado a comprender la programación orientada a objetos de una manera más práctica. OOP realmente ayuda a que sea más fácil para la aplicación expandirse en el futuro si es necesario al ser claro y reutilizable.

Además, un complemento que use programación orientada a objetos será más rápido y fácil de ejecutar. Eso es porque los métodos que son comunes para todos los objetos de una clase consumen memoria solo una vez, durante su declaración.

La seguridad también se mejora debido a la encapsulación. En la programación de procedimientos, por otro lado, todos los datos son globales, lo que significa que el acceso está disponible desde cualquier lugar.

Como resultado de lo anterior, el mantenimiento del código, la productividad, la escalabilidad y la resolución de problemas también se vuelven mucho más fáciles para usted y su equipo.

En los próximos artículos de esta serie, veremos este estilo de programación en acción aplicándolo a un complemento de WordPress. Específicamente, crearemos una copia del complemento Limitar intentos de inicio de sesión versión 1.7.1 creado por Johan Eenfeldt pero convertido con un enfoque orientado a objetos tanto como sea posible.

Durante este proceso, desglosaremos el flujo del complemento y estableceremos los requisitos. En el futuro, probaremos nuestros primeros pensamientos sobre el diseño del complemento y, en el paso de implementación, escribiremos el código. Durante el proceso de implementación, haremos algunas idas y venidas y rediseñaremos, si es necesario, para obtener los resultados deseados.

Sin embargo, no entraremos en detalles sobre todas las partes del código. En su lugar, nos gustaría centrarnos en compartir la forma en que los complementos se construyen de forma orientada a objetos. Estamos seguros de que, una vez que haya terminado de leer esta serie de artículos, podrá crear su propio complemento OOP.

Haga clic aquí para leer la Parte 3 de nuestra Serie de Programación Orientada a Objetos

Ver también

  • WordPress y la programación orientada a objetos: una descripción general