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:
Complex classes like DBObject often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use DBObject, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 16 | class DBObject implements Interfaces\IDBObject |
||
| 17 | { |
||
| 18 | /* |
||
| 19 | * @const TABLE_NAME : Linked SQL Table |
||
| 20 | */ |
||
| 21 | const TABLE_NAME = ''; |
||
| 22 | |||
| 23 | /* |
||
| 24 | * @const TABLE_INDEX : Unique Id of the SQL Table |
||
| 25 | */ |
||
| 26 | const TABLE_INDEX = ''; |
||
| 27 | |||
| 28 | /** |
||
| 29 | * @const DB_CONFIG : Database configuration identifier |
||
| 30 | */ |
||
| 31 | const DB_CONFIG = ''; |
||
| 32 | |||
| 33 | /** |
||
| 34 | * @const RELATION_ONE_ONE : Relation one to one |
||
| 35 | */ |
||
| 36 | const RELATION_ONE_ONE = 1; |
||
| 37 | /** |
||
| 38 | * @const RELATION_ONE_MANY : Relation one to many |
||
| 39 | */ |
||
| 40 | const RELATION_ONE_MANY = 2; |
||
| 41 | /** |
||
| 42 | * @const RELATION_MANY_MANY : Relation many to many |
||
| 43 | */ |
||
| 44 | const RELATION_MANY_MANY = 3; |
||
| 45 | |||
| 46 | protected $dbVariables = []; |
||
| 47 | protected $dbValues = []; |
||
| 48 | |||
| 49 | protected $protectedVariables = []; |
||
| 50 | protected $protectedValues = []; |
||
| 51 | protected $loadedProtectedVariables = []; |
||
| 52 | |||
| 53 | protected $readOnlyVariables = []; |
||
| 54 | |||
| 55 | protected $relations = []; |
||
| 56 | protected $relationValues = []; |
||
| 57 | protected $loadedRelations = []; |
||
| 58 | |||
| 59 | protected $dbLink = false; |
||
| 60 | |||
| 61 | protected $validatorMessages = []; |
||
| 62 | |||
| 63 | |||
| 64 | public function __construct() |
||
| 68 | /** |
||
| 69 | * Magic getter |
||
| 70 | * |
||
| 71 | * Try to get object property according this order : |
||
| 72 | * <ul> |
||
| 73 | * <li>$dbVariable</li> |
||
| 74 | * <li>$protectedVariable (triggger call to accessToProtectedVariable() |
||
| 75 | * if not already loaded)</li> |
||
| 76 | * </ul> |
||
| 77 | * |
||
| 78 | * @param string $name Property name |
||
| 79 | * @return Mixed Property value |
||
| 80 | */ |
||
| 81 | public function __get($name) |
||
| 95 | |||
| 96 | /** |
||
| 97 | * Magic setter |
||
| 98 | * |
||
| 99 | * Set a property to defined value |
||
| 100 | * Assignment in this order : |
||
| 101 | * - $dbVariable |
||
| 102 | * - $protectedVariable |
||
| 103 | * </ul> |
||
| 104 | * @param string $name variable name |
||
| 105 | * @param mixed $value variable value |
||
| 106 | */ |
||
| 107 | public function __set($name, $value) |
||
| 119 | |||
| 120 | public function __isset($name) |
||
| 147 | |||
| 148 | /** |
||
| 149 | * __sleep magic method, permits an inherited DBObject class to be serialized |
||
| 150 | * @return Array of properties to serialize |
||
| 151 | */ |
||
| 152 | public function __sleep() |
||
| 165 | |||
| 166 | public function __wakeup() |
||
| 170 | |||
| 171 | private function getDBVariable($name) |
||
| 179 | |||
| 180 | /** |
||
| 181 | * Check if variable is from DB |
||
| 182 | * @param string $name variable name |
||
| 183 | * @return boolean |
||
| 184 | */ |
||
| 185 | public function isDBVariable($name) |
||
| 189 | |||
| 190 | private function getProtectedVariable($name) |
||
| 209 | |||
| 210 | private function getRelation($name) |
||
| 228 | |||
| 229 | /** |
||
| 230 | * Check if variable is predefined relation |
||
| 231 | * @param string $name variable name |
||
| 232 | * @return boolean |
||
| 233 | */ |
||
| 234 | protected function isRelation($name) |
||
| 238 | /** |
||
| 239 | * Define object relations |
||
| 240 | * |
||
| 241 | * @return object |
||
| 242 | */ |
||
| 243 | protected function setRelations() |
||
| 249 | |||
| 250 | /** |
||
| 251 | * Mark a protected variable as loaded |
||
| 252 | * @param string $name varialbe name |
||
| 253 | * @return void |
||
| 254 | */ |
||
| 255 | public function markProtectedVariableAsLoaded($name) |
||
| 261 | |||
| 262 | /** |
||
| 263 | * Mark a relation as loaded |
||
| 264 | * @param string $name varialbe name |
||
| 265 | * @return void |
||
| 266 | */ |
||
| 267 | protected function markRelationAsLoaded($name) |
||
| 273 | /** |
||
| 274 | * Check if a relation already have been loaded |
||
| 275 | * @param string $name Variable name |
||
| 276 | * @return boolean |
||
| 277 | */ |
||
| 278 | protected function isRelationLoaded($name) |
||
| 282 | |||
| 283 | protected function loadRelation($name) |
||
| 298 | |||
| 299 | private function loadRelationOneOne($name) |
||
| 308 | |||
| 309 | View Code Duplication | private function loadRelationOneMany($name) |
|
| 320 | |||
| 321 | View Code Duplication | private function loadRelationManyMany($name) |
|
| 332 | |||
| 333 | private function resetLoadedVariables() |
||
| 340 | |||
| 341 | /** |
||
| 342 | * Check if requested property exists |
||
| 343 | * |
||
| 344 | * Check in following order: |
||
| 345 | * <ul> |
||
| 346 | * <li>$dbVariables</li> |
||
| 347 | * <li>$protectedVariables</li> |
||
| 348 | * <li>$relations</li> |
||
| 349 | * <li>legacy property</li> |
||
| 350 | * </ul> |
||
| 351 | * @param string $property Property name |
||
| 352 | * @return boolean true if exists |
||
| 353 | */ |
||
| 354 | public function propertyExists($property) |
||
| 361 | |||
| 362 | /** |
||
| 363 | * Check if variable is a protected variable |
||
| 364 | * @param string $name variable name |
||
| 365 | * @return boolean |
||
| 366 | */ |
||
| 367 | public function isProtectedVariable($name) |
||
| 371 | |||
| 372 | |||
| 373 | |||
| 374 | /** |
||
| 375 | * Check if a protected variable already have been loaded |
||
| 376 | * @param string $name Variable name |
||
| 377 | * @return boolean |
||
| 378 | */ |
||
| 379 | protected function isProtectedVariableLoaded($name) |
||
| 383 | |||
| 384 | |||
| 385 | |||
| 386 | /** |
||
| 387 | * Load ORM from Database |
||
| 388 | * @param mixed $id SQL Table Unique id |
||
| 389 | * @return mixed Loaded object or false on failure |
||
| 390 | */ |
||
| 391 | public function load($id) |
||
| 410 | |||
| 411 | public function isLoaded() |
||
| 415 | |||
| 416 | public function loadOrFail($id) |
||
| 425 | |||
| 426 | public static function loadOrCreate($arg) |
||
| 433 | |||
| 434 | public static function loadOrInstanciate($arg) |
||
| 470 | |||
| 471 | public function loadFromSql($sql, $sql_params = []) |
||
| 488 | |||
| 489 | /** |
||
| 490 | * Construct an DBObject from an array |
||
| 491 | * @param array $data associative array |
||
| 492 | * @return DBObject Built DBObject |
||
| 493 | */ |
||
| 494 | public static function instanciate($data = []) |
||
| 507 | |||
| 508 | public static function create($data = []) |
||
| 515 | |||
| 516 | /** |
||
| 517 | * Delete record from SQL Table |
||
| 518 | * |
||
| 519 | * Delete record link to current object, according SQL Table unique id |
||
| 520 | * @return null |
||
| 521 | */ |
||
| 522 | public function delete() |
||
| 536 | |||
| 537 | /** |
||
| 538 | * Save current object into db |
||
| 539 | * |
||
| 540 | * Call INSERT or UPDATE if unique index is set |
||
| 541 | * @param boolean $forceInsert true to force insert instead of update |
||
| 542 | * @return null |
||
| 543 | */ |
||
| 544 | public function save($forceInsert = false) |
||
| 573 | |||
| 574 | /** |
||
| 575 | * UPDATE current object into database |
||
| 576 | * @return null |
||
| 577 | */ |
||
| 578 | private function update() |
||
| 601 | |||
| 602 | /** |
||
| 603 | * INSERT current object into database |
||
| 604 | * @access private |
||
| 605 | * @return null |
||
| 606 | */ |
||
| 607 | private function insert() |
||
| 630 | |||
| 631 | protected function connectDB() |
||
| 640 | |||
| 641 | |||
| 642 | protected function accessToProtectedVariable($name) |
||
| 646 | |||
| 647 | public function validate() |
||
| 651 | |||
| 652 | public function getValidatorMessages() |
||
| 656 | } |
||
| 657 |
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.