Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
1 | <?php |
||
46 | class AnnotationReader implements \ArrayAccess |
||
47 | { |
||
48 | 20 | static public function createDocBlockFactory(){ |
|
49 | 20 | $fqsenResolver = new FqsenResolver(); |
|
50 | 20 | $tagFactory = new StandardTagFactory($fqsenResolver,[]); |
|
51 | 20 | $descriptionFactory = new DescriptionFactory($tagFactory); |
|
52 | 20 | $tagFactory->addService($descriptionFactory); |
|
53 | 20 | $tagFactory->addService(new TypeResolver($fqsenResolver)); |
|
54 | 20 | $docBlockFactory = new DocBlockFactory($descriptionFactory, $tagFactory); |
|
55 | 20 | return $docBlockFactory; |
|
56 | } |
||
57 | |||
58 | 20 | static public function assertAnnotationEnabled() |
|
63 | /** |
||
64 | * load from class with local cache |
||
65 | * TODO 增加 filter 能力 |
||
66 | * @param string $className |
||
67 | * @param Cache $localCache |
||
68 | * @return object |
||
69 | */ |
||
70 | 20 | static public function read($className, Cache $localCache = null) |
|
94 | /** |
||
95 | * @param $className |
||
96 | * @return self |
||
97 | */ |
||
98 | 20 | static function readWithoutCache($className) |
|
99 | { |
||
100 | 20 | $reader = new self(); |
|
101 | |||
102 | 20 | $rfl = new \ReflectionClass($className); |
|
103 | 20 | $reader->class = self::readAnnotationBlock($rfl->getDocComment()); |
|
104 | 20 | $reader->class->name = $className; |
|
105 | |||
106 | //method annotations |
||
107 | 20 | foreach ($rfl->getMethods() as $i){ |
|
108 | 16 | $block = self::readAnnotationBlock($i->getDocComment()); |
|
109 | 16 | $block->name = $i->getName(); |
|
110 | 16 | $reader->methods[$i->getName()]=$block; |
|
111 | 20 | } |
|
112 | //property annotations |
||
113 | 20 | View Code Duplication | foreach ($rfl->getProperties() as $i){ |
114 | 19 | if ($i->isStatic()) { |
|
115 | 15 | continue; |
|
116 | } |
||
117 | 19 | $block = self::readAnnotationBlock($i->getDocComment()); |
|
118 | 19 | $block->name = $i->getName(); |
|
119 | 19 | $reader->properties[$i->getName()]=$block; |
|
120 | 20 | } |
|
121 | 20 | while ($rfl = $rfl->getParentClass()) { |
|
122 | 1 | View Code Duplication | foreach ($rfl->getProperties(\ReflectionProperty::IS_PRIVATE) as $i) { |
123 | 1 | if ($i->isStatic()) { |
|
124 | continue; |
||
125 | } |
||
126 | 1 | $block = self::readAnnotationBlock($i->getDocComment()); |
|
127 | 1 | $block->name = $i->getName(); |
|
128 | 1 | $reader->properties[$i->getName()]=$block; |
|
129 | 1 | } |
|
130 | 1 | } |
|
131 | 20 | return $reader; |
|
132 | } |
||
133 | |||
134 | 20 | static private function readAnnotationBlock($doc) |
|
168 | |||
169 | /** |
||
170 | * @var AnnotationBlock |
||
171 | */ |
||
172 | public $class; |
||
173 | /** |
||
174 | * @var AnnotationBlock[] |
||
175 | */ |
||
176 | |||
177 | public $methods=[]; |
||
178 | /** |
||
179 | * @var AnnotationBlock[] |
||
180 | */ |
||
181 | public $properties=[]; |
||
182 | |||
183 | 20 | public function offsetExists($offset) |
|
187 | |||
188 | 20 | public function offsetGet($offset) |
|
192 | |||
193 | public function offsetSet($offset, $value) |
||
197 | |||
198 | public function offsetUnset($offset) |
||
202 | } |
Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.