Código Divino (código de DIOS)



El código "divino" es un término de alto sonido que puede parecer un encabezado amarillo, pero sin embargo es precisamente ese código el que se discutirá: en qué partes consiste y cómo escribirlo. Esta es una historia sobre mis esfuerzos para asegurar que las tareas no vuelvan con una revisión del código con la nota: "Todo lo que * nya - rehacer".

No tengo una educación especializada, y tuve que aprender programación en la práctica, a través de errores, abrasiones y contusiones. Trabajando constantemente para mejorar la calidad del código escrito, elaboré algunas reglas que deberían cumplir. Quiero compartirlos

Código de Dios - acrónimo acrónimo - código escrito de acuerdo con los principios de comprensión, calistenia de objetos, ley de Demeter y sólido. Alguien que todos conocen, alguien solo conoció a algunos, pero consideraremos cada componente del acrónimo. No me propongo sumergirme en cada grupo de reglas en detalle, ya que se han cubierto muchas veces en Internet. En cambio, ofrezco un apretón de mi propia experiencia.

GRASP


Nueve plantillas para asignar responsabilidades a clases y objetos. Para la conveniencia de recordar, los divido en dos subgrupos:

  1. En el primer subgrupo, podemos distinguir las reglas que le permiten escribir módulos atómicos que están bien probados y modificados. Estas reglas no son tanto sobre responsabilidad, sino, digamos, sobre las propiedades de los módulos: acoplamiento débil, adhesión fuerte, polimorfismo, resistencia a los cambios. Por mi parte, anulo estas reglas con SOLID, más sobre esto en la parte correspondiente.
  2. El segundo subgrupo ya son plantillas más claras que nos dicen sobre quién crea los objetos ("creador" - el nombre colectivo para los patrones de fábrica), cómo reducir la conexión entre los módulos (usando los patrones "controlador" e "intermediario"), a quién delegar responsabilidades individuales (experto en información) y qué hacer si amo DDD y al mismo tiempo poco acoplamiento (pura ficción).

Lee más aquí .

Objeto calistenia


Un conjunto de reglas de ejecución de código que son muy similares al código de leyes codeStyle. También hay nueve de ellos. Hablaré sobre tres que trato de seguir en mi trabajo diario (ligeramente modificado), el resto se puede leer en la fuente original .

  1. La longitud del método no es más de 15 LOC, el número de métodos en la clase no es más de 15, el número de clases en un espacio de nombres no es más de 15. La conclusión es que las largas hojas de código son muy difíciles de leer y entender. Además, las clases y métodos largos son una señal de violación de SRP (más sobre esto a continuación).
  2. Máximo un nivel de anidamiento por método.

    public function processItems(array items)
    {
         // 0
         foreach (items as item) {
              // 1
              for (i = 0; i < 5; i++) {
                   // 2
                   … process item 5 times …
              }
         }
    }

    item .

    public function processItems(array items)
    {
         // 0
         foreach (items as item) {
              // 1
              this.processItem(item);
         }
    }
     
    public function processItem(Item item)
    {
         // 0
         for (i = 0; i < 5; i++) {
              // 1
              … process item 5 times …
         }
    }

    -, — , , .
  3. else , .

    public function processSomeDto(SomeDtoClass dto)
    {
         if (predicat) {
              throw new Exception(‘predicat is failed’);
         } else {
              return this.dtoProcessor.process(dto);
         }
    }

    :

    public function processSomeDto(SomeDtoClass dto)
    {
         if (predicat) {
              throw new Exception(‘predicat is failed’);
         }
     
         return this.dtoProcessor.process(dto);
    }

, .


GRASP’a. , .



: B, . . :

  1. .
  2. , .
  3. .
  4. , .

. , . this.objectB.objectC.getSomeStuff() , , .

. -, . :

public function methodA()
{
     spawnedObject = this.factory.spawn();
     spawnedObject.performSomeStuff();
}

:

public function methodA()
{
     this.factory.spawn().performSomeStuff();
}

, - .

public function methodA()
{
     this.processor.process(this.factory.spawn());
}

: DTO/Entity. .

public function methodA(SomeDtoClass dto)
{
     dto.getAddress().getCity();
}

, , . , , , , getCity DTO Address dto.

SOLID


SRP, OCP, LSP, ISP, DIP — , .

SRP — . — , . High Cohesion GRASP’a.

: , — - (MVC). - - , SRP.

public function indexAction(RequestInterface request): ResponseInterface
{
     requestDto = this.requestTransformer.transform(request);
     responseDto = this.requestProcessor.process(requestDto);
 
     return this.responseTransformer.transform(responseDto);
}

- , , — . , , , , .

OCP — -. , , .

- , if/switch. , . . — . , .

resolver, .

final lass Resolver implements ResolverInterface
{
     private mapping;
 
     public function Resolver(array mapping)
     {
          this.mapping = mapping;
     }
 
     public function resolve(Item item)
     {
          return this.mapping[item.getType()].perform(item);
     }
}

, . : , final, abstract, .

LSP — . , .

:

  1. ( ).
  2. ( , , , ).
  3. ( ).
  4. , ( , , , ).

    class ParentClass
    {
         public function someMethod(string param1)
         {
              // some logic
         }
    }
    
    class ChildClass extends ParentClass
    {
         public function someMethod(string param1, string param2)
         {
              if (param1 == '') {
                   throw new ExtraException();
              }
    
              // some logic
         }
    }


someMethod ChildClass (param2), param1, . , ParentClass ChildClass.

ISP — . , . , , , , — , .

interface DuckInterface
{
     public function swim(): void;

     public function fly(): void;
}

class MallardDuck implements DuckInterface
{
     public function swim(): void
     {
          // some logic
     }

     public function fly(): void
     {
          // some logic
     }
}

class RubberDuck implements DuckInterface
{
     public function swim(): void
     {
          // some logic
     }

     public function fly(): void
     {
          // can't fly :(
     }
}

RubberDuck DuckInterface. , , , DuckInterface FlyableInterface SwimableInterface, .

DIP — . , , ( , ). new .

class DIPViolation
{
     public function badMethod()
     {
          someService = new SomeService(445, 'second params');
          // operations with someService
     }
}

- , . . :

class DIP
{
     private $service;

     public function DIP(SomeServiceInterface $someService)
     {
          $this->someService = $someService;
     }

     public function goodMethod()
     {
          // operations with someService
     }
}

, , , , «» . , . , , , «», , :)

Source: https://habr.com/ru/post/es414201/


All Articles