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 |
||
13 | class InstalledPackageFileSystemRepository implements InstalledPackageRepositoryInterface |
||
14 | { |
||
15 | |||
16 | /** |
||
17 | * @var string Path to state file |
||
18 | */ |
||
19 | protected $filePath; |
||
20 | |||
21 | /** |
||
22 | * @var array |
||
23 | */ |
||
24 | protected $packages = array(); |
||
25 | |||
26 | /** |
||
27 | * @var bool Flag to indicate if we have read the existing file |
||
28 | */ |
||
29 | protected $isLoaded = false; |
||
30 | |||
31 | /** |
||
32 | * @var bool Flag to indicate if we need to write once we are finished |
||
33 | */ |
||
34 | protected $hasChanges = false; |
||
35 | |||
36 | /** |
||
37 | * @var InstalledPackageDumper |
||
38 | */ |
||
39 | protected $dumper; |
||
40 | |||
41 | /** |
||
42 | * If file exists, check its readable |
||
43 | * Check in any case that it's writeable |
||
44 | * |
||
45 | * @param string $filePath |
||
46 | * @param InstalledPackageDumper $dumper |
||
47 | */ |
||
48 | 18 | public function __construct($filePath, InstalledPackageDumper $dumper) |
|
65 | |||
66 | /** |
||
67 | * @return array |
||
68 | */ |
||
69 | 8 | public function findAll() |
|
74 | |||
75 | /** |
||
76 | * @param string $packageName |
||
77 | * @return InstalledPackage |
||
78 | * @throws \Exception |
||
79 | */ |
||
80 | 13 | public function findByPackageName($packageName) |
|
81 | { |
||
82 | 13 | $this->load(); |
|
83 | 13 | foreach ($this->packages as $package) { |
|
84 | 8 | if ($package->getName() === $packageName) { |
|
85 | 8 | return $package; |
|
86 | } |
||
87 | } |
||
88 | |||
89 | 12 | throw new \Exception(sprintf('Package Installed Files for: "%s" not found', $packageName)); |
|
90 | } |
||
91 | |||
92 | /** |
||
93 | * If version specified, perform a strict check, |
||
94 | * which only returns true if repository has the package in the specified version |
||
95 | * |
||
96 | * @param string $packageName |
||
97 | * @param string $version |
||
98 | * @return bool |
||
99 | */ |
||
100 | 6 | public function has($packageName, $version = null) |
|
115 | |||
116 | /** |
||
117 | * @param InstalledPackage $package |
||
118 | * @throws \Exception |
||
119 | */ |
||
120 | 11 | public function add(InstalledPackage $package) |
|
121 | { |
||
122 | 11 | $this->load(); |
|
123 | |||
124 | try { |
||
125 | 11 | $this->findByPackageName($package->getName()); |
|
126 | 11 | } catch (\Exception $e) { |
|
127 | 11 | $this->packages[] = $package; |
|
128 | 11 | $this->hasChanges = true; |
|
129 | 11 | return; |
|
130 | } |
||
131 | |||
132 | 1 | throw new \Exception(sprintf('Package: "%s" is already installed', $package->getName())); |
|
133 | } |
||
134 | |||
135 | /** |
||
136 | * @param InstalledPackage $package |
||
137 | * @throws \Exception |
||
138 | */ |
||
139 | 7 | public function remove(InstalledPackage $package) |
|
140 | { |
||
141 | 7 | $this->load(); |
|
142 | |||
143 | 7 | foreach ($this->packages as $key => $installedPackage) { |
|
144 | 6 | if ($installedPackage->getName() === $package->getName()) { |
|
145 | 6 | array_splice($this->packages, $key, 1); |
|
146 | 6 | $this->hasChanges = true; |
|
147 | 6 | return; |
|
148 | } |
||
149 | } |
||
150 | |||
151 | 1 | throw new \Exception(sprintf('Package: "%s" not found', $package->getName())); |
|
152 | } |
||
153 | |||
154 | /** |
||
155 | * Load the Mappings File |
||
156 | * |
||
157 | * @return array |
||
158 | */ |
||
159 | 14 | private function load() |
|
171 | |||
172 | /** |
||
173 | * Do the write on destruct, we shouldn't have to do this manually |
||
174 | * - you don't call save after adding an entry to the database |
||
175 | * and at the same time, do want to perform IO for each package addition/removal. |
||
176 | * |
||
177 | * Also I don't like enforcing the consumer to call save and load. |
||
178 | */ |
||
179 | 11 | public function __destruct() |
|
190 | } |
||
191 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.