Merida Design Blog

Publicado el | Artículos / , ,

S.O.L.I.D. Principios de programación orientada a objetos: Abierto/Cerrado

Este es el segundo artículo de la serie S.O.L.I.D. Principios de la programación orientada a objetos.

El segundo principio de S.O.L.I.D. correspondiente a la O (Open/Closed Principle) establece que:

Los objetos o entidades deben estar abiertos para extenderse pero cerrados para modificarse.

Es decir, que los objetos deben ser fáciles de extender sin tener que modificar la clase misma. Veamos exactamente a que se refiere con un ejemplo.

Siempre usando el ejemplo para el cálculo de áreas del artículo anterior, veamos de nuevo la clase AreaCalculator, en especial el método sum.

    public function sum() {
    	foreach($this->shapes as $shape) {
        	if(is_a($shape, 'Square')) {
            	$area[] = pow($shape->length, 2);
        	} else if(is_a($shape, 'Circle')) {
            	$area[] = pi() * pow($shape->radius, 2);
        	}
    	}

     	return array_sum($area);
	}

Observando el código anterior, si quisiéramos que el método sum fuera capaz de sumar más tipos de formas tendríamos que agregar mas condiciones if/else y por supuesto, esto va en contra del principio Abierto/Cerrado.

Para solucionar este problema, podemos eliminar la lógica para el cálculo de las áreas de la clase AreaCalculator y colocarla en cada una de las clases de forma Square y Circle.

Las clases de formas quedarían entonces de la siguiente manera:

class Square {
    public $length;

    public function __construct($length) {
       	$this->length = $length;
    }

    public function area() {
       	return pow($this->length, 2);
    }
}
	
class Circle {
    public $radius;
		
    public function __construct($radius) {
        $this->radius = $radius;
    }
		
    public function area() {
        return pi() * por($this->radius, 2);
    }
}

Ahora modificamos el método para el cálculo de la sumatoria de la clase AreaCalculator:

class AreaCalculator {
    ...
    public function sum() {
        foreach($this->shapes as $shape) {
            $area[] = $shape->area();
        }
		
        return array_sum($area);
    }
}

Nuestra clase ahora respeta el principio de Abierto/Cerrado y es posible pasarle cualquier otro tipo de forma y obtendremos la sumatoria sin problemas. Sin embargo hay otro problema, ¿como sabemos si el objeto proporcionado a la clase AreaCalculator es realmente una forma ó si cuenta con el método para calcular su área?

Para resolver este problema debemos crear una interfaz que sea implementada por todas las formas y en ella no aseguramos que todas las formas cuenten con los métodos requeridos.

interface ShapeInterface {
    public function area();
}

Eso es todo lo que necesitamos para declarar nuestra interfaz, ahora cualquier clase que la implemente tendrá que definir un método area. Veamos como quedan nuestra clases Circle y Square.

class Circle implements ShapeInterface {
    ...
		
    public function area() {
        ...
    }
}
	
class Square implements ShapeInterface {
    ...
		
    public function area() {
        ...
    }
}

Con los cambios anteriores realizados lo que nos que por hacer es, modificar la clase AreaCalculator para que valide que todas las formas que le sean proporcionadas, sean del tipo ShapeInterface, o de lo contrario arrojamos un error.

public class AreaCalculator {
    ...
		
    public function sum() {
        foreach($this->shapes as $shape) {
            if(is_a($shape, 'ShapeInterface')) {
                $area[] = $shape->area();
                continue;
            }
				
            throw new AreaCalculatorInvalidShapeException;
        }
			
        return array_sum($area);
    }
}

 

Conclusión

Como vimos en este artículo, seguir los lineamientos de el principio Abierto/Cerrado le da a nuestros módulos una mayor escalabilidad sin tener que modificarlos con cada cambio, solo es necesario planear un poco antes de realizarlos.

En el siguiente artículo veremos el Principio de Sustitución de Liskov.



Publicaciones que pueden interesarte

    Deja un comentario

      tope
    Derechos Reservados, Merida Design 2017
    %d bloggers like this: