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 |
||
43 | class Entities |
||
44 | { |
||
45 | private $wsClient = null; |
||
46 | |||
47 | /** |
||
48 | * Class constructor |
||
49 | * @param string $wsClient Parent WSClient instance |
||
50 | */ |
||
51 | public function __construct($wsClient) |
||
55 | |||
56 | /** |
||
57 | * Retrieves an entity by ID |
||
58 | * @param string $moduleName The name of the module / entity type |
||
59 | * @param string $entityID The ID of the entity to retrieve |
||
60 | * @return array $select The list of fields to select (defaults to SQL-like '*' - all the fields) |
||
61 | * @return boolean Entity data |
||
62 | */ |
||
63 | public function findOneByID($moduleName, $entityID, array $select = []) |
||
67 | |||
68 | /** |
||
69 | * Retrieve the entity matching a list of constraints |
||
70 | * @param string $moduleName The name of the module / entity type |
||
71 | * @param array $params Data used to find a matching entry |
||
72 | * @return array $select The list of fields to select (defaults to SQL-like '*' - all the fields) |
||
73 | * @return integer The matching record |
||
74 | */ |
||
75 | public function findOne($moduleName, array $params, array $select = []) |
||
83 | |||
84 | /** |
||
85 | * Retrieves the ID of the entity matching a list of constraints + prepends '<module_id>x' string to it |
||
86 | * @param string $moduleName The name of the module / entity type |
||
87 | * @param array $params Data used to find a matching entry |
||
88 | * @return integer Type ID (a numeric ID + '<module_id>x') |
||
89 | */ |
||
90 | public function getID($moduleName, array $params) |
||
98 | |||
99 | /** |
||
100 | * Retrieve a numeric ID of the entity matching a list of constraints |
||
101 | * @param string $moduleName The name of the module / entity type |
||
102 | * @param array $params Data used to find a matching entry |
||
103 | * @return integer Numeric ID |
||
104 | */ |
||
105 | public function getNumericID($moduleName, array $params) |
||
113 | |||
114 | /** |
||
115 | * Creates an entity for the giving module |
||
116 | * @param string $moduleName Name of the module / entity type for which the entry has to be created |
||
117 | * @param array $params Entity data |
||
118 | * @return array Entity creation results |
||
119 | */ |
||
120 | public function createOne($moduleName, array $params) |
||
138 | |||
139 | /** |
||
140 | * Updates an entity |
||
141 | * @param string $moduleName The name of the module / entity type |
||
142 | * @param array $params Entity data |
||
143 | * @return array Entity update result |
||
144 | */ |
||
145 | public function updateOne($moduleName, $entityID, array $params) |
||
179 | |||
180 | /** |
||
181 | * Provides entity removal functionality |
||
182 | * @param string $moduleName The name of the module / entity type |
||
183 | * @param string $entityID The ID of the entity to delete |
||
184 | * @return array Removal status object |
||
185 | */ |
||
186 | public function deleteOne($moduleName, $entityID) |
||
192 | |||
193 | /** |
||
194 | * Retrieves multiple records using module name and a set of constraints |
||
195 | * @param string $moduleName The name of the module / entity type |
||
196 | * @param array $params Data used to find matching entries |
||
197 | * @return array $select The list of fields to select (defaults to SQL-like '*' - all the fields) |
||
198 | * @return integer $limit limit the list of entries to N records (acts like LIMIT in SQL) |
||
199 | * @return bool|array The array containing matching entries or false if nothing was found |
||
200 | */ |
||
201 | public function findMany($moduleName, array $params, array $select = [], $limit = 0) |
||
218 | |||
219 | /** |
||
220 | * Sync will return a sync result object containing details of changes after modifiedTime |
||
221 | * @param integer [$modifiedTime = null] The date of the first change |
||
222 | * @param string [$moduleName = null] The name of the module / entity type |
||
223 | * @return array Sync result object |
||
224 | */ |
||
225 | public function sync($modifiedTime = null, $moduleName = null) |
||
241 | |||
242 | /** |
||
243 | * Checks if if params holds valid entity data/search constraints, otherwise returns false |
||
244 | * @access public |
||
245 | * @static |
||
246 | * @param array $params Array holding entity data/search constraints |
||
247 | * @return boolean Returns true if params holds valid entity data/search constraints, otherwise returns false |
||
248 | */ |
||
249 | private static function checkParams(array $params, $paramsPurpose) |
||
259 | |||
260 | /** |
||
261 | * Builds the query using the supplied parameters |
||
262 | * @access public |
||
263 | * @static |
||
264 | * @param string $moduleName The name of the module / entity type |
||
265 | * @param array $params Data used to find matching entries |
||
266 | * @return array $select The list of fields to select (defaults to SQL-like '*' - all the fields) |
||
267 | * @return int $limit limit the list of entries to N records (acts like LIMIT in SQL) |
||
268 | * @return string The query build out of the supplied parameters |
||
269 | */ |
||
270 | public static function getQueryString($moduleName, array $params, array $select = [], $limit = 0) |
||
285 | } |
||
286 |
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.
Let’s take a look at an example:
Our function
my_function
expects aPost
object, and outputs the author of the post. The base classPost
returns a simple string and outputting a simple string will work just fine. However, the child classBlogPost
which is a sub-type ofPost
instead decided to return anobject
, and is therefore violating the SOLID principles. If aBlogPost
were passed tomy_function
, PHP would not complain, but ultimately fail when executing thestrtoupper
call in its body.