Una abstracción se enfoca en la visión externa de un objeto, separa el comportamiento específico de un objeto, a esta división que realiza se le conoce como la barrera de abstracción, la cuál se consigue aplicando el principio de mínimo compromiso.
.
Pero… ¿Qué es el principio de mínimo compromiso? Se refiere al proceso por el cuál la interfaz de un objeto muestra su comportamiento específico y nada más, absolutamente nada más.
(Fuente)
.
En otras palabras la abstracción se enfoca en "que hace" sin importar en "cómo lo hace".
.
Es como solo fijarse en el nombre de una función calcularHorasDelAño(), sin importar el código que hay dentro, solo nos quedamos con el nombre, que ya nos dice "que hace", y no "como lo hace".
just like that
Dependency Inversion Principle
Este principio nos ayuda a definir cómo se vinculan las diferentes clases que tienen que darle servicios a otras. Un concepto que se maneja con este principio es que existen clases con alto nivel, otras con bajo nivel.
Alto nivel → Son aquellas que tienen que ver con la lógica del negocio.
Bajo nivel → Son aquellas que ayudan a que las clases de alto nivel cumplan su objetivo.
Y de lo que se encarga este principio es de que las dependencia entre estas no sea muy fuerte.
Según C. Martin:
Los módulos de alto nivel no deben depender de los de bajo nivel, ambos deben depender de abstracción.
Las abstracciones no deben depender de los detalles, los detalles deben depender de las abstracciones.
Resumen:
Este principio nos indica que debemos reducir las dependencias de los módulos que existen en nuestra aplicación.
Otra forma de decirlo es que los módulos NO DEBEN ser los encargados de crear los objetos con los que trabajan, sino que alguien más debe de crearlos y dárselos cuando lo necesiten.
Se le hizo un poco complicado entender cada uno de los principios de SOLID pero profundizare mas y trabaje en ellos, ya que son muchos los beneficios que me pueden aportar
RetoA
Problema: No respeta el principio de responsabilidad única al tener muchos métodos que no tienen que ver con ordenar.
Solución: Dividir en 3 clases distintas.
RetoB
Problema: No cumple con el principio abierto-cerrado ya que para agregar una nueva clase además de generarla se debe módificar la clase ProjectManagment.
Solución: Implementar que la función proccess de Project Managment requiera cumplir con una interfaz.
RetoC
Problema: No cumple con el principio de susbtitución de Liskov al no realizar Dog lo mismo que su clase padre.
Solución: Quitarle a Animal el método fly, agregar una interfaz FlyerAnimal y en otra clase que asi lo requiera implementarla.
RetoD
Problema: Error al no alicar segregación de interfaz, ya que el consultor no puede realizar un método en específico.
Solución Separar en 3 Interfaces la interfaz Underling Interface para evitar posibles errores y al momento de construir ver si es del tipo de interfaz compuesto.
RetoE
Problema: No respeta el principio de Inversión de dependencias al no recibir un Interfaz sino un tipo de clase en concreto en el constructor.
Solución: Cambiar el constructor para que reciba una interfaz de IManzano y que la clase Manzano la implemente.
Muchas gracias, me fui guiando con tu feedback y me ayudó a identificar mis falencias más que todo en e Dependency Inversion Principle.
@codemikel Hola, también te recomiendo ver estos 2 videos:
Principios SOLID
Inyección de dependencias
Para el primer reto utilicé el principio Open/Close. De este modo podrémos agregar nuevos tipos de "objetos" de nuevas clases que vayamos implementando en el futuro.
<?php
classProgrammer{publicfunctioncode(){return'coding';}publicfunctionprocess(){code();}}classTester{publicfunctiontest(){return'testing';}publicfunctionprocess(){test();}}classProjectManagement{publicfunctionprocess(array $members){foreach($members as $member){ $member->process();}}}?>```
Comparto 4/5 retos que pude identificar y brindar una solución. (Se vale retroalimentación de ustedes).
<?php
//Segregacion del interface
interface UnderlingInterface
{
public function collate();
}
interfaceconsultantgInterface{publicfunctionprogram();publicfunctionfiletps();}classUnderlingimplementsUnderlingInterface, consultantgInterface
{publicfunctionprogram(){return'Program initech systems to deposit fractions of pennies to private account';}publicfunctionfiletps(){return'Place cover sheet on TPS report before going out';}publicfunctioncollate(){return'Collect and combine texts, information, and figures in proper order.';}}classConsultantimplementsconsultantgInterface{publicfunctionprogram(){return'Outsource task to India';}publicfunctionfiletps(){return'Place cover sheet on TPS report before going out';}}classLumbergh{protected $underling;publicfunction__construct(UnderlingInterface $underling){ $this->underling = $underling;}publicfunctionharass(){ $this->underling->program(); $this->underling->filetps(); $this->underling->collate();}}```
Los pinguinos y las gallinas no están de acuerdo con tu solución para el reto 4c 😂😂
Este si la verdad no lo entendí, porque con el ejemplo que pone, si se abre una nueva forma de enviar mensajes, igual se va a tener que modificar el constructor
Estoy con la misma duda. Yo no soy muy entendido en PHP pero creo que está haciendo exactamente lo mismo.
Me explico... si paso la clase mediante inyección de dependencia en el contrsuctor y le doy valor a la propiedad, es practicamente lo mismo que hacer la instancia y darle valor a la propiedad.
Seguramente hay algo que yo no estoy entendiendo.
¿Alguien tiene claro cómo funciona la inyección de dependencia?
Pero te recomiendo más el de PHP ya que ese sí profundiza en los conceptos de POO
Una vez más llegó tarde, el crack RetaxMaster siempre me gana a contestar jaja lo que el dijo x2
De nuevo el instructor no termina de aplicar la solución al problema.
El principio de inversión de dependencia nos ayuda a definir como se vinculan las diferentes clases que tienen que darle servicio a otras.
.
Un concepto importante que se deduce de este principio es que existen clases de alto nivel y clases de bajo nivel.
Reto4d
No lo tengo claro, pero era para hacerlo diferente a otro compañero
<?phpinterfaceCollateInterface{publicfunctioncollate();}interfaceUnderlingInterface{publicfunctionprogram();publicfunctionfiletps();}classUnderlingimplementsUnderlingInterface, CollateInterface
{publicfunctionprogram(){return'Program initech systems to deposit fractions of pennies to private account';}publicfunctionfiletps(){return'Place cover sheet on TPS report before going out';}publicfunctioncollate(){return'Collect and combine texts, information, and figures in proper order.';}publicfunctionprocess(){$this->program();$this->filetps();$this->collate();}}classConsultantimplementsUnderlingInterface{publicfunctionprogram(){return'Outsource task to India';}publicfunctionfiletps(){return'Place cover sheet on TPS report before going out';}publicfunctionprocess(){$this->program();$this->filetps();}}classLumbergh{protected$underling;publicfunction__construct(UnderlingInterface$underling){$this->underling=$underling;}publicfunctionharass(){$this->underling->process();}}
Este lo implementé asi
/****** Interface Segregation Principle *****/interfaceUnderlingInterface{publicfunctionprogram();publicfunctionfiletps();}interfaceCollateable{publicfunctioncollate();}classUnderlingimplementsUnderlingInterface,Collateable{publicfunctionprogram(){return'Program initech systems to deposit fractions of pennies to private account';}publicfunctionfiletps(){return'Place cover sheet on TPS report before going out';}publicfunctioncollate(){return'Collect and combine texts, information, and figures in proper order.';}}classConsultantimplementsUnderlingInterface{publicfunctionprogram(){return'Outsource task to India';}publicfunctionfiletps(){return'Place cover sheet on TPS report before going out';}}classLumbergh{protected $underling;publicfunction__construct(UnderlingInterface $underling){ $this->underling = $underling;}publicfunctionharass(){ $this->underling->program(); $this->underling->filetps(); $this->underling->collate();}}```
Reto C:
Problema:
Rompemos el principio L.
Solución:
Dogs are Animals but dogs can’t fly. Podemos armar una jerarquía de herencia con animales que sí pueden volar y animales que no pueden volar.
Otra solución consiste en implementar interfaces, por ejemplo Flyable y Runnable.
Reto D:
Problema:
Rompe el principio de segregación de interfaces (I) dado que la clase Consultant está obligada a implementar el método collate() el cual no necesita.
Solución:
Mover la definición del método collate de la interfaz UnderlingInterface a una nueva interfaz, por ejemplo, CollateInterface. Luego hacer que la clase Consultant implemente sólo UnderlingInterface y que la clase Underling implemente ambas interfaces. La clase Lumbergh queda igual.
interfaceUnderlingInterface{publicfunctionprogram();publicfunctionfiletps();}interfaceCollateInterface{publicfunctioncollate();}classUnderlingimplementsUnderlingInterface,CollateInterface{publicfunctionprogram(){return'Program initech systems to deposit fractions of pennies to private account';}publicfunctionfiletps(){return'Place cover sheet on TPS report before going out';}publicfunctioncollate(){return'Collect and combine texts, information, and figures in proper order.';}}classConsultantimplementsUnderlingInterface{publicfunctionprogram(){return'Outsource task to India';}publicfunctionfiletps(){return'Place cover sheet on TPS report before going out';}}
Reto E:
Problema:
Rompe el principio D.
Solución:
El módulo ContadorDeManzanas debería delegar la tarea de contar manzanas a la clase Manzano.
resumen patatero, la inversion de dependencias , propone el uso de relaciones de composicion, es decir que un objeto este compuesto por otros objetos, pero que los elementos que lo componen no sea construidos en el objeto principal, en su lugar se deben recibir como parametros, para mas facilidad pensarlo como una fabrica de ensamblado que recibe piezas y con las piezas arma algo nuevo y mucho mas funcional
Hola Jaime, muy buen aporte, me ayudo a entender más este principio.
Muy interesante el planteamiento que menciona que los parametros del constructor no deben ser clases si no interfaces. Efectivamente es la forma correcta de hacerlo.
Este código no cumple con el principio de inyección de dependencias
Al implementarlas como interfaces permitiría incluir tipos de servidores de correos como hotmail, gmail etc., además de incluir los mensajes de facebook, whatsapp, telegram, etc.,
interfaceEmailSender{ fun sendEmail(message :String)}classHotmail:EmailSender{ overrider fun sendEmail(message :String)}classGmail:EmailSender{ overrider fun sendEmail(message :String)}
interfaceMessageSender{ fun sendMessage(message :String)}classWhatsApp:MessageSender{ override fun sendMessage(message :String)}classTelegram:MessageSender{ override fun sendMessage(message :String)}```
Donde esta el ejemplo del código que hizo?
En los archivos están los códigos de las clases :)
Sección "Archivos y Enlaces" :)
¡Saludos!
Me tranqué con algo...
Me explico... si paso la clase mediante inyección de dependencia en el contrsuctor y le doy valor a la propiedad, es practicamente lo mismo que hacer la instancia y darle valor a la propiedad.
¿Alguien tiene claro cómo funciona la inyección de dependencia?
Hola Mauricio de ahí lo importante que la dependencia que estás inyectando sea una interfaz, te pongo un ejemplo si en el código de la clase yo tuviera una clase para enviar correos por gmail y otra para enviar correos con hotmail estos deberían implementar una interface iEmailSender que sería la que le paso al constructor, con esto no tendría que modificar mi constructor ya que para él es indiferente que clase le estoy pasando pero si deben implementar la interface que espera.
Espero que me hayas entendido :)
Dejame explicarte lo que entendí:
Lo que entendí de Inyección de dependencia es que le paso al contructor un objeto ya instanciado a la clase. Quitando la responsabilidad de hacer la instancia a la clase que se le inyecta la dependencia. Con el fin de reducir acoplamiento. ¿Tenemos la misma definición?
Lo positivo de eso es que si se cambia la manera de instanciar el objeto a la clase la cual lo inyecta no le afecta porque ya le viene instanciado.
Sobre tu respuesta
Si yo inyecto cualquier clase que implemente esa interfáz me queda clarísimo que esas funcionalidades van a estar presentes ya que las define la interfáz.
Lo otro que quizás no esté comprendiendo es la posibilidad de que en el constructor se inyecte directamente la interfas (literalmente) y no una clase que implemente esa interfás. De ser así ¿Cómo la interfáz sabría cuáles son las clases que la implementan?