Clases privadas Escondiéndose en php

En php, como en la mayoría de los otros lenguajes OOP, hay modificadores de visibilidad. Estas son las palabras clave públicas, protegidas y privadas. Pero se aplican exclusivamente a propiedades, métodos o constantes. Estos modificadores están estrechamente relacionados con la capacidad de encapsular datos. Vale la pena señalar que en lenguajes como java, C #, vaya ( https://golang.org/doc/go1.4#internalpackages ), ruby ​​( https://habr.com/post/419969/ ), crystal ( https : //crystal-lang.org/reference/syntax_and_semantics/visibility.html ) es posible limitar el alcance de los paquetes (clases) o clases \ tipos. En php no hay forma de limitar el alcance de las clases: cualquier clase conectada es accesible desde cualquier otra clase. Sin embargo, puedes emular esta característica usando varios trucos.


Por qué podría ser necesario ocultar a nivel de clase:


  • Clases de servicio (ayudantes) de la biblioteca: no ensucie la API de la biblioteca con clases internas sin sentido.
  • Encapsulación con ocultamiento de objetos internos de "lógica empresarial", por ejemplo, prohibición de la generación directa de objetos dependientes sin pasar por una clase más general.

Por separado, podemos distinguir la partición de clases "grandes" en objetos pequeños. Es una buena práctica limitar la complejidad (y el número de líneas) tanto de los métodos individuales como de las clases. El número de líneas aquí va como uno de los marcadores que el método de clase o la clase en sí asume una responsabilidad innecesaria. Al refactorizar un método público, trasladamos partes de él a métodos privados \ protegidos. Pero cuando, por una razón u otra, la clase crece y separamos una entidad separada de ella, estas clases muy privadas \ protegidas se transfieren a una clase separada, por lo que indirectamente abrimos el acceso a métodos que anteriormente estaban limitados al alcance de una clase.


Ahora los métodos reales de emular encubrimientos en sí.


A nivel del acuerdo de ejecución del código


Con los comentarios de PHPDoc, puede marcar una clase, un rasgo o una interfaz como internal ( http://docs.phpdoc.org/references/phpdoc/tags/internal.html ). Sin embargo, algunos IDE (como PhpStorm) pueden entender tales etiquetas.


Usar información de tiempo de ejecución


En tiempo de ejecución, puede verificar desde dónde se llamó al constructor de la clase. Por ejemplo, a través del método debug_backtrace ( http://php.net/manual/ru/function.debug-backtrace.php ) o use la funcionalidad Xdebug similar para controlar el código en el entorno dev \ test. Aquí hay un ejemplo de una solución formalizada ( https://coderwall.com/p/ixvnga/how-emulates-private-class-concept-in-php ).


utilizando debug_backtrace
 /** * The private class */ final class PrivateClass { /** * defines the only class able to instantiate the current one * * @var string */ private $allowedConsumer = 'AllowedPrivateClassConsumer'; /** * constructor * * @throws Exception */ public function __construct() { /** * here comes the privacy filter, it could be extracted to a private method * or to a static method of another class with few adjustments */ $builder = debug_backtrace(); if (count($builder) < 2 || !isset($builder[1]['class']) || $builder[1]['class'] !== $this->allowedConsumer) { throw new Exception('Need to be instantiated by '.$this->allowedConsumer); } } } 

Usa clases anónimas


Una funcionalidad relativamente nueva en php son las clases anónimas ( http://php.net/manual/ru/language.oop5.anonymous.php ). Habiendo descrito la clase anónima dentro del método protegido, buscamos ocultarla. Para no confundir la definición de una clase dentro de una función, puede describir la clase "privada" en un archivo separado como resumen, y ya expandirla en la definición de una clase anónima. Un buen ejemplo del uso de este método se encuentra en este enlace ( https://markbakeruk.net/2018/06/25/using-php-anonymous-classes-as-package-private-classes/ ).


Con base en el material encontrado, está claro que la funcionalidad de ocultar clases se exige de alguna manera (y existe en muchos idiomas), pero la práctica de su uso es muy limitada, posiblemente debido a la falta de descripción de ejemplos en varias "mejores prácticas", colecciones de plantillas y fuentes similares. Lo cual, en mi opinión, es bastante extraño, que hay un énfasis en ocultar los métodos internos y las propiedades de los objetos, pero casi nadie presta atención al hecho de que piezas lógicas de código más grandes en forma de clases de biblioteca de utilidad o dominios de dominio permanecen en el espacio de visibilidad global.

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


All Articles