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 Base 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 Base, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 4 | abstract class Base { |
||
| 5 | /** |
||
| 6 | * Property dictionary for all tables |
||
| 7 | */ |
||
| 8 | private static $properties = array(); |
||
| 9 | |||
| 10 | private $is_new = true; |
||
| 11 | |||
| 12 | /** |
||
| 13 | * Contains property values |
||
| 14 | */ |
||
| 15 | private $data = array(); |
||
| 16 | |||
| 17 | public function __set( $name, $value ) { |
||
| 24 | |||
| 25 | private function set_property( $name, $value ) { |
||
| 28 | |||
| 29 | public function __get( $name ) { |
||
| 38 | |||
| 39 | private function get_property( $name ) { |
||
| 46 | |||
| 47 | private static function unserialize_property($property) { |
||
| 56 | |||
| 57 | /** |
||
| 58 | * Retrieves the database table name. |
||
| 59 | * |
||
| 60 | * The name is derived from the namespace an class name. Additionally, it |
||
| 61 | * is prefixed with the global WordPress database table prefix. |
||
| 62 | * @todo cache |
||
| 63 | * |
||
| 64 | * @return string database table name |
||
| 65 | */ |
||
| 66 | public static function table_name() { |
||
| 72 | |||
| 73 | /** |
||
| 74 | * Define a property with name and type. |
||
| 75 | * |
||
| 76 | * Currently only supports basics. |
||
| 77 | * @todo enable additional options like NOT NULL, DEFAULT etc. |
||
| 78 | * |
||
| 79 | * @param string $name Name of the property / column |
||
| 80 | * @param string $type mySQL column type |
||
| 81 | */ |
||
| 82 | public static function property( $name, $type, $args = array() ) { |
||
| 104 | |||
| 105 | /** |
||
| 106 | * Return a list of property dictionaries. |
||
| 107 | * |
||
| 108 | * @return array property list |
||
| 109 | */ |
||
| 110 | private static function properties() { |
||
| 119 | |||
| 120 | /** |
||
| 121 | * Does the given property exist? |
||
| 122 | * |
||
| 123 | * @param string $name name of the property to test |
||
| 124 | * @return bool True if the property exists, else false. |
||
| 125 | */ |
||
| 126 | public static function has_property( $name ) { |
||
| 129 | |||
| 130 | /** |
||
| 131 | * Return a list of property names. |
||
| 132 | * |
||
| 133 | * @return array property names |
||
| 134 | */ |
||
| 135 | public static function property_names() { |
||
| 138 | |||
| 139 | /** |
||
| 140 | * Does the table have any entries? |
||
| 141 | * |
||
| 142 | * @return bool True if there is at least one entry, else false. |
||
| 143 | */ |
||
| 144 | public static function has_entries() { |
||
| 147 | |||
| 148 | /** |
||
| 149 | * Return number of rows in the table. |
||
| 150 | * |
||
| 151 | * @return int number of rows |
||
| 152 | */ |
||
| 153 | public static function count() { |
||
| 159 | |||
| 160 | public static function find_by_id( $id ) { |
||
| 179 | |||
| 180 | public static function find_all_by_property( $property, $value ) { |
||
| 205 | |||
| 206 | View Code Duplication | public static function find_one_by_property( $property, $value ) { |
|
| 227 | |||
| 228 | View Code Duplication | public static function find_all_by_where( $where ) { |
|
| 253 | |||
| 254 | View Code Duplication | public static function find_one_by_where( $where ) { |
|
| 275 | /** |
||
| 276 | * Retrieve all entries from the table. |
||
| 277 | * |
||
| 278 | * @param string $sql_suffix optional SQL, appended after FROM clause |
||
| 279 | * @return array list of model objects |
||
| 280 | */ |
||
| 281 | View Code Duplication | public static function all( $sql_suffix = '' ) { |
|
| 300 | |||
| 301 | /** |
||
| 302 | * True if not yet saved to database. Else false. |
||
| 303 | */ |
||
| 304 | public function is_new() { |
||
| 307 | |||
| 308 | public function flag_as_not_new() { |
||
| 311 | |||
| 312 | /** |
||
| 313 | * Rails-ish update_attributes for easy form handling. |
||
| 314 | * |
||
| 315 | * Takes an array of form values and takes care of serializing it. |
||
| 316 | * |
||
| 317 | * @param array $attributes |
||
| 318 | * @return bool |
||
| 319 | */ |
||
| 320 | public function update_attributes( $attributes ) { |
||
| 355 | |||
| 356 | /** |
||
| 357 | * Update and save a single attribute. |
||
| 358 | * |
||
| 359 | * @param string $attribute attribute name |
||
| 360 | * @param mixed $value |
||
| 361 | * @return (bool) query success |
||
| 362 | */ |
||
| 363 | public function update_attribute($attribute, $value) { |
||
| 378 | |||
| 379 | /** |
||
| 380 | * Saves changes to database. |
||
| 381 | * |
||
| 382 | * @todo use wpdb::insert() |
||
| 383 | */ |
||
| 384 | public function save() { |
||
| 422 | |||
| 423 | /** |
||
| 424 | * Sets default values. |
||
| 425 | * |
||
| 426 | * @return array |
||
| 427 | */ |
||
| 428 | private function set_defaults() { |
||
| 441 | |||
| 442 | /** |
||
| 443 | * Return default values for properties. |
||
| 444 | * |
||
| 445 | * Can be overridden by inheriting model classes. |
||
| 446 | * |
||
| 447 | * @return array |
||
| 448 | */ |
||
| 449 | public function default_values() { |
||
| 452 | |||
| 453 | public function delete() { |
||
| 467 | |||
| 468 | private function property_name_to_sql_update_statement( $p ) { |
||
| 477 | |||
| 478 | private function property_name_to_sql_value( $p ) { |
||
| 487 | |||
| 488 | /** |
||
| 489 | * Create database table based on defined properties. |
||
| 490 | * |
||
| 491 | * Automatically includes an id column as auto incrementing primary key. |
||
| 492 | * @todo allow model changes |
||
| 493 | */ |
||
| 494 | public static function build() { |
||
| 512 | |||
| 513 | /** |
||
| 514 | * Convention based index generation. |
||
| 515 | * |
||
| 516 | * Creates default indices for all columns matching both: |
||
| 517 | * - equals "id" or contains "_id" |
||
| 518 | * - doesn't have an index yet |
||
| 519 | */ |
||
| 520 | public static function build_indices() { |
||
| 537 | |||
| 538 | /** |
||
| 539 | * Model identifier. |
||
| 540 | */ |
||
| 541 | public static function name() { |
||
| 553 | } |
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.
Both the
$myVarassignment in line 1 and the$higherassignment in line 2 are dead. The first because$myVaris never used and the second because$higheris always overwritten for every possible time line.