
8. Ciocan de aur
Un ciocan de aur este un anti-model definit de încrederea că o anumită soluție este aplicabilă universal. Exemple:-
După ce a întâmpinat o problemă și a găsit un model pentru soluția perfectă, un programator încearcă să lipească acest tipar peste tot, aplicând-l la proiectele actuale și viitoare, în loc să caute soluțiile adecvate pentru cazuri specifice.
-
Unii dezvoltatori și-au creat odată propria variantă a unui cache pentru o situație specifică (pentru că nimic altceva nu era potrivit). Mai târziu, la următorul proiect care nu a implicat nicio logică de cache specială, au folosit din nou varianta lor în loc să folosească biblioteci gata făcute (de exemplu, Ehcache). Rezultatul a fost o grămadă de bug-uri și incompatibilități, precum și mult timp pierdut și nervi prăjiți.
Oricine se poate îndrăgosti de acest anti-model. Dacă sunteți începător, este posibil să nu aveți cunoștințe despre modelele de design. Acest lucru vă poate determina să încercați să rezolvați toate problemele într-un singur mod pe care l-ați stăpânit. Dacă vorbim de profesioniști, atunci numim această deformare profesională sau nerdview. Aveți propriile modele de design preferate și, în loc să îl folosiți pe cel potrivit, îl folosiți pe cel preferat, presupunând că o potrivire bună în trecut garantează același rezultat în viitor.
Această capcană poate produce rezultate foarte triste - de la o implementare proastă, instabilă și dificil de menținut până la un eșec complet al proiectului. Așa cum nu există o singură pastilă pentru toate bolile, nu există un singur model de design pentru toate ocaziile.
9. Optimizare prematură
Optimizarea prematură este un anti-model al cărui nume vorbește de la sine.10. Cod spaghete
Codul spaghetti este un anti-model definit de cod care este prost structurat, confuz și greu de înțeles, care conține tot felul de ramificații, cum ar fi excepțiile de împachetare, condiții și bucle. Anterior, operatorul goto era principalul aliat al acestui anti-pattern. Declarațiile Goto nu mai sunt folosite cu adevărat, ceea ce elimină din fericire o serie de dificultăți și probleme asociate.
public boolean someDifficultMethod(List<String> XMLAttrList) {
...
int prefix = stringPool.getPrefixForQName(elementType);
int elementURI;
try {
if (prefix == -1) {
...
if (elementURI != -1) {
stringPool.setURIForQName(...);
}
} else {
...
if (elementURI == -1) {
...
}
}
} catch (Exception e) {
return false;
}
if (attrIndex != -1) {
int index = attrList.getFirstAttr(attrIndex);
while (index != -1) {
int attName = attrList.getAttrName(index);
if (!stringPool.equalNames(...)){
...
if (attPrefix != namespacesPrefix) {
if (attPrefix == -1) {
...
} else {
if (uri == -1) {
...
}
stringPool.setURIForQName(attName, uri);
...
}
if (elementDepth >= 0) {
...
}
elementDepth++;
if (elementDepth == fElementTypeStack.length) {
...
}
...
return contentSpecType == fCHILDRENSymbol;
}
}
}
}
}
Arată îngrozitor, nu-i așa? Din păcate, acesta este cel mai comun anti-model :( Nici măcar persoana care scrie un astfel de cod nu va putea să-l înțeleagă în viitor. Alți dezvoltatori care văd codul se vor gândi: „Ei bine, dacă funcționează, atunci bine - este mai bine să nu o atingeți". Adesea, o metodă este inițial simplă și foarte transparentă, dar pe măsură ce se adaugă noi cerințe, metoda este încărcată treptat cu tot mai multe enunțuri condiționate, transformând-o într-o monstruozitate ca aceasta. Dacă o astfel de metodă apare, trebuie să-l refactorizezi fie complet, fie cel puțin părțile cele mai confuze. De obicei, atunci când programați un proiect, timpul este alocat pentru refactorizare, de exemplu, 30% din timpul de sprint este pentru refactorizare și teste. Desigur, acest lucru presupune că nu există nicio grabă (dar când se întâmplă asta vreodată).aici .
11. Numere magice
Numerele magice este un anti-model în care într-un program sunt folosite tot felul de constante fără nicio explicație a scopului sau semnificației lor. Adică sunt, în general, prost numite sau în cazuri extreme, nu există niciun comentariu care să explice care sunt comentariile sau de ce. La fel ca codul de spaghete, acesta este unul dintre cele mai comune anti-modele. Cineva care nu a scris codul poate avea sau nu idee despre numerele magice sau despre modul în care acestea funcționează (și în timp, autorul însuși nu le va putea explica). Ca rezultat, schimbarea sau eliminarea unui număr face ca codul să nu mai funcționeze împreună. De exemplu, 36 și 73. Pentru a combate acest anti-pattern, recomand o revizuire a codului. Codul dvs. trebuie să fie examinat de dezvoltatori care nu sunt implicați în secțiunile relevante ale codului. Ochii lor vor fi proaspeți și vor avea întrebări: ce este asta și de ce ai făcut asta? Și, desigur, trebuie să folosiți nume explicative sau să lăsați comentarii.12. Programare copiere și lipire
Programarea prin copiere și inserare este un anti-model în care codul altcuiva este copiat și lipit fără gânduri, ceea ce poate duce la efecte secundare neprevăzute. De exemplu, metode de copiere și lipire cu calcule matematice sau algoritmi complecși pe care nu îi înțelegem pe deplin. Poate funcționa pentru cazul nostru particular, dar în alte circumstanțe ar putea duce la probleme. Să presupunem că am nevoie de o metodă pentru a determina numărul maxim dintr-o matrice. Scotocind pe internet, am găsit această soluție:
public static int max(int[] array) {
int max = 0;
for(int i = 0; i < array.length; i++) {
if (Math.abs(array[i]) > max){
max = array[i];
}
}
return max;
}
Obținem o matrice cu numerele 3, 6, 1, 4 și 2, iar metoda returnează 6. Grozav, să o păstrăm! Dar mai târziu obținem o matrice formată din 2,5, -7, 2 și 3, iar apoi rezultatul nostru este -7. Și acest rezultat nu este bun. Problema aici este că Math.abs() returnează valoarea absolută. Ignorarea acestui lucru duce la dezastru, dar numai în anumite situații. Fără o înțelegere aprofundată a soluției, există multe cazuri pe care nu le veți putea verifica. Codul copiat poate depăși, de asemenea, structura internă a aplicației, atât din punct de vedere stilistic, cât și la un nivel mai fundamental, arhitectural. Un astfel de cod va fi mai dificil de citit și întreținut. Și, desigur, nu trebuie să uităm că copiarea directă a codului altcuiva este un tip special de plagiat.
13. Reinventarea roții
Reinventarea roții este un anti-model, cunoscut și sub numele de reinventarea roții pătrate. În esență, acest șablon este opusul anti-modelului de tip copy-and-paste considerat mai sus. În acest anti-pattern, dezvoltatorul implementează propria soluție pentru o problemă pentru care există deja soluții. Uneori, aceste soluții existente sunt mai bune decât ceea ce inventează programatorul. Cel mai adesea, acest lucru duce doar la timp pierdut și la o productivitate mai scăzută: programatorul poate să nu găsească deloc o soluție sau poate găsi o soluție care este departe de cea mai bună. Acestea fiind spuse, nu putem exclude posibilitatea de a crea o soluție independentă, deoarece a face asta este un drum direct către programare copy-and-paste. Programatorul trebuie să fie ghidat de sarcinile de programare specifice care apar pentru a le rezolva în mod competent, fie prin utilizarea de soluții gata făcute, fie prin crearea de soluții personalizate. Foarte des, motivul folosirii acestui anti-model este pur și simplu graba. Rezultatul este o analiză superficială a (căutării) soluțiilor gata făcute. Reinventarea roții pătrate este un caz în care anti-modelul luat în considerare are un rezultat negativ. Adică, proiectul necesită o soluție personalizată, iar dezvoltatorul o creează, dar prost. În același timp, o opțiune bună există deja și alții o folosesc cu succes. Concluzia: se pierde o cantitate imensă de timp. În primul rând, creăm ceva care nu funcționează. Apoi încercăm să-l refactorăm și, în cele din urmă, îl înlocuim cu ceva care exista deja. Un exemplu este implementarea propriului cache personalizat atunci când există deja o mulțime de implementări. Indiferent cât de talentat ai fi ca programator, ar trebui să reții că reinventarea unei roți pătrate este cel puțin o pierdere de timp. Și, după cum știți, timpul este cea mai valoroasă resursă.14. Problema yo-yo
Problema yo-yo este un anti-pattern în care structura aplicației este excesiv de complicată din cauza fragmentării excesive (de exemplu, un lanț de moștenire subdivizat excesiv). „Problema yo-yo” apare atunci când trebuie să înțelegeți un program a cărui ierarhie de moștenire este lungă și complexă, creând apeluri de metodă profund imbricate. Ca rezultat, programatorii trebuie să navigheze între multe clase și metode diferite pentru a inspecta comportamentul programului. Numele acestui anti-model provine de la numele jucăriei. Ca exemplu, să ne uităm la următorul lanț de moștenire: Avem o interfață de tehnologie:
public interface Technology {
void turnOn();
}
Interfața de transport o moștenește:
public interface Transport extends Technology {
boolean fillUp();
}
Și apoi avem o altă interfață, GroundTransport:
public interface GroundTransportation extends Transport {
void startMove();
void brake();
}
Și de acolo, derivăm o clasă abstractă Car:
public abstract class Car implements GroundTransportation {
@Override
public boolean fillUp() {
/* some implementation */
return true;
}
@Override
public void turnOn() {
/* some implementation */
}
public boolean openTheDoor() {
/* some implementation */
return true;
}
public abstract void fixCar();
}
Urmează clasa Volkswagen abstractă:
public abstract class Volkswagen extends Car {
@Override
public void startMove() {
/* some implementation */
}
@Override
public void brake() {
/* some implementation */
}
}
Și, în sfârșit, un model specific:
public class VolkswagenAmarok extends Volkswagen {
@Override
public void fixCar(){
/* some implementation */
}
}
Acest lanț ne obligă să căutăm răspunsuri la întrebări precum:
-
Câte metode
VolkswagenAmarok
are? -
Ce tip ar trebui inserat în locul semnului de întrebare pentru a obține o abstractizare maximă:
? someObj = new VolkswagenAmarok(); someObj.brake();
15. Complexitate accidentală
Complexitatea inutilă este un anti-model în care complicațiile inutile sunt introduse într-o soluție.
public void createDescriptionForElement(ServiceType type, Long languageId, Long serviceId, String description)throws Exception {
switch (type){
case CAR:
jdbcTemplate.update(CREATE_RELATION_WITH_CAR, languageId, serviceId, description);
case USER:
jdbcTemplate.update(CREATE_RELATION_WITH_USER, languageId, serviceId, description);
case FILE:
jdbcTemplate.update(CREATE_RELATION_WITH_FILE, languageId, serviceId, description);
case PLAN:
jdbcTemplate.update(CREATE_RELATION_WITH_PLAN, languageId, serviceId, description);
case CUSTOMER:
jdbcTemplate.update(CREATE_RELATION_WITH_CUSTOMER, languageId, serviceId, description);
default:
throw new Exception();
}
}
Și, în consecință, avem această enumerare:
public enum ServiceType {
CAR(),
USER(),
FILE(),
PLAN(),
CUSTOMER()
}
Totul pare a fi simplu și bun... Dar cum rămâne cu celelalte metode? Într-adevăr, toți vor avea, de asemenea, o grămadă de switch
declarații și o grămadă de interogări de baze de date aproape identice, care, la rândul lor, vor complica foarte mult și vor umfla foarte mult clasa noastră. Cum ar putea fi mai ușor toate acestea? Să facem upgrade puțin enumerarea noastră:
@Getter
@AllArgsConstructor
public enum ServiceType {
CAR("cars_descriptions", "car_id"),
USER("users_descriptions", "user_id"),
FILE("files_descriptions", "file_id"),
PLAN("plans_descriptions", "plan_id"),
CUSTOMER("customers_descriptions", "customer_id");
private String tableName;
private String columnName;
}
Acum fiecare tip are numele câmpurilor originale ale tabelului său. Ca urmare, metoda de creare a unei descrieri devine:
private static final String CREATE_RELATION_WITH_SERVICE = "INSERT INTO %s(language_id, %s, description) VALUES (?, ?, ?)";
public void createDescriptionForElement(ServiceType type, Long languageId, Long serviceId, String description) {
jdbcTemplate.update(String.format(CREATE_RELATION_WITH_SERVICE, type.getTableName(), type.getColumnName()), languageId, serviceId, description);
}
Convenabil, simplu și compact, nu crezi? Indicația unui dezvoltator bun nu este cât de des folosește modele, ci mai degrabă cât de des evită anti-modele. Ignoranța este cel mai rău dușman, pentru că trebuie să-ți cunoști dușmanii din vedere. Ei bine, asta e tot ce am pentru azi. Vă mulțumesc tuturor! :)
GO TO FULL VERSION