No tienes acceso a esta clase

隆Contin煤a aprendiendo! 脷nete y comienza a potenciar tu carrera

Aprende todo un fin de semana sin pagar una suscripci贸n 馃敟

Aprende todo un fin de semana sin pagar una suscripci贸n 馃敟

Reg铆strate

Comienza en:

0D
14H
38M
27S

Dependency Inversion Principle

15/26
Recursos

Dependency Inversion Principle detalla que los m贸dulos de alto nivel no deben depender de los de bajo nivel, ambos deben depender de abstracciones.

Las abstracciones no deben depender de los detalles, los detalles deben depender de las abstracciones.

Aportes 98

Preguntas 11

Ordenar por:

驴Quieres ver m谩s aportes, preguntas y respuestas de la comunidad?

o inicia sesi贸n.

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 鈥渜ue hace鈥 sin importar en 鈥渃贸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 鈥渜ue hace鈥, y no "como lo hace".

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.

Para el primer reto utilic茅 el principio Open/Close. De este modo podr茅mos agregar nuevos tipos de 鈥渙bjetos鈥 de nuevas clases que vayamos implementando en el futuro.

<?php

    class Programmer {
        public function code() {
            return 'coding';
        }
        
        public function process() {
            code();
        }
    }
    
    class Tester {
        public function test() {
            return 'testing';
        }
        
        public function process() {
            test();
        }
    }
    
    class ProjectManagement {
        public function process(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).

Reto4

<?php
//Single responsibility

    class OrderTotal{
        public function calculateTotalSum(){/*...*/}
    }

    class OrderItemsGet{
        public function getItems(){/*...*/}
        public function getItemCount(){/*...*/}
    }

    class OrderItemsAction{
        public function addItem($item){/*...*/}
        public function deleteItem($item){/*...*/}
    }

    class Orderprint{
        public function printOrder(){/*...*/}
    }

    class OrderShow{
        public function showOrder(){/*...*/}
    }

    class OrderAction{
        public function load(){/*...*/}
        public function save(){/*...*/}
        public function update(){/*...*/}
        public function delete(){/*...*/}
    }

Reto4b

<?php
//Open & Close
    interface profile{
        public function process();
    }
    
    class Programmer implements profile
    {

        public function process(profiles $member)
        {
            return 'coding';
        }
    }
    class Tester implements profile
    {
        public function process(profile $member)
        {
            return 'testing';
        }
    }
    

Reto4c

<?php
//Liskov substitution
    interface fly{
        public function fly();
    }

    class Animal{
        
    }
    class AnimalhasWings extends Animal implements fly{
        public function fly()
        {
        }
    }
    class Dog extends Animal{
       
    }```

**Reto4d**



<?php
//Segregacion del interface
interface UnderlingInterface
{
public function collate();
}

   interface consultantgInterface
{
    public function program();

    public function filetps();
}


class Underling implements UnderlingInterface, consultantgInterface
{
    public function program()
    {
        return 'Program initech systems to deposit fractions of pennies to private account';
    }

    public function filetps()
    {
        return 'Place cover sheet on TPS report before going out';
    }

    public function collate()
    {
        return 'Collect and combine texts, information, and figures in proper order.';
    }
}

class Consultant implements consultantgInterface
{
    public function program()
    {
        return 'Outsource task to India';
    }

    public function filetps()
    {
        return 'Place cover sheet on TPS report before going out';
    }

}

class Lumbergh
{
    protected $underling;

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

    public function harass()
    {
        $this->underling->program();
        $this->underling->filetps();
        $this->underling->collate();
    }
}```

Segundo reto, apliqu茅 el princpio de responsabilidad 煤nica:

class Item {

      public function calculateTotalSum(){/*...*/}
      public function getItems(){/*...*/}
      public function getItemCount(){/*...*/}
      public function addItem($item){/*...*/}
      public function deleteItem($item){/*...*/}

}

class DataBase() {

      public function load(){/*...*/}
      public function save(){/*...*/}
      public function update(){/*...*/}
      public function delete(){/*...*/}

}

class Order {
        
      public function printOrder(){/*...*/}
      public function showOrder(){/*...*/}

}

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

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

<?php
    interface CollateInterface
    {
      public function collate();
    }

    interface UnderlingInterface
    {
        public function program();

        public function filetps();

    }

    class Underling implements UnderlingInterface, CollateInterface
    {
        public function program()
        {
            return 'Program initech systems to deposit fractions of pennies to private account';
        }

        public function filetps()
        {
            return 'Place cover sheet on TPS report before going out';
        }

        public function collate()
        {
            return 'Collect and combine texts, information, and figures in proper order.';
        }

        public function process()
        {
          $this->program();
          $this->filetps();
          $this->collate();
        }
    }

    class Consultant implements UnderlingInterface
    {
        public function program()
        {
            return 'Outsource task to India';
        }

        public function filetps()
        {
            return 'Place cover sheet on TPS report before going out';
        }

        public function process()
        {
          $this->program();
          $this->filetps();
        }
    }

    class Lumbergh
    {
        protected $underling;

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

        public function harass()
        {
            $this->underling->process();
        }
    }

    interface Workable{
        public function process();
    }

    class Programmer implements Workable
    {
        public function process()
        {
            return 'coding';
        }
    }
    class Tester implements Workable
    {
        public function process()
        {
            return 'testing';
        }

    }
    class ProjectManagement
    {
        public function process(Workable $member)
        {
            $member->process(); 
        }
    }

RETOS
Reto A:
Problema:
Rompe el principio S.
Soluci贸n:
Divido la clase Order obteniendo lo siguiente:

    class Order {
        public function calculateTotalSum(){/*...*/}
        public function getItems(){/*...*/}
        public function getItemCount(){/*...*/}
        public function addItem($item){/*...*/}
        public function deleteItem($item){/*...*/}
    }

    class ViewOrder {
        public function printOrder(){/*...*/}
        public function showOrder(){/*...*/}
    }

    class OrderService {
        public function load(){/*...*/}
        public function save(){/*...*/}
        public function update(){/*...*/}
        public function delete(){/*...*/}
    }

Reto B:
Problema:
Rompe el principio O.
Soluci贸n:
Utilizamos abstracci贸n para hacer extensible la clase Programmer.

     class ProjectManagement {
        public function process($member) {
                $member->process();
        }
    }

Reto C:
Problema:
Rompemos el principio L.
Soluci贸n:
Dogs are Animals but dogs can鈥檛 fly. Podemos armar una jerarqu铆a de herencia con animales que s铆 pueden volar y animales que no pueden volar.

   class Animal {
    }
   class AnimalFly extends Animal {
        public function fly() {}
    }
   class AnimalNotFly extends Animal {
        public function watchTV() {}
    }

    class Dog extends AnimalNotFly {
        public function watchTV() {}
    }
    class Bird extends AnimalFly {
        public function fly() {}
    }

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.

    interface UnderlingInterface {
        public function program();
        public function filetps();
    }

    interface CollateInterface {
        public function collate();
    }

    class Underling implements UnderlingInterface, CollateInterface {
        public function program() {
            return 'Program initech systems to deposit fractions of pennies to private account';
        }
        public function filetps() {
            return 'Place cover sheet on TPS report before going out';
        }
        public function collate() {
            return 'Collect and combine texts, information, and figures in proper order.';
        }
    }

    class Consultant implements UnderlingInterface {
        public function program() {
            return 'Outsource task to India';
        }
        public function filetps() {
            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.

    class Manzano {
        private $manzanas = [];
        public function getManzanas() {
            return $this->manzanas;
        }
        public function cuentas() {
            return count($this->manzano->getManzanas());
        }
    }

    class ContadorDeManzanas {
        private $manzano;
        public function __contsruct(Manzano $manzano) {
            $this->manzano = $manzano;
        }
        public function cuantas() {
            return $this->manzano->cuentas();
        }
    }

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

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

class Notifier {
    lateinit var emailSender : EmailSender
    lateinit var messageSender: MessageSender
   constructor(){
    emailSender = EmailSender()
    messageSender = MessageSender()
  }   
}

Un punto importante es que EmailSender, MessageSender no deben de ser clases sino interfaces.

class Notifier {
  constructor(emailSender : EmailSender, messageSender: MessageSender) {
    this.emailSender = emailSender
    this.messageSender = MessageSender
  }
}

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.,

interface EmailSender {
  fun sendEmail(message : String)
}

class Hotmail : EmailSender {
  overrider fun sendEmail(message : String)
}

class Gmail : EmailSender {
  overrider fun sendEmail(message : String)
}
interface MessageSender{
 fun sendMessage(message : String)
}

class WhatsApp : MessageSender{
  override fun sendMessage(message : String)
}
class Telegram : MessageSender{
  override fun sendMessage(message : String)
}```

Reto E: No respeta el principio de Inversi贸n de Dependencias al no recibir un Interfaz sino un tipo de clase en concreto en el constructor. Puede abstraerse el contador de manzanos para cualquier otro fruto. El contador de frutos es un m贸dulo de alto nivel que no depende de los detalles.

interface IProduccion
  {
      public function get()
  }

  class Manzano implements IProduccion
  {
      private $manzanas = [];

      public function get()
      {
          return $this->manzanas;
      }
  }

  class ContadorDeFrutas
  {
      public function __construct(IProduccion $arbol)
      {
          $this->arbol = $arbol;
      }

      public function cuantas()
      {
          return count($this->arbol->get());
      }
  }
 interface FlyingAnimal
    {
        public function fly();
    }

    class Animal implements FlyingAnimal
    {
        public function __construct( bool $hasWings ){
            $this->hasWings = $hasWings;
        }
    }

    class Dog extends Animal
    {
        public function fly()
        {
            if (! $this->hasWings) {
                throw new Exception;
            }
        }
    }

Si no estoy mal en este principio se aplica la 鈥淚nyeccion de Dependencias鈥

De nuevo el instructor no termina de aplicar la soluci贸n al problema.

En el reto4d apliqu茅 el principio de Liskov donde basicamente especialic茅 las interfaces para hacerlas m谩s finas y no tener que imponerles a las clases que las implementen que tambi茅n implementen todos sus m茅todos:

<?php

    interface UnderlingInterface {
        public function program();
        public function filetps();
        public function collate();
    }
    
    interface ConsultantInterface {
        public function program();
        public function filetps();
    }

    class Underling implements UnderlingInterface {
        public function program() {
            return 'Program initech systems to deposit fractions of pennies to private account';
        }

        public function filetps() {
            return 'Place cover sheet on TPS report before going out';
        }

    }

    class Consultant implements ConsultantInterface {
        public function program() {
            return 'Outsource task to India';
        }

        public function filetps() {
            return 'Place cover sheet on TPS report before going out';
        }

    }

?>```

Reto4b

<?php
    interface Workable
    {
      public function process();
    }

    class Programmer implements Workable
    {
        public function code()
        {
            return 'coding';
        }

        public function process()
        {
          $this->code();
        }
    }

    class Tester implements Workable
    {
        public function test()
        {
            return 'testing';
        }

        public function process()
        {
          $this->test();
        }
        
    }

    class ProjectManagement
    {
        public function process(Workable $member)
        {
            $member->process();
        }
    }

Reto4

<?php
    class Order {
        public function printOrder(){/*...*/}
        public function showOrder(){/*...*/}
    }

    class OrderItems {
        public function calculateTotalSum(){/*...*/}
        public function getItems(){/*...*/}
        public function getItemCount(){/*...*/}
        public function addItem($item){/*...*/}
        public function deleteItem($item){/*...*/}
    }

    interface OrderRecord {
        public function load(){/*...*/}
        public function save(){/*...*/}
        public function update(){/*...*/}
        public function delete(){/*...*/}
    }

Se puede complementar la informacion de SOLID: https://www.youtube.com/watch?v=2X50sKeBAcQ

Reto 4e
Problema: No se cumple el Principio de Inversi贸n de Dependencias ya que el constructor recibe una clase y no una interface.

    interface ManzanoInterface
    {
        public function getManzanas();
    }

    class Manzano implements ManzanoInterfacte
    {
        private $manzanas = [];

        public function getManzanas()
        {
            return $this->manzanas;
        }
    }


    class ContadorDeManzanas
    {
        private $manzano;

        public function __contsruct(ManzanoInterfacte $manzano)
        {
            $this->manzano = $manzano;
        }

        public function cuantas()
        {
            return count($this->manzano->getManzanas());
        }
    }

Reto 4d
Problema: No se cumple el Principio de Segregaci贸n de Interfaces, pues la clase Consultant est谩 implementando el m茅todo collate() que no necesita y est谩 devolviendo siempre un valor nulo.
Soluci贸n: La propuesta ser铆a dividir la interface UnderlingInterface en dos interfaces seg煤n sus actividades y crear un m茅todo que agrupe las actividades que realiza cada uno, para que la clase Lumbergh pueda recibir la interface y llamar a este m茅todo.

    interface UnderlingInterface 
    {
        public function program();
        public function filetps();
        public function work();
    }

    interface CollateInterface 
    {
        public function collate();
    }

    class Underling implements UnderlingInterface, CollateInterface
    {
        public function program()
        {
            return 'Program initech systems to deposit fractions of pennies to private account';
        }

        public function filetps()
        {
            return 'Place cover sheet on TPS report before going out';
        }

        public function collate()
        {
            return 'Collect and combine texts, information, and figures in proper order.';
        }

        public function work()
        {
            $this->program();
            $this->filetps();
            $this->collate();
        }
    }

    class Consultant implements UnderlingInterface
    {
        public function program()
        {
            return 'Outsource task to India';
        }

        public function filetps()
        {
            return 'Place cover sheet on TPS report before going out';
        }

        public function work()
        {
            $this->program();
            $this->filetps();
        }
    }

    class Lumbergh
    {
        protected $underling;

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

        public function harass()
        {
            $this->underling->work();
        }
    }

Reto 4c
Problema: No se cumple el Principio de Sustituci贸n de Liskov pues la clase hija est谩 sobreescribiendo un m茅todo de la clase padre y altera su comportamiento pues arroja una excepci贸n diferente.
Soluci贸n: La propuesta ser铆a modificar la relaci贸n de herencia e implementar una interface para incluir el m茅todo fly(), de modo que no le imponemos a la clase Dog que implemente m茅todos que no le pertecen.

    interface Bird 
    {
        public function fly() 
        {
            return 'flying';
        };
    }

    class Animal
    {
    }

    class Dog extends Animal 
    {
    }

    class Eagle extends Animal implements Bird 
    {
    }

Reto 4b
Problema: No se cumple el Principio Abierto/Cerrado, porque si existieran m谩s roles de empleados se tendr铆a que modificar el m茅todo process() en la clase. ProjectManagement para agregar un nuevo caso.
Soluci贸n: La propuesta ser铆a crear un m茅todo process() en cada una de las clases.

    class Programmer
    {
        public function process()
        {
            return 'coding';
        }
    }

    class Tester
    {
        public function process()
        {
            return 'testing';
        }
    }

    class ProjectManagement
    {
        public function process($member)
        {
            $member->process();
        }
    }

Reto 4
Problema: No se cumple el Principio de Responsabilidad 脷nica, ya que hay una sola clase que hace muchas cosas, es un 鈥渉ombre orquesta鈥.
Soluci贸n: La propuesta ser铆a agrupar los m茅todos en nuevas clases.
Los m茅todos load, save, update y delete seguramente se podr铆an reutilizar y aplicar en otro contexto.

    class Order 
    {
        public function calculateTotalSum(){/*...*/}
    }

    class OrderItem
    {
        public function getItems(){/*...*/}
        public function getItemCount(){/*...*/}
        public function addItem($item){/*...*/}
        public function deleteItem($item){/*...*/}
    }

    class OrderPrint 
    {
        public function printOrder(){/*...*/}
    }

    class OrderShow 
    {
        public function showOrder(){/*...*/}
    }

    class DatabaseOperation 
    {
        public function load(){/*...*/}
        public function save(){/*...*/}
        public function update(){/*...*/}
        public function delete(){/*...*/}
    }
<?php

    interface employee {
        public function work();
    }

    class Programmer implements employee
    {
        public function work()
        {
            return 'coding';
        }
    }
    class Tester implements employee
    {
        public function work()
        {
            return 'testing';
        }
    }
    class ProjectManagement
    {
        public function process(employee $member)
        {
            return $member->work();
        }
    }

$manager = new ProjectManagement();
$tester = new Tester();
$programmer = new Programmer();

echo $manager->process($tester);
echo $manager->process($programmer);

<?php
    class Animal
    {
        public function fly()
        {
        }
    }

    class Canine
    {
        public function bark()
        {
            //
        }
    }

    class Dog extends Canine
    {
        public function bark()
        {
        return "Gruauf!";
        }
    }
<?php
class Order
{
    public function printOrder()
    { /*...*/
    }
    public function showOrder()
    { /*...*/
    }
}

class Calculations
{
    public function calculateTotalSum()
    { /*...*/
    }
}

class ManageCalculations
{
    public function load()
    { /*...*/
    }
    public function save()
    { /*...*/
    }
    public function update()
    { /*...*/
    }
    public function delete()
    { /*...*/
    }
}

class Items
{

    public function getItems()
    { /*...*/
    }
    public function getItemCount()
    { /*...*/
    }
    public function addItem($item)
    { /*...*/
    }
    public function deleteItem($item)
    { /*...*/
    }
}
<?php

    interface UnderlingInterface
    {
        public function program();

        public function filetps();

        public function collate();
    }

    interface ConsultantInterface
    {
        public function program();

        public function filetps();
    }

    class Underling implements UnderlingInterface
    {
        public function program()
        {
            return 'Program initech systems to deposit fractions of pennies to private account';
        }

        public function filetps()
        {
            return 'Place cover sheet on TPS report before going out';
        }

        public function collate()
        {
            return 'Collect and combine texts, information, and figures in proper order.';
        }
    }

    class Consultant implements ConsultantInterface
    {
        public function program()
        {
            return 'Outsource task to India';
        }

        public function filetps()
        {
            return 'Place cover sheet on TPS report before going out';
        }
    }

    class Lumbergh
    {
        protected $underling;

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

        public function harass()
        {
            $this->underling->program();
            $this->underling->filetps();
            $this->underling->collate();
        }
    }

reto4.php

<?php

    class Item {
        public function calculateTotalSum(){/*...*/}
        public function getItems(){/*...*/}
        public function getItemCount(){/*...*/}
        public function addItem($item){/*...*/}
        public function deleteItem($item){/*...*/}
    }

    class Order {
        public function printOrder(){/*...*/}
        public function showOrder(){/*...*/}
    }

    class Database {
        public function load(){/*...*/}
        public function save(){/*...*/}
        public function update(){/*...*/}
        public function delete(){/*...*/}
    }

reto4b.php

<?php
    interface Codeable {
        public function code();
    }

    interface Testable {
        public function test();
    }

    class Programmer implements Codeable
    {
        public function code()
        {
            return 'coding';
        }
    }
    
    class Tester implements Testable
    {
        public function test()
        {
            return 'testing';
        }
    }

    class ProjectManagement
    {
        public function process($member)
        {
            if ($member instanceof Codeable) {
                $member->code();
            } elseif ($member instanceof Testable) {
                $member->test();
            };
            throw new Exception('Invalid input member');
        }
    }

reto4c.php

<?php
    class Animal {
        // ...
    }
    
    class FlyingAnimal extends Animal
    {
        public function fly()
        {
        }
    }

    class Dog extends Animal
    {
        public function fly()
        {
            if (! $this->hasWings) {
                throw new Exception;
            }
        }
    }

reto4d.php

<?php

    interface BaseInterface {
        public function program();
        public function filetps();
    }

    interface UnderlingInterface {
        public function collate();
    }

    class Base {
        public function filetps()
        {
            return 'Place cover sheet on TPS report before going out';
        }
    }

    class Underling extends Base implements BaseInterface, UnderlingInterface
    {
        public function program()
        {
            return 'Program initech systems to deposit fractions of pennies to private account';
        }
        
        public function collate()
        {
            return 'Collect and combine texts, information, and figures in proper order.';
        }
    }

    class Consultant extends Base implements BaseInterface
    {
        public function program()
        {
            return 'Outsource task to India';
        }
    }

    class Lumbergh
    {
        protected $underling;

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

        public function harass()
        {
            $this->underling->program();
            $this->underling->filetps();
            $this->underling->collate();
        }
    }

reto4e.php

<?php
    interface ManzanoInterface {
        public function getManzanas();
    }

    class Manzano implements ManzanoInterface
    {
        private $manzanas = [];

        public function getManzanas()
        {
            return $this->manzanas;
        }
    }

    class ContadorDeManzanas
    {
        private $manzano;

        public function __contsruct(ManzanoInterface $manzano)
        {
            $this->manzano = $manzano;
        }

        public function cuantas()
        {
            return count($this->manzano->getManzanas());
        }
    }

Esto me lo preguntaron en una entrevista, vine ac谩 a aprenderlo, gracias!

B谩sicamente se trata de reducir la cantidad de dependencias que tiene una clase de alto nivel de las clases de bajo nivel, aunque en este ejemplo se est谩 violando el principio de abierto cerrado, pues si surge una nueva clase de notificaci贸n habr铆a que modificar los par谩metros del constructor para agregarlo鈥

el esfuerzo por explicar los principios SOLID es algo que se valora, sin embargo, hay partes en las que si bien lo trata de explicar no queda del todo claro, de modo que dejare esto por aqui si quieren tener una mayor claridad o un refuerzo al concepto que se expone:
https://www.youtube.com/watch?v=2X50sKeBAcQ

Reto 4d

Creo que esta violando el Interface Segregation Principle ya que en la clase consultant esta apareciendo un metodo que da como resultado un null, ya que no la necesita.

Mi soluci贸n

interface UnderlingInterface
    {
        public function program();
        public function filetps();
    }

    interface CollateInterface {
        public function collate();
    }

    class Underling implements underlingInterface, CollateInterface
    {
        public function program()
        {
            return 'Program initech systems to deposit fractions of pennies to private account';
        }

        public function filetps()
        {
            return 'Place cover sheet on TPS report before going out';
        }

        public function collate()
        {
            return 'Collect and combine texts, information, and figures in proper order.';
        }
    }

    class Consultant implements UnderlingInterface
    {
        public function program()
        {
            return 'Program initech systems to deposit fractions of pennies to private account';
        }

        public function filetps()
        {
            return 'Place cover sheet on TPS report before going out';
        }
    }

No supe como solucionar esta parte

class Lumbergh
    {
        protected $underling;

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

    }

Reto 4c

VIOLA - Liskov Substitution Principle y Interface Segregation Principle

La clase dog al heredar de la clase animal, se ve obligado a implementar el metodo fly, ya que la logica del negocio nos dice que un perro no puede volar, bueno hasta ahora no hay un caso en la vida real xD

interface CanFly
    {
        
        public function fly();
    }

    class Animal
    {
        
    }

    class Dog implements Animal
    {
        public function bark()
        {
            echo 'The dog is Barking';
        }
    }

    class Bird implements Animal, CanFly
    {
        private $haswings;
        public function fly()
        {
            echo "The Bird is Flying";
        }
    }

Reto 4b

violando asi el principio Open/closed principle.

La clase Project management, al parecer es una soluci贸n a corto plazo a la que necesita para que cumpla su objetivo, el problema viene cuando queremos expandir m谩s adelante esta funcionalidad, ya que necesitamos modificar el codigo que funciona para que estas futuras funcionalidades se acoplen al c贸digo actual.

Mi Soluci贸n

interface ProcessInterface 
    {
        public function process();
    }


    class Programmer implements ProcessInterface
    {
        public function code()
        {
            return 'coding';
        }

        public function process()
        {
            return 'process';
        }
    }
    class Tester implements ProcessInterface
    {
        public function test()
        {
            return 'testing';
        }

        public function process()
        {
            return 'process';
        }
    }

    class ProjectManagement
    {
        public function process(ProcessInterface $processInterface)
        {
            $processInterface->process();
        }
    }

Reto 4

Viola Single Responsibility Principle
La clase Order tienen metodos que son necesarias para que funcione la clase pero esos metodos est谩n desviando su objetivo principal que es manejar solo orders.

Mi soluci贸n

class Order
{
    public function calculateTotalSum(){/*...*/}
    public function getItems(){/*...*/}
    public function getItemCount(){/*...*/}
    public function addItem($item){/*...*/}
    public function deleteItem($item){/*...*/}

    public function printOrder(){/*...*/}
    public function showOrder(){/*...*/}
}

class Database 
{
    public function load(){/*...*/}
    public function save(){/*...*/}
    public function update(){/*...*/}
    public function delete(){/*...*/}
}

Reto4b: Liskov Substitution Principle

Reto4d: Interface Segregation Principle

Reto4: Single Responsibility Principle

Reto4c: Liskov Substitution Principle

Reto4e: No supe cual era

Creo que si creamos una abstracci贸n llamada Sender que pudiera ser implementada (o heredada) en los Senders concretos como el EmailSender, WhatsappSender, etc y en la clase Notifier usar un arreglo de Senders podr铆a incluso extraerse m谩s el comportamiento.

En caso de que el notificador no fuera 煤nico y existieran varias formas de implementarlo tambi茅n abogar铆a por la abstracci贸n y generaci贸n de notificadores concretos.

Este principio es genial y la puerta para entender muchos patrones de dise帽o.

en reto4.php no parece que se respete el principio de responsabilidad Unica
en reto4b.php se puede mejorar siguiendo el principio de abierto/cerrado
en reto4c.php no encontre mejoras o principios que no se respeten
en reto4d.php puede mejorar si se respetara el principio de segregacion de interfaces
en reto4e.php no veo mejoras, de hecho creo que respeta el principio de inversion de dependencias

Esta鈥 realmente no entend铆 muy bien lo que ten铆a que hacer pero por mejorar el c贸digo鈥

<?php
    class Animal
    {

    }

    class Dog extends Animal
    {
        public function bark()
        {
            return "Woof!";
        }
    }

    class Bird extends Animal
    {
        public function fly()
        {
            return "I'm flying!";
        }
    }

Principio SOLID: Single Responsability Principle

Apunta a desarrollar aplicaciones mas mantenibles a trav茅s del tiempo

S: Single Responsibility Principle (SRP) Una sola raz贸n para cambiar

O: Open/Closed Principle (OCP) Abierta para su extensi贸n, cerrada para modificaci贸n

L: Liskov Substitution Principle (LSP) Usar m茅todos clase padre solamente , la clase hijo no debe alterar el comportamiento de los m茅todos del padre

I: Interface Segregation Principle (ISP) Los clientes de un programa solo deben conocer los m茅todos que usan

D: Dependency Inversion Principle (DIP) Los modulos de alto nivel no deben depender de los de bajo nivel.

Las abstracciones no deben depender de los detalles, los detalles deben depender de las abstracciones.

Este informacion le podria ayudar a mas de uno 馃槉
https://gustavopeiretti.com/principios-solid-con-ejemplos/

4/5 retos que pude identificar he intentar solucionar.

Single Reponsibility Principle

    class Order
    {
        public function printOrder(){/*...*/}
        public function showOrder(){/*...*/}
    }

    class Item  
    {
        public function getItems(){/*...*/}
        public function getItemCount(){/*...*/}

        public function addItem($item){/*...*/}
        public function deleteItem($item){/*...*/}   
    }

    class Calculate  
    {
        public function calculateTotalSum(){/*...*/}
    }

    class DataBase  
    {
        public function load(){/*...*/}
        public function save(){/*...*/}
        public function update(){/*...*/}
        public function delete(){/*...*/}
    }

Open/Closed Principle

interface ProcessInterface 
    {
        public function process($member);
    }
    
    class ProjectManagement
    {
        public function process($member)
        {
            $member->process($member);
        }
    }

    class Programmer implements ProcessInterface
    {
        public function code()
        {
            return 'coding';
        }

        public function process($member)
        {
            $member->code();
        }
    }

    class Tester implements ProcessInterface
    {
        public function test()
        {
            return 'testing';
        }

        public function process($member)
        {
            $member->test();
        }
    }

Liskov Substitution Principle

class Animal
    {
        public function fly()
        {
            if (! $this->hasWings) {
                throw new Exception;
            }
        }
    }

    class Dog extends Animal
    {
        
    }

Interface Segregation Principle

interface UnderlingInterface
    {
        public function program();

        public function filetps();
    }

    interface ConsultantInterface 
    {
        public function collate();
    }


    class Underling implements UnderlingInterface, ConsultantInterface
    {
        public function program()
        {
            return 'Program initech systems to deposit fractions of pennies to private account';
        }

        public function filetps()
        {
            return 'Place cover sheet on TPS report before going out';
        }

        public function collate()
        {
            return 'Collect and combine texts, information, and figures in proper order.';
        }
    }

    class Consultant implements UnderlingInterface
    {
        public function program()
        {
            return 'Outsource task to India';
        }

        public function filetps()
        {
            return 'Place cover sheet on TPS report before going out';
        }
    }

    class Lumbergh
    {
        protected $underling;

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

        public function harass()
        {
            $this->underling->program();
            $this->underling->filetps();
            $this->underling->collate();
        }
    }

Esto es lo que hice sobre el ejercicio de DIP

<?php
    class Arbol
    {
        private $tipoFruto; 
        private $frutos = [];

        public function getFrutos()
        {
            return $this->frutos;
        }
    }

    class ContadorDeFrutoa
    {
        private $Arbol;

        public function __contsruct(Arbol $Arbol)
        {
            $this->Arbol = $Arbol;
        }

        public function cuantas()
        {
            return count($this->frutos->getFrutos());
        }
    }
?>

鈥淓n alg煤n momento nuestro programa o aplicaci贸n llegar谩 a estar formado por muchos m贸dulos. Cuando esto pase, es cuando debemos usar inyecci贸n de dependencias, lo que nos permitir谩 controlar las funcionalidades desde un sitio concreto en vez de tenerlas esparcidas por todo el programa. Adem谩s, este aislamiento nos permitir谩 realizar testing mucho m谩s f谩cilmente.鈥

fuente:https://enmilocalfunciona.io/principios-solid/

My python implementation for challenge reto4b:

"""Open/Closed principle"""

import abc


class Workable(abc.ABC):
    """"""

    @abc.abstractmethod
    def process(self):
        """"""


class Programmer(Workable):

    def code(self):
        """"""
        return 'coding'

    def process(self):
        """"""
        self.code()


class Tester(Workable):

    def test(self):
        """"""
        return 'testing'

    def process(self):
        """"""
        self.test()


class ProjectManagement:
    """"""

    def process(self, member: Workable):
        """"""
        member.process()

My python implementation for challenge reto4c:

"""Liskov substitution principle"""

import abc


class Flyable(abc.ABC):
    """"""

    @abc.abstractmethod
    def fly(self):
        """"""


class Animal:
    """"""

    def eat(self):
        """"""


class Dog(Animal):
    """"""

    def eat(self):
        """"""
        return 'eat meat'


class Bird(Animal, Flyable):

    def eat(self):
        """"""
        return 'eat earthworms'

    def fly(self):
        """"""
        return 'Birds fly in different directions'


def animal_eat(animal: Animal):
    animal.eat()


Seg煤n mi punto de vista el archivo que infring铆a uno de los principios SOLID es el archivo reto4.php
Aqu铆 esta resuelto:

<?php
    class TotalOrder {
        public function calculateTotalSum(){/*...*/}
    }
    class OrderItems{
        public function getItemCount(){/*...*/}
        public function addItem($item){/*...*/}
        public function deleteItem($item){/*...*/}
        public function getItems(){/*...*/}
    }
    class OrderActions{
        public function printOrder(){/*...*/}
        public function showOrder(){/*...*/}
    }
    class OrderStates{
        public function load(){/*...*/}
        public function save(){/*...*/}
        public function update(){/*...*/}
        public function delete(){/*...*/}
    }
?>

El 鈥 Principio de inversi贸n de dependencia establece que la pol铆tica de alto nivel de su sistema no debe depender de detalles de bajo nivel. Adem谩s, las abstracciones nunca deber铆an depender de los detalles. Los singleton suelen implementar algunos detalles de bajo nivel

FALTAN ARCHIVOS DEL RESTO

La Inversion de Dependencia o Dependecy Inversion, tambien hace parte de IoC (Inversion de Control o Inversion of Control)

No se encuentran los retos de los que habla Mauro en el v铆deo, creen que podr铆an agregarlos?

Una pregunta para confirmar si he entendido bien, Para llevar a cabo la utilizacion de este principio, tendr铆amos que modificar tambi茅n la instancia que creamos del notificador? para enviarle las nuevas clases al constructor nuevo?

no hay 鈥 馃槙

En el reto4 lo conveniente ser铆a implementar nuevas clases para que por ejemplo: load(), save() y upload() se encuentren en una clase diferente a las dem谩s funciones y no dejar caer el toda la responsabilidad en la clase existente.

reto4e

<?php
    interface ManzanoInterface
    {
      public function getManzanas();
    }

    class Manzano implements ManzanoInterface
    {
        private $manzanas = [];

        public function getManzanas()
        {
            return $this->manzanas;
        }
    }

    class ContadorDeManzanas
    {
        private $manzano;

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

        public function cuantas()
        {
            return count($this->manzano->getManzanas());
        }
    }

Creo que estar铆a bueno que en cada desaf铆o se plantee un problema que se quiere resolver, como la l贸gica de negocio. De manera que en base a eso podamos proponer una soluci贸n adecuada. De por ahi eso nos ayuda a estar m谩s seguros de que la soluci贸n que encontremos sea la adecuada.

<?php
    class Order {
        public function calculateTotalSum(){/*...*/}
        public function getItems(){/*...*/}
        public function getItemCount(){/*...*/}
        public function addItem($item){/*...*/}
        public function deleteItem($item){/*...*/}

        public function printOrder(){/*...*/}
        public function showOrder(){/*...*/}

        
    }
    class manageOrder{
         function __construct() {
            print "En el constructor BaseClass\n";
         }
       	
	 public function load($order){/*...*/}
         public function save($order){/*...*/}
         public function update($order){/*...*/}
         public function delete($order){/*...*/}
    }
    

hice uno pero para kotlin


fun main() {
    val SAMSUNG : String = "samsung"
	val LG : String = "lg"
    val MOTOROLA : String = "motorola"
    
    var  motorolaCelular = Celular(MOTOROLA,"celular","G7",35000)
    var samsungTV = Televition(SAMSUNG,"television","RG85",15900)
    
    var itemsManager : ItemsManager = ItemsManager()
    itemsManager.addItem(samsungTV)
    itemsManager.addItem(motorolaCelular)
    
    println("total items: " + itemsManager.getItemCount())
    println("total price: $" + itemsManager.calculateTotalSum())
    
    print("TV Models: " )
    itemsManager.getItems().forEach{it ->         	
        	print(if(it.getType() == "television")it.getModel() else "")
    }
    print("\nCelualars Models: " )
    itemsManager.getItems().forEach{it ->         	
        	print(if(it.getType() == "celular")it.getModel() else "")
    }
    
}
abstract class Item {
    private var brand : String = ""
    private var type : String = ""
    private var model : String = ""
    private var price : Int = 0
    
    constructor(brand:String, type:String, model:String, price:Int){
        this.type = type
        this.model = model
        this.price = price    
        this.brand = brand
    }
    fun getBrand() : String{
        return this.brand
    }
    
    fun getType() : String{
        return this.type
    }
    fun getModel() : String{
        return this.model
    }
    fun getPrice() : Int {
        return this.price
    }
}

class Celular : Item {
    constructor(brand:String, type:String,model:String, price: Int) : super(brand,type,model,price)       
}
class Televition : Item {
    constructor(brand:String,type:String,model:String, price: Int) : super(brand,type,model,price)    
    
}
class ItemsManager{  
    private var items : MutableList<Item>  = ArrayList<Item>()
	private var item : Item? = null 
    
    fun addItem(item : Item){
        items.add(item)
    }
    fun calculateTotalSum() : Int{
        var totalSum : Int = 0
        for(item in items){
            totalSum += item.getPrice()
        }
        return totalSum
    }
    fun getItems():List<Item>{
        return items
    }
    fun getItemCount():Int{
        return items.size
    }       
}

Clase 14: Principio de segregaci贸n de interfaz
El Interface Segregation Principle establece que los clientes de un programa dado s贸lo deber铆an conocer de 茅ste los m茅todos que realmente usan.
Nota: este principio dice como estructurar las interfaces. De modo que cuando una clase implementa una interface no se le exija implementar m茅todos que no necesita o no son propios.
Clase 15: Principio de inversi贸n de dependencia
Dependency Inversion Principle detalla que los m贸dulos de alto nivel no deben depender de los de bajo nivel, ambos deben depender de abstracciones.
Las abstracciones no deben depender de los detalles, los detalles deben depender de las abstracciones.

Nota: este principio nos ayuda a definir como se vinculan las diferentes clases con que tienen que darle servicios a otras, ya que tenemos clases de alto nivel y bajo nivel. Las de alto nivel son las que tienen la l贸gica del negocio y las de bajo nivel

Reto4

	//SOLID - SRP

	//Dedicada a Operaciones de Calculo
    class CalculateOrder
    {
        public function calculateTotalSum(){/*...*/}
        public function getItems(){/*...*/}
        public function getItemCount(){/*...*/}
        public function addItem($item){/*...*/}
        public function deleteItem($item){/*...*/}
    }

	//Dedicada a Despliegue de Informaci贸n
    class DisplayOrder
    {
        public function printOrder(){/*...*/}
        public function showOrder(){/*...*/}
    }

	//Dedicada a Operaciones de Almacenamiento
    class PersistenceOrder
    {
        public function load(){/*...*/}
        public function save(){/*...*/}
        public function update(){/*...*/}
        public function delete(){/*...*/}
    }

Reto4d

//SOLID - ISP
    interface WorkerInterface
    {
        public function work();
    }

    interface ConsultantInterface extends WorkerInterface
    {
        public function program();

        public function filetps();
    }

    interface UnderlingInterface extends ConsultantInterface
    {
        public function collate();
    }

    class Underling  implements UnderlingInterface
    {
        public function program()
        {
            return 'Program initech systems to deposit fractions of pennies to private account';
        }

        public function filetps()
        {
            return 'Place cover sheet on TPS report before going out';
        }

        public function collate()
        {
            return 'Collect and combine texts, information, and figures in proper order.';
        }
		
        public function work()
        {
            program();
			filetps();
			collate();
        }
    }

    class Consultant implements ConsultantInterface
    {
        public function program()
        {
            return 'Outsource task to India';
        }

        public function filetps()
        {
            return 'Place cover sheet on TPS report before going out';
        }

        public function work()
        {
            program();
			filetps();
        }
    }

    class Lumbergh
    {
        protected $underling;

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

        public function harass()
        {
            $this->underling->work();
        }
    }

SOLID: Dependency Inversion Principle
Detalla que los modulos de alto nivel no deben depender de los de bajo nivel, ambos deben depender de abstracciones.
Las abrastracciones no deben depender de los detalles, los detalles deben depender de las abstracciones

Ya hab铆a escuchado y 鈥渁prendido鈥 los principios SOLID, pero con estas clases me ha quedado m谩s claro.

interface IManzano
    {
        public function getManzanas()
    }

    class Manzano implements IManzano
    {
        private $manzanas = [];

        public function getManzanas()
        {
            return $this->manzanas;
        }
    }

    class ContadorDeManzanas
    {
        public function __contsruct(IManzano $manzano)
        {
            $this->manzano = $manzano;
        }

        public function cuantas()
        {
            return count($this->manzano->getManzanas());
        }
    }
    class ManageOrder
    {
        public function calculateTotalSum(){/*...*/}
        public function getItems(){/*...*/}
        public function getItemCount(){/*...*/}
        public function addItem($item){/*...*/}
        public function deleteItem($item){/*...*/}
    }

    class OrderData{
        public function load(){/*...*/}
        public function save(){/*...*/}
        public function update(){/*...*/}
        public function delete(){/*...*/}

    }


    class Order{
        public function printOrder(){/*...*/}
        public function showOrder(){/*...*/}
    }
interface UnderlingInterface
    {
        public function program();
        public function filetps();
        public function collate();
    }

    interface ConsultantInterface{
        public function program();
        public function filetps();
    }




    class Underling implements UnderlingInterface
    {
        public function program()
        {
            return 'Program initech systems to deposit fractions of pennies to private account';
        }

        public function filetps()
        {
            return 'Place cover sheet on TPS report before going out';
        }

        public function collate()
        {
            return 'Collect and combine texts, information, and figures in proper order.';
        }
    }




    class Consultant implements ConsultantInterface
    {
        public function program()
        {
            return 'Outsource task to India';
        }

        public function filetps()
        {
            return 'Place cover sheet on TPS report before going out';
        }

        public function collate()
        {
            return null;
        }
    }




    class Lumbergh
    {
        protected $underling;

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

        public function harass()
        {
            $this->underling->program();
            $this->underling->filetps();
            $this->underling->collate();
        }
    }

los par谩metros que recibe el constructor deben ser interfaces

El principio ser铆a como un ejemplo as铆:

class Numbers {
    constructor(num1, num2) {
        this.num1 = num1
        this.num2 = num2
    }
}


class Sum extends Numbers {
    constructor(num1, num2) {
        super(num1, num2)
    }
    sum() {
        return console.log(this.num1 + this.num2);
    }
}

class Mult extends Numbers {
    constructor(num1, num2) {
        super(num1, num2)
    }
    mult() {
        return console.log(this.num1 * this.num2);
    }
}
const sum = new Sum(2, 4);
sum.sum();

const mult = new Mult(3, 4);
mult.mult();

por lo que veo solo la interfaz EmailSender podria implementarse ya que puede ser mediante hotmail, gmail, etc ya que la de WhatsApp no esta bien, creo que seria hacer una interfaz superior en la que se pudeira incluir whatsapp, facebook, telegram etc.

Esto es muy interesante en verdad sigo epnsando que esto es practucamente implementar patrones de dise帽o.

Reto A: En este use el single responsability

<?php
    //Single responsability

  class OrderCRUDE  {
    public function load(){ /*  */}
    public function save(){ /*  */}
    public function update(){ /*  */}
    public function delete(){ /*  */}
  }

  class actionOrder {
    public function addItem($item){/*...*/}
    public function deleteItem($item){/*...*/}
    public function printOrder(){/*...*/}
    public function showOrder(){/*...*/}
    public function calculateTotalSum(){/*...*/}
  }

  class GetOrderItem {
    public function getItems(){/*...*/}
    public function getItemCount(){/*...*/}
  }

Reto4b

fun main() {
    val programer = Programmer()
    val tester = Tester()
    val projectManagement = ProjectManagement()
    val programmerDo = projectManagement.process(programer)
    val testerDo = projectManagement.process(tester)
    
    
    println("A programmer is " + programmerDo)
    println("A tester is " + testerDo)
}
interface Workable {
    fun process(): String
}
class Programmer : Workable {
    public fun code():String
    {
        return "coding"
    }
    override fun process() : String{
        return code()
    }
}

class Tester : Workable {
    public fun test() : String
    {
        return "testing"
    }
    override fun process(): String{
        return test()
    }
}
class ProjectManagement {
    
    public fun process( member : Workable): String
    {
        return member.process()
    }
}

Reto4c

<?php
    class Animal
    {
        public $hasWings;
    }

    class Bird extends Animal
    {
        public function fly()
        {
            if (! $this->hasWings) {
                throw new Exception;
            }
            return 'flying';
        }
    }

    class Dog extends Animal
    {
    }

reto4c



fun main() {
  val duke = Dog()
  val littleBird = Bird()
  var animalMoveManager =  AnimalMoveManager()
  animalMoveManager.move(duke)
  animalMoveManager.move(littleBird)
  
  animalMoveManager.move(duke,"duke")
  animalMoveManager.move(littleBird, "bird")
  
}
interface Flyable{
    public fun fly(name:String)
    
}
interface Animal{
    public fun walk(name:String)
}




class Dog : Animal
{
   private fun run(name:String){
       println(name + "is running!")
   }
   override fun walk(name:String)
    {
        run(name)
    }
}

class Bird : Animal, Flyable{
    override fun walk(name:String){
        println(name + " is moving!")        
    }
    override fun fly(name:String){
        println(name + " is flying")
    }
}

class AnimalMoveManager{
    public fun move( animal : Animal, name:String = "animal"){
        animal.walk(name)
    }
}

output

animalis running!
animal is moving!
dukeis running!
bird is moving!```

reto4d



fun main() {
 var consultant = Consultant()
 var lumberg = Lumbergh(consultant)
 lumberg.harass()
  
}

interface UnderlingInterface
    {
        public fun program() : String;

        public fun filetps() : String;

        public fun collate() : String;
    }

    class Underling : UnderlingInterface {
        override fun program() : String
        {
            return "Program initech systems to deposit fractions of pennies to private account";
        }

        override public fun filetps() : String
        {
            return "Place cover sheet on TPS report before going out";
        }

        override public fun collate() : String
        {
            return "Collect and combine texts, information, and figures in proper order.";
        }
    }

    class Consultant : UnderlingInterface
    {
        override public fun program() : String
        {
            return "Outsource task to India";
        }

        override public fun filetps() : String
        {
            return "Place cover sheet on TPS report before going out";
        }

        override public fun collate() : String
        {
            return "";
        }
    }

    class Lumbergh
    {
        var underling : UnderlingInterface

        constructor(underling : UnderlingInterface)
        {
            this.underling = underling;
        }

        public fun harass()
        {
            println(this.underling.program());
            println(this.underling.filetps());
            println(this.underling.collate());
        }
    }```

output


Outsource task to India
Place cover sheet on TPS report before going out


Perfecto. Gracias

Reto 1

<?php

    class Order {
        public function load(){/*...*/}
        public function save(){/*...*/}
        public function update(){/*...*/}
        public function delete(){/*...*/}
    }

    class OrderItemManager {
        public function calculateTotalSum(){/*...*/}
        public function getItems(){/*...*/}
        public function getItemCount(){/*...*/}
        public function addItem($item){/*...*/}
        public function deleteItem($item){/*...*/}
    }

    class OrderPrinter() {
        public function printOrder(){/*...*/}
        public function showOrder(){/*...*/}
    }

// class Order
// {
//     public function calculateTotalSum(){/*...*/}
//     public function getItems(){/*...*/}
//     public function getItemCount(){/*...*/}
//     public function addItem($item){/*...*/}
//     public function deleteItem($item){/*...*/}

//     public function printOrder(){/*...*/}
//     public function showOrder(){/*...*/}

//     public function load(){/*...*/}
//     public function save(){/*...*/}
//     public function update(){/*...*/}
//     public function delete(){/*...*/}
// }

Mi c贸digo del primer reto, en este caso apliqu茅 el principio de sustituci贸n de Liskov:

<?php
  
    class Worker() {
  
        public function do_what_you_can_do() {
            $this->work();
        }

    }

    class Programmer extends Worker
    {
        public function work()
        {
            return 'coding';
        }
    }
    class Tester extends Worker
    {
        public function work()
        {
            return 'testing';
        }
    }
    class ProjectManagement
    {
        public function process(Worker $member)
        {

            $member->do_what_you_can_do();
        }
    }

Reto 2

<?php
    class Programmer
    {   
        public function __construct() {
            return $this->code()
        }

        public function code()
        {
            return 'coding';
        }
    }

    class Tester
    {
        public function __construct() {
            return $this->test()
        }

        public function test()
        {
            return 'testing';
        }
    }

    class ProjectManager 
    {
        $MEMBER_LIST = array('Programmer', 'Tester')
        public function process($member)
        {
            for ($i = 0; i <= count($this->$MEMBER_LIST); $i++) {
                if (in_array($member, $this->$MEMBER_LIST)) {
                    $member()
                } else {
                    throw new Exception('Invalid input member');
                }
            }
        }
    }

Ejercicio E

    /* Dependency Inversion Principle */

    interface fruta 
    {
        public function getFruta();
    }

    class Manzana implements fruta
    {
        private $manzanas = [];
        public function getFruta()
        {
            return $this->manzanas;
        }
    }

    class Banano implements fruta
    {
        private $bananos = [];
        public function getFruta()
        {
            return $this->bananos;
        }
    }

    class ContadorDeFrutas
    {
        private $fruta;

        public function __contsruct(fruta $fruta)
        {
            $this->fruta = $fruta;
        }

        public function contar()
        {
            return count($this->fruta->getFruta());
        }
    }

    $bananos = new Banano();
    $contadorBananos = new ContadorDeFrutas($Bananos);
    $cantidad = $contadorBananos->contar();

    $manzanas = new Manzana();
    $contadorManzanas = new ContadorDeFrutas($manzanas);
    $cantidad = $contadorManzanas->contar();

Reto 4.

Interface Order
{
    public function calculateTotalSum();
}

Interface Items
{
    public function getItems();
    public function getItemCount();
    public function addItem($item);
    public function deleteItem($item);
}

Interface OrderRender
{
    public function printOrder();
    public function showOrder();
}

Interface OrderCrudActions
{
    public function load();
    public function save();
    public function update();
    public function delete();
}

class Order implements Order, OrderRender, OrderCrudActions
{
    protected $item; 

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

    public function calculateTotalSum()
    {

    }
}

鈥 Reto 4b.

class ProjectManagement
    {
        public function processCode(Programmer $member)
        {
            $member->code();
        }

        public function test(Tester $member)
        {
            $member->test();
        }
    }

鈥 Reto 4c.

interface Animal
    {

    }

    class FlyingAnimal
    {
        public function fly(){}
    }

    class LandAnimal
    {

    }

鈥 Reto 4d.

interface CollateInterface
    {
        public function collate();
    }

    interface ConsultantInterface
    {
        public function program();
        public function filetps();
    }

    interface UnderlingInterface extends CollateInterface, ConsultantInterface
    {

    }

    class Underling implements UnderlingInterface
    {
        public function program() {
            return 'Program initech systems to deposit fractions of pennies to private account';
        }

        public function filetps(){
            return 'Place cover sheet on TPS report before going out';
        }

        public function collate(){
            return 'Collect and combine texts, information, and figures in proper order.';
        }
    }

    class Consultant implements ConsultantInterface
    {
        public function program(){
            return 'Outsource task to India';
        }

        public function filetps(){
            return 'Place cover sheet on TPS report before going out';
        }
    }

    class Lumbergh
    {
        protected $underling;

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

        public function harass(){
            $this->underling->program();
            $this->underling->filetps();
            $this->underling->collate();
        }
    }

鈥 Reto 4e.

class Manzano
    {
        private $manzanas = [];

        public function getManzanas()
        {
            return $this->manzanas;
        }

        public function cuantas()
        {
            return count($this->manzanas);
        }
    }

Incre铆ble, tiempo tratando de encontrarle utilidad y en el 3:39 lo encontr茅.

En este video de BetaTech explica los principios solid, me sirvio para reforzar el conocimiento de este curso.

https://architectcoders.com/wp-content/uploads/2019/08/principios-solid-devexperto.pdf

Conclusi贸n:
鈥淐omo ves, este mecanismo nos obliga a organizar nuestro c贸digo de una manera
muy distinta a como estamos acostumbrados, y en contra de lo que la l贸gica
dicta inicialmente, pero a la larga compensa por la flexibilidad que otorga a la
arquitectura de nuestra aplicaci贸n鈥

Este era (hasta hoy) uno el principio que m谩s me costaba entender.

Gracias che!! Toda una joya la explicaci贸n de los principios

My python implementation for challenge reto4 :

"""Single responsibility principle"""


class Order:

    def __init__(self):
        """"""

    def print_order(self, pk: int) -> None:
        """"""

    def show_order(self, pk: int) -> object:
        """"""

    def calculate_total_sum(self) -> float:
        """"""


class OrderItem:

    def __init__(self):
        """"""

    def add_item(self, item: object) -> object:
        """"""

    def get_item_count(self, pk: int) -> object:
        """"""

    def delete_item(self, pk: int) -> None:
        """"""

    def get_item(self, pk: int) -> object:
        """"""


class OrderRecord:

    def __init__(self):
        """"""

    def load(self, pk: int) -> object:
        """"""

    def save(self, order: object) -> object:
        """"""

    def update(self, order: object) -> object:
        """"""

    def delete(self, pk: int) -> object:
        """"""

**Reto4b **
Se aplic贸 Open/Closed principle ahora se puede agregar otras profesiones y clase ProyectManagement no se tendr谩 que modificar.

<?php
    interface IProfession{
        public function activity();
    }

    class Programmer implements IProfession
    {
        public function activity()
        {
            return 'coding';
        }
    }
    class Tester implements IProfession
    {
        public function activity()
        {
            return 'testing';
        }
    }

    //Open/Closed principle ahora se puede agregar otras profesiones y clase ProyectManagement no se tendr谩 que modificar
    class ProjectManagement
    {
        public function process(IProfession $member)
        {
            $member->activity();
        }
    }

reto4c
Se corrigi贸 violaci贸n de Liskov Substitution Principle

<?php
// Se corrigi贸 violaci贸n de Liskov Substitution Principle
interface IFly
{
    public function fly();
}

class Animal
{
}

class Dog extends Animal implements IFly
{
    public function fly()
    {
        if (!$this->hasWings) {
            throw new Exception;
        }
    }
}

reto4d
Se agreg贸 Interface Segregation Principle para no forzar la implementaci贸n de todos los m茅todos

<?php
// se agreg贸 Interface Segregation Principle para no forzar la implementaci贸n de todos los m茅todos
interface IProgram
{
    public function program();
}
interface IFiletps
{
    public function filetps();
}
interface ICollate
{
    public function collate();
}


class Underling implements IProgram, IFiletps, ICollate
{
    public function program()
    {
        return 'Program initech systems to deposit fractions of pennies to private account';
    }

    public function filetps()
    {
        return 'Place cover sheet on TPS report before going out';
    }

    public function collate()
    {
        return 'Collect and combine texts, information, and figures in proper order.';
    }
}

class Consultant implements IProgram, IFiletps
{
    public function program()
    {
        return 'Outsource task to India';
    }

    public function filetps()
    {
        return 'Place cover sheet on TPS report before going out';
    }
}

class Lumbergh
{
    protected $program;
    protected $filetps;
    protected $collate;

    public function __construct(IProgram $program, IFiletps $filetps, ICollate $collate)
    {
        $this->program = $program;
        $this->filetps = $filetps;
        $this->collate = $collate;
    }

    public function harass()
    {
        $this->program->program();
        $this->filetps->filetps();
        $this->collate->collate();
    }
}

reto4e
se aplic贸 Dependency Inversion Principle para desacoplar la clase de bajo nivel Manzano de la clase de alto nivel ContadorDeManzanas

<?php
// se aplic贸 Dependency Inversion Principle para desacoplar la clase de bajo nivel Manzano de la clase de alto nivel ContadorDeManzanas 
interface ITree
{
    public function getFruits();
}

class Manzano implements ITree
{
    private $manzanas = [];

    public function getFruits()
    {
        return $this->manzanas;
    }
}

class ContadorDeFrutas
{
    private $tree;

    public function __contsruct(ITree $tree)
    {
        $this->tree = $tree;
    }

    public function cuantas()
    {
        return count($this->tree->getFruits());
    }
}

Estoy bastante perdido en este tema de los principios solid. Entiendo lo que quiere decir pero al momento de inspeccionar los c贸digos brindados es que como que estoy ciego y no puedo ver nada. Pero bueno supongo que ser谩 seguir practicando y repetir algunas clases para digerir mejor el contenido. 馃檪

<?php
    class Order
    {
        public function Calculo_Items(){
            public function calculateTotalSum(){/*...*/}
            
        }

        public function Obtener_Items(){
            public function getItems(){/*...*/}
            public function getItemCount(){/*...*/}
        }
        
        public function Orden_Item(){
            public function addItem($item){/*...*/}
            public function deleteItem($item){/*...*/}
        }
        
        public function Mostrar_info(){
            public function printOrder(){/*...*/}
            public function showOrder(){/*...*/}
        }
        
        public function Carga_y_Actualizado(){
            public function load(){/*...*/}
            public function save(){/*...*/}
            public function update(){/*...*/}
        }
        
        public function delete(){/*...*/}
    }


<?php
    class Programmer
    {
        public function code()
        {
            return 'coding';
        }

        public function process(){
            code();
        }

    }
    class Tester
    {
        public function test()
        {
            return 'testing';
        }

        public function process(){
            test();
        }
    }

    class ProjectManagement {
        public function process(array $members) {
            foreach( $members as $member ) {
                $member->process();
            }
        }
    }

Entonces creo que es necesario ver el curso de programaci贸n a objetos antes de ver este curso.

El objetivo del Dependency Inversion Principle (DIP) consiste en reducir las dependencias entre los m贸dulos del c贸digo, es decir, alcanzar un bajo acoplamiento de las clases.

<?php
	interface worker{
		public function work();
	}
	
    class Programmer implements worker
    {
        public function work()
        {
            return 'coding';
        }
    }
    class Tester implements worker
    {
        public function work()
        {
            return 'testing';
        }
    }
    class ProjectManagement
    {
        public function process($member)
        {
			$member->work();
        }
    }

Este c贸digo no cumple con el principio de inyecci贸n de dependencias

class Notifier {
    lateinit var emailSender : EmailSender
    lateinit var messageSender: MessageSender
   constructor(){
    emailSender = EmailSender()
    messageSender = MessageSender()
  }   
}

Un punto importante es que EmailSender, MessageSender no deben de ser clases sino interfaces.

class Notifier {
  constructor(emailSender : EmailSender, messageSender: MessageSender) {
    this.emailSender = emailSender
    this.messageSender = MessageSender
  }
}

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.,

interface EmailSender {
  fun sendEmail(message : String)
}

class Hotmail : EmailSender {
  overrider fun sendEmail(message : String)
}

class Gmail : EmailSender {
  overrider fun sendEmail(message : String)
}