Deprecido: PHP_CODESNIFFER es ideal para manejar espacios y posiciones de carbón. Sin embargo, estas reglas son sobre la arquitectura y la estructura del código. En 2020, hay una herramienta que se adapta perfectamente a Phpstan .
Dicho eso, la calistenia de objetos se implementaron como reglas de Phpstan en un paquete symplify/phpstan-rules . Usarlo en su lugar?
includes:
- vendor/symplify/phpstan-rules/packages/object-calisthenics/config/object-calisthenics-rules.neon
- vendor/symplify/phpstan-rules/packages/object-calisthenics/config/object-calisthenics-services.neon
La calistenia de objetos se establece de reglas en el código orientado a objetos, que se centran en la mantenibilidad, la legibilidad, la prueba y la comprensibilidad . Primero somos pragmáticos : son fáciles de usar todos juntos o uno por uno.
Lea la publicación de William Durand o verifique la presentación de Guilherme Blanco .
composer require object-calisthenics/phpcs-calisthenics-rules --devSi sabe lo que quiere, salta a la regla específica:
En php_codesniffer
vendor/bin/phpcs src tests -sp
--standard=vendor/object-calisthenics/phpcs-calisthenics-rules/src/ObjectCalisthenics/ruleset.xml
--sniffs=ObjectCalisthenics.Classes.ForbiddenPublicPropertyEn EasyCoding Standard
# ecs.yaml
services :
ObjectCalisthenicsSniffsClassesForbiddenPublicPropertySniff : ~entonces
vendor/bin/ecs check srcX nivel de sangría por método foreach ( $ sniffGroups as $ sniffGroup ) {
foreach ( $ sniffGroup as $ sniffKey => $ sniffClass ) {
if (! $ sniffClass instanceof Sniff) {
throw new InvalidClassTypeException ;
}
}
}?
foreach ( $ sniffGroups as $ sniffGroup ) {
$ this -> ensureIsAllInstanceOf ( $ sniffGroup , Sniff::class);
}
// ...
private function ensureIsAllInstanceOf ( array $ objects , string $ type )
{
// ...
}En php_codesniffer:
vendor/bin/phpcs ... --sniffs=ObjectCalisthenics.Metrics.MaxNestingLevelEn ECS:
# ecs.yaml
services :
ObjectCalisthenicsSniffsMetricsMaxNestingLevelSniff : ~ En php_codesniffer:
<? xml version = " 1.0 " ?>
< ruleset name = " my-project " >
< rule ref = " ObjectCalisthenics.Metrics.MaxNestingLevel " >
< properties >
< property name = " maxNestingLevel " value = " 2 " />
</ properties >
</ rule >
</ ruleset >En ECS:
services :
ObjectCalisthenicsSniffsMetricsMaxNestingLevelSniff :
maxNestingLevel : 2 if ( $ status === self :: DONE ) {
$ this -> finish ();
} else {
$ this -> advance ();
}?
if ( $ status === self :: DONE ) {
$ this -> finish ();
return ;
}
$ this -> advance ();En php_codesniffer:
vendor/bin/phpcs ... --sniffs=ObjectCalisthenics.ControlStructures.NoElseEn ECS:
# ecs.yaml
services :
ObjectCalisthenicsSniffsControlStructuresNoElseSniff : ~-> ) por declaración $ this -> container -> getBuilder ()-> addDefinition (SniffRunner::class);?
$ containerBuilder = $ this -> getContainerBuilder ();
$ containerBuilder -> addDefinition (SniffRunner::class);En php_codesniffer:
vendor/bin/phpcs ... --sniffs=ObjectCalisthenics.CodeAnalysis.OneObjectOperatorPerLineEn ECS:
# ecs.yaml
services :
ObjectCalisthenicsSniffsCodeAnalysisOneObjectOperatorPerLineSniff : ~ En php_codesniffer:
<? xml version = " 1.0 " ?>
< ruleset name = " my-project " >
< rule ref = " ObjectCalisthenics.CodeAnalysis.OneObjectOperatorPerLine " >
< properties >
< property name = " variablesHoldingAFluentInterface " type = " array " value = " $queryBuilder,$containerBuilder " />
< property name = " methodsStartingAFluentInterface " type = " array " value = " createQueryBuilder " />
< property name = " methodsEndingAFluentInterface " type = " array " value = " execute,getQuery " />
</ properties >
</ rule >
</ ruleset >En ECS:
services :
ObjectCalisthenicsSniffsCodeAnalysisOneObjectOperatorPerLineSniff :
variablesHoldingAFluentInterface : ["$queryBuilder", "$containerBuilder"]
methodsStartingAFluentInterface : ["createQueryBuilder"]
methodsEndingAFluentInterface : ["execute", "getQuery"]Esto está relacionado con la clase, el rasgo, la interfaz, la constante, la función y los nombres de variables.
class EM
{
// ...
}?
class EntityMailer
{
// ...
}En php_codesniffer:
vendor/bin/phpcs ... --sniffs=ObjectCalisthenics.NamingConventions.ElementNameMinimalLengthEn ECS:
# ecs.yaml
services :
ObjectCalisthenicsSniffsNamingConventionsElementNameMinimalLengthSniff : ~ En php_codesniffer:
<? xml version = " 1.0 " ?>
< ruleset name = " my-project " >
< rule ref = " ObjectCalisthenics.NamingConventions.ElementNameMinimalLength " >
< properties >
< property name = " minLength " value = " 3 " />
< property name = " allowedShortNames " type = " array " value = " i,id,to,up " />
</ properties >
</ rule >
</ ruleset >En ECS:
# ecs.yaml
services :
ObjectCalisthenicsSniffsNamingConventionsElementNameMinimalLengthSniff :
minLength : 3
allowedShortNames : ["i", "id", "to", "up"] class SimpleStartupController
{
// 300 lines of code
}?
class SimpleStartupController
{
// 50 lines of code
} class SomeClass
{
public function simpleLogic ()
{
// 30 lines of code
}
}?
class SomeClass
{
public function simpleLogic ()
{
// 10 lines of code
}
} class SomeClass
{
// 20 properties
}?
class SomeClass
{
// 5 properties
} class SomeClass
{
// 20 methods
}?
class SomeClass
{
// 5 methods
}En php_codesniffer:
vendor/bin/phpcs ... --sniffs=ObjectCalisthenics.Files.ClassTraitAndInterfaceLength,ObjectCalisthenics.Files.FunctionLength,ObjectCalisthenics.Metrics.MethodPerClassLimit,ObjectCalisthenics.Metrics.PropertyPerClassLimitEn ECS:
# ecs.yaml
services :
ObjectCalisthenicsSniffsFilesClassTraitAndInterfaceLengthSniff : ~
ObjectCalisthenicsSniffsFilesFunctionLengthSniff : ~
ObjectCalisthenicsSniffsMetricsMethodPerClassLimitSniff : ~
ObjectCalisthenicsSniffsMetricsPropertyPerClassLimitSniff : ~ En php_codesniffer:
<? xml version = " 1.0 " ?>
< ruleset name = " my-project " >
< rule ref = " ObjectCalisthenics.Files.ClassTraitAndInterfaceLength " >
< properties >
< property name = " maxLength " value = " 200 " />
</ properties >
</ rule >
< rule ref = " ObjectCalisthenics.Files.FunctionLength " >
< properties >
< property name = " maxLength " value = " 20 " />
</ properties >
</ rule >
< rule ref = " ObjectCalisthenics.Metrics.PropertyPerClassLimit " >
< properties >
< property name = " maxCount " value = " 10 " />
</ properties >
</ rule >
< rule ref = " ObjectCalisthenics.Metrics.MethodPerClassLimit " >
< properties >
< property name = " maxCount " value = " 10 " />
</ properties >
</ rule >
</ ruleset >En ECS:
# ecs.yaml
services :
ObjectCalisthenicsSniffsFilesClassTraitAndInterfaceLengthSniff :
maxLength : 200
ObjectCalisthenicsSniffsFilesFunctionLengthSniff :
maxLength : 20
ObjectCalisthenicsSniffsMetricsPropertyPerClassLimitSniff :
maxCount : 10
ObjectCalisthenicsSniffsMetricsMethodPerClassLimitSniff :
maxCount : 10Estas reglas están parcialmente relacionadas con el diseño impulsado por el dominio.
class ImmutableBankAccount
{
public $ currency = ' USD ' ; private $ amount ;
public function setAmount ( int $ amount )
{
$ this -> amount = $ amount ;
}
}?
class ImmutableBankAccount
{
private $ currency = ' USD ' ; private $ amount ;
public function withdrawAmount ( int $ withdrawnAmount )
{
$ this -> amount -= $ withdrawnAmount ;
}
}En php_codesniffer:
vendor/bin/phpcs ... --sniffs=ObjectCalisthenics.Classes.ForbiddenPublicProperty,ObjectCalisthenics.NamingConventions.NoSetterEn ECS:
# ecs.yaml
services :
ObjectCalisthenicsSniffsClassesForbiddenPublicPropertySniff : ~
ObjectCalisthenicsSniffsNamingConventionsNoSetterSniff : ~ En php_codesniffer:
<? xml version = " 1.0 " ?>
< ruleset name = " my-project " >
< rule ref = " ObjectCalisthenics.NamingConventions.NoSetter " >
< properties >
< property name = " allowedClasses " type = " array " value = " *DataObject " />
</ properties >
</ rule >
</ ruleset >En ECS:
# ecs.yaml
services :
ObjectCalisthenicsSniffsNamingConventionsNoSetterSniff :
allowedClasses :
- ' *DataObject 'Mientras usamos en la práctica, encontramos que estas reglas son demasiado estrictas, vagas o incluso molestas, en lugar de ayudar a escribir código más limpio y más pragmático. También están estrechamente relacionados con el diseño impulsado por el dominio.
3. Envuelva tipos y cadenas primitivas : ya que Php 7, puede usar sugerencias define(strict_types=1) y de tipo escalar. Para otros casos, por ejemplo, correo electrónico, puede lidiar con eso en su dominio a través de objetos de valor.
4. Use colecciones de primera clase : esta regla tiene sentido, pero es demasiado estricto para ser útil en la práctica. Incluso nuestro código no lo pasó en absoluto.
8. No use clases con más de dos variables de instancia : esto depende del dominio individual de cada proyecto. No tiene sentido hacer una regla para eso.
1 característica por relaciones públicas
Cada nueva característica debe estar cubierta por pruebas
Todas las pruebas y controles de estilo deben pasar
composer complete-checkEstaremos encantados de fusionar su función entonces.