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 Batiment 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 Batiment, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
9 | class Batiment { |
||
10 | //pour quand on recup un batiment |
||
11 | private $nom_batiment; |
||
12 | private $nom_batiment_sql; |
||
13 | private $niveau_batiment; |
||
14 | private $temps_construction; |
||
15 | private $ressource_construire; |
||
16 | private $id_batiment; |
||
17 | |||
18 | private $info_batiment; |
||
19 | private $info_batiment_next; |
||
20 | |||
21 | //pour les constructions |
||
22 | private $nom_batiment_construction; |
||
23 | private $date_fin_construction; |
||
24 | private $niveau_batiment_construction; |
||
25 | |||
26 | //-------------------------- BUILDER ----------------------------------------------------------------------------// |
||
27 | public function __construct() { |
||
30 | //-------------------------- END BUILDER ----------------------------------------------------------------------------// |
||
31 | |||
32 | |||
33 | |||
34 | //-------------------------- GETTER ----------------------------------------------------------------------------// |
||
35 | public function getNomBatiment() { |
||
56 | |||
57 | public function getNomBatimentConstruction() { |
||
66 | |||
67 | /** |
||
68 | * @param $nom_batiment |
||
69 | * @return int |
||
70 | * pour recuperer le niveau d'un batiment |
||
71 | */ |
||
72 | public function getNiveauBatiment($nom_batiment_sql, $id_base = null) { |
||
99 | |||
100 | /** |
||
101 | * @param $ressource |
||
102 | * @return int |
||
103 | * recuperation de la production de chaque ressource en fonction du lvl des batiments |
||
104 | */ |
||
105 | public function getProduction($ressource, $id_base = null) { |
||
134 | |||
135 | /** |
||
136 | * @return int |
||
137 | * fonction qui retourne le stockage de l'entrepot |
||
138 | */ |
||
139 | public function getStockageEntrepot($id_base = null) { |
||
161 | |||
162 | /** |
||
163 | * permet de récupérer toutes les infos d'un batiment dans la popup |
||
164 | * @param $nom_batiment |
||
165 | */ |
||
166 | public function getUnBatiment($nom_batiment) { |
||
167 | $dbc = App::getDb(); |
||
168 | $dbc1 = Bataille::getDb(); |
||
169 | |||
170 | $construction = $this->getTestBatimentConstruction($nom_batiment); |
||
171 | |||
172 | //recuperation des infos du batiment |
||
173 | $query = $dbc->select() |
||
174 | ->from("_bataille_batiment") |
||
175 | ->where("nom_batiment", "=", $construction[0], "AND") |
||
176 | ->where("ID_base", "=", Bataille::getIdBase()) |
||
177 | ->get(); |
||
178 | |||
179 | if ((is_array($query)) && (count($query) > 0)) { |
||
180 | foreach ($query as $obj) { |
||
181 | $this->nom_batiment_sql = $obj->nom_batiment_sql; |
||
182 | $this->niveau_batiment = $obj->niveau; |
||
183 | $this->id_batiment = $obj->ID_batiment; |
||
184 | } |
||
185 | |||
186 | if (($construction[1] == true) && ($this->niveau_batiment > 1)) { |
||
187 | $this->niveau_batiment = $this->niveau_batiment + 1; |
||
188 | } |
||
189 | |||
190 | $max_level = $this->getInfoUpgradeBatiment(); |
||
191 | } |
||
192 | else { |
||
193 | $query = $dbc1->select("nom_table") |
||
194 | ->from("liste_batiment") |
||
195 | ->where("nom", "=", $nom_batiment) |
||
196 | ->get(); |
||
197 | |||
198 | if ((is_array($query)) && (count($query) > 0)) { |
||
199 | foreach ($query as $obj) { |
||
200 | $this->nom_batiment_sql = $obj->nom_table; |
||
201 | } |
||
202 | } |
||
203 | |||
204 | $this->niveau_batiment = 0; |
||
205 | $this->getInfoUpgradeBatiment(); |
||
206 | $max_level = 0; |
||
207 | } |
||
208 | |||
209 | //permet de savoir si le batiment produit bien des ressoures |
||
210 | $batiment_production = []; |
||
211 | |||
212 | $query = $dbc1->select("nom")->from("liste_batiment")->where("type", "=", "ressource")->get(); |
||
213 | |||
214 | if ((is_array($query)) && (count($query) > 0)) { |
||
215 | foreach ($query as $obj) { |
||
216 | $batiment_production[] = $obj->nom; |
||
217 | } |
||
218 | } |
||
219 | |||
220 | Bataille::setValues([ |
||
221 | "nom_batiment_sql" => $this->nom_batiment_sql, |
||
222 | "niveau_batiment" => $this->niveau_batiment, |
||
223 | "id_batiment" => $this->niveau_batiment, |
||
224 | "max_level" => $max_level, |
||
225 | "batiment_production" => $batiment_production |
||
226 | ]); |
||
227 | |||
228 | return $max_level; |
||
229 | } |
||
230 | |||
231 | /** |
||
232 | * pour récupérer la construction en cours dans la base |
||
233 | */ |
||
234 | public function getConstruction() { |
||
270 | |||
271 | /** |
||
272 | * pour récupérer la liste des batiments qu'il est possible de construire |
||
273 | */ |
||
274 | public function getBatimentAConstruire() { |
||
397 | |||
398 | /** |
||
399 | * @param $case_depart |
||
400 | * @param $nom_batiment |
||
401 | * @param $nom_batiment_sql |
||
402 | * @return bool |
||
403 | * fonction qui test si un il y a la place de construire un batiment en fonction de sa case ou il a été laché en x et y |
||
404 | * et en fonction de sa taille et du positionnement des autres batiments |
||
405 | */ |
||
406 | public function getEmplacementConstructionLibre($case_depart, $nom_batiment, $nom_batiment_sql) { |
||
459 | |||
460 | /** |
||
461 | * @param $nom_batiment_sql |
||
462 | * @return array |
||
463 | * fonction qui renvoi un tableau contenant la taille et hauteur d'un batiment en |
||
464 | * fonction de son nom |
||
465 | */ |
||
466 | View Code Duplication | public function getTailleBatiment($nom_batiment_sql) { |
|
481 | |||
482 | /** |
||
483 | * @param $nom_batiment_sql |
||
484 | * @param $niveau |
||
485 | * @return array |
||
486 | * recuperation des ressources nécéssaire pour construire le batiment |
||
487 | */ |
||
488 | private function getRessourceConstruireBatiment($nom_batiment_sql, $niveau) { |
||
514 | |||
515 | /** |
||
516 | * fonction qui renvoi un tableau avec le nom du batiment sans (en construction) |
||
517 | * + true pour dire que le batiment est en construction |
||
518 | * |
||
519 | * @param $nom_batiment |
||
520 | * @return array |
||
521 | */ |
||
522 | private function getTestBatimentConstruction($nom_batiment) { |
||
529 | |||
530 | /** |
||
531 | * fonction qui renvoi les informations pour augmenter le niveau d'un batiment |
||
532 | * @return int |
||
533 | */ |
||
534 | private function getInfoUpgradeBatiment() { |
||
595 | //-------------------------- END GETTER ----------------------------------------------------------------------------// |
||
596 | |||
597 | |||
598 | |||
599 | //-------------------------- SETTER ----------------------------------------------------------------------------// |
||
600 | /** |
||
601 | * fonction qui initialise la construction d'un batiment |
||
602 | * @param $nom_batiment |
||
603 | * @param $nom_batiment_sql |
||
604 | */ |
||
605 | public function setCommencerConstruireBatiment($nom_batiment, $nom_batiment_sql, $posx, $posy) { |
||
606 | $dbc = App::getDb(); |
||
607 | $dbc1 = Bataille::getDb(); |
||
608 | |||
609 | if ($this->getConstruction() == 0) { |
||
610 | $un_batiment = $this->getUnBatiment($nom_batiment); |
||
611 | |||
612 | //on test si assez de ressrouce pour construire le batiment |
||
613 | if ($un_batiment == 0) { |
||
614 | $ressource = $this->getRessourceConstruireBatiment($nom_batiment_sql, 0); |
||
615 | $this->nom_batiment_sql = $nom_batiment_sql; |
||
616 | $this->niveau_batiment = 0; |
||
617 | } |
||
618 | else { |
||
619 | $ressource = $this->getRessourceConstruireBatiment($this->nom_batiment_sql, $this->niveau_batiment); |
||
620 | } |
||
621 | |||
622 | //si pas assez de ressource |
||
623 | if (($ressource["eau"]["class"] || $ressource["electricite"]["class"] ||$ressource["fer"]["class"] ||$ressource["fuel"]["class"]) == "rouge") { |
||
624 | FlashMessage::setFlash("Pas assez de ressources pour construire ce batiment"); |
||
625 | return false; |
||
626 | } |
||
627 | else { |
||
628 | //recuperation du temps de construction |
||
629 | $query = $dbc1->select("ressource_construire") |
||
630 | ->select("temps_construction") |
||
631 | ->from($this->nom_batiment_sql) |
||
632 | ->where("ID_".$this->nom_batiment_sql, "=", $this->niveau_batiment+1) |
||
633 | ->get(); |
||
634 | |||
635 | foreach ($query as $obj) { |
||
636 | $temps_construction = round($obj->temps_construction-($obj->temps_construction*Bataille::getBatiment()->getNiveauBatiment("centre_commandement")/100)); |
||
637 | $ressource_construction = explode(", ", $obj->ressource_construire); |
||
638 | } |
||
639 | |||
640 | //on insere la construction dans la table batiment si new batiment |
||
641 | if ($un_batiment == 0) { |
||
642 | $dbc->insert("niveau", $this->niveau_batiment+1) |
||
643 | ->insert("nom_batiment", $nom_batiment) |
||
644 | ->insert("nom_batiment_sql", $this->nom_batiment_sql) |
||
645 | ->insert("posx", intval($posx)) |
||
646 | ->insert("posy", intval($posy)) |
||
647 | ->insert("construction", 1) |
||
648 | ->insert("ID_base", Bataille::getIdBase()) |
||
649 | ->into("_bataille_batiment") |
||
650 | ->set(); |
||
651 | |||
652 | $this->id_batiment = $dbc->lastInsertId(); |
||
653 | } |
||
654 | else { |
||
655 | $dbc->update("niveau", $this->niveau_batiment+1) |
||
656 | ->update("construction", 1) |
||
657 | ->from("_bataille_batiment") |
||
658 | ->where("ID_batiment", "=", $this->id_batiment, "AND") |
||
659 | ->where("ID_base", "=", Bataille::getIdBase()) |
||
660 | ->set(); |
||
661 | } |
||
662 | |||
663 | |||
664 | //on initialise la construction |
||
665 | //recuperation de la date en seconde |
||
666 | $today = Bataille::getToday(); |
||
667 | |||
668 | //date de la fin de la construction en seconde |
||
669 | $fin_construction = $today+$temps_construction; |
||
670 | |||
671 | $dbc->insert("date_fin", $fin_construction) |
||
672 | ->insert("ID_base", Bataille::getIdBase()) |
||
673 | ->insert("ID_batiment", $this->id_batiment) |
||
674 | ->into("_bataille_construction") |
||
675 | ->set(); |
||
676 | |||
677 | //on retire les ressources de la base |
||
678 | Bataille::getRessource()->setUpdateRessource($ressource_construction[2], $ressource_construction[3], $ressource_construction[0], $ressource_construction[1], 0, "-"); |
||
679 | } |
||
680 | } |
||
681 | else { |
||
682 | FlashMessage::setFlash("Un batiment est déjà en construction, vous ne pouvez pas en construire un autre !"); |
||
683 | return false; |
||
684 | } |
||
685 | } |
||
686 | |||
687 | /** |
||
688 | * fonction qui termine la construction d'un batiment |
||
689 | * @param $id_batiment |
||
690 | */ |
||
691 | private function setTerminerConstruction($id_batiment) { |
||
711 | //-------------------------- END SETTER ----------------------------------------------------------------------------// |
||
712 | } |
If you define a variable conditionally, it can happen that it is not defined for all execution paths.
Let’s take a look at an example:
In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.
Available Fixes
Check for existence of the variable explicitly:
Define a default value for the variable:
Add a value for the missing path: