神码(GOD'S码)



“神圣的”代码是一个听起来很冠冕堂皇的词,看起来像是一个黄色标题,但尽管如此,将要讨论的正是这样的代码:它由什么部分组成以及如何编写。 这是一个关于我为确保任务不会随代码审查而返回的事情的故事,并带有以下注释:“ All he * nya-redo”。

我没有专门的教育,我不得不通过错误,擦伤和擦伤的方式在实践中学习编程。 不断努力提高书面代码的质量,我制定了一些应遵循的规则。 我要分享。

GOD的代码-首字母缩写词-根据Grasp,Object健美操,Demeter定律和Solid原理编写的代码。 他们都认识的人,只有一个人见过,但我们将考虑首字母缩略词的每个组成部分。 我的目标不是深入研究每组规则,因为Internet上已多次涉及这些规则。 相反,我根据自己的经验进行了介绍。

格拉斯


九个模板,用于将职责分配给类和对象。 为了方便记忆,我将它们分为两个子组:

  1. 在第一个子组中,我们可以区分规则,这些规则使您可以编写经过良好测试和修改的原子模块。 这些规则与责任无关,而与模块的特性有关:弱耦合,强粘附力,多态性,抗变化性。 对于我自己,我用SOLID覆盖了这些规则,有关这一点的更多信息,请参见相应部分。
  2. 第二个子组是更清晰的模板,告诉我们谁创建对象(“创建者”-工厂模式的集合名称),如何减少模块之间的连接(使用“控制器”和“中间”模式)以及委托给谁个人责任(信息专家),以及如果我爱DDD且同时耦合度低(纯小说)怎么办。

在这里阅读更多。

对象健美操


一组代码执行规则,与法律的codeStyle代码非常相似。 也有九个。 我将谈论我在日常工作中尝试遵循的三点(稍作修改),其余的可以在原始资料中阅读。

  1. 该方法的长度不超过15个LOC,该类中的方法数量不超过15个,一个名称空间中的类数量不超过15个。最重要的是,很长的代码很难阅读和理解。 另外,长类和方法是违反SRP的信号(更多信息请参见下文)。
  2. 每个方法最多嵌套一层。

    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/zh-CN414201/


All Articles