Jakie są najgorsze anty-wzorce, na które natrafiłeś w swojej karierze programisty?
Jestem głównie zaangażowany w Javę, chociaż prawdopodobnie jest ona niezależna od języka.
Myślę, że najgorsze jest to, co nazywam głównym anty-wzorem . Oznacza program składający się z pojedynczej, bardzo dużej klasy (czasem wraz z parą małych klas), która zawiera całą logikę. Zwykle z dużą pętlą, w której zawarta jest cała logika biznesowa, czasami zawierająca dziesiątki tysięcy wierszy kodu.
language-agnostic
anti-patterns
стривігор
źródło
źródło
Uderzę inny oczywisty „kopiowaniem makaronu”. Kopiowanie kodu, który jest prawie identyczny z tym, czego chcesz, a następnie zmiana kilku rzeczy (zamiast wypakowywania do metody).
Jest to szczególnie rozpowszechnione w niektórych testowych kodach funkcjonalnych i API z późnych lat 90-tych: dosłownie setki (lub nawet tysiące) prawie identycznych przypadków testowych, które można podzielić na kilka funkcji, które przyjmują 3 lub 4 parametry - lub nawet lepiej , coś opartego na danych. Moją pierwszą pracą po studiach było dosłownie 8 miesięcy przepisywania i refaktoryzacji tysięcy wierszy makaronu, które używały przestarzałych metod. Kiedy skończyłem, pliki testowe miały mniej niż 10 oryginalnego rozmiaru i były o wiele łatwiejsze w utrzymaniu (i czytelności!).
źródło
Myślę, że mogę dużo napisać o Pattern Mania i rozwiązaniach, które można rozwiązać przy mniejszym wysiłku, ale wolałbym wskazać świetny artykuł, który przeczytałem ostatnio, z fantastycznym przykładem tego, jak proste rozwiązanie może być nadmiernie skomplikowane .
Jak (nie) pisać w Factorial w Javie, tak więc umieściliśmy fabrykę w twoim algorytmie
źródło
Złoty Młot
źródło
Regiony
W języku C # możesz zdefiniować region kodu, który można zwinąć w IDE, ukrywając go, chyba że chcesz poradzić sobie z tym kodem. Byłem na (obecnie jestem) projekcie, w którym regiony rozciągały się na setki linii (szkoda, że nie przesadzam) i było wiele regionów w funkcji tysiąca linii (znowu chciałbym żartować).
Z drugiej strony programista, który stworzył region, wykonał bardzo dobrą robotę, identyfikując określone funkcje w regionie. Do tego stopnia, że mogłem zrobić metodę wyodrębnienia dla regionu i przejść dalej.
Regiony zachęcają deweloperów do „ukrywania” swoich bzdur na widoku.
źródło
DoNotUseRegions
.#region SQL Update
sprawia , że jest zwijany, więc wymagane jest mniej przewijania.Dla mnie najgorszym wzorem jest Kopiuj / Wklej .
źródło
Nie przeciążające metody:
Wyraźnie pokazuje, że programista nie zrozumiał przeciążenia.
źródło
Sekwencje przełączania pętli
http://en.wikipedia.org/wiki/Loop-switch_sequence
Drażnią mnie bez końca i naprawdę pokazują, jak niedoświadczony był deweloper
źródło
Miękkie kodowanie , tj. Gdy programiści robią wszystko, aby uniknąć kodowania na twardo i kończą po drugiej stronie skali - zależności „na stałe”.
źródło
Zachowaj stan w kliencie.
Kiedyś pracował z aplikacją internetową, w której cały stan był przechowywany w przeglądarce. (Aby zapewnić bezproblemową skalowalność, wszystkie wyjątki zostały zignorowane).
źródło
Masowe meldowanie
Nienawidzę, gdy widzę, że programista nie dokonał odprawy przez ponad tydzień. Oznacza to, że albo utknął i nie szukał pomocy, albo zlepia wiele funkcji w jednym dużym meldunku. (Pominąłem najgorszy scenariusz, on po prostu nic nie robi. Łatwo to rozwiązać ... dwa słowa brzmią, jakbyś był zatrudniony.)
Jeśli dokonujesz dużej odprawy, tracisz wiele korzyści z SCM, takich jak możliwość połączenia zestawu zmian z określoną funkcją. Prawdopodobnie będziesz mieć wiele do zrobienia i nie zawsze jest to łatwe.
źródło
Obecnie pracuję z fragmentem starszego kodu i uwielbiam sposób, w jaki poprzedni programista otrzymuje pierwszy element listy:
Ale najgorsze, co widziałem w tym kodzie, to definiowanie klas wbudowanych stron JSP, pisanie całego HTML, CSS i Javascript za pomocą skryptletów i out.println :-(
źródło
Jednym z najgorszych zachowań anty-wzorcowych, jakie widziałem, był sklep, który pozwalał na wpisanie kodu do kontroli wersji dopiero po wyprodukowaniu. W połączeniu z wyłącznymi kasami w VSS, doprowadziło to do skomplikowanego procesu cofania kas, jeśli wada produkcyjna musiała zostać naprawiona przed następną wersją, nie mówiąc już o tym, że więcej niż jedna osoba musi zmienić dany plik na nadchodzące wydanie.
Fakt, że była to polityka departamentalna, sprawił, że stało się to jeszcze gorsze niż przypadek takiego zachowania jednego dewelopera.
źródło
Blokowanie dosłownego napisu
Bardzo długie nazwy klas. (w JRE)
Zła struktura dziedziczenia
Wyjątek, który nie jest.
Bezcelowa i tajemnicza obsługa błędów
Niepotrzebne tworzenie obiektów
Zgłaszanie wyjątku do innych celów
Używanie obiektów instancji do metod statycznych.
Synchronizacja na polu innym niż końcowy
Bezcelowa kopia stałego ciągu znaków
Bezcelowe wywołanie String.toString ()
Wywołania do System.gc () w celu zwolnienia pamięci
Ustawienie zmiennej lokalnej na null, aby zwolnić trochę pamięci
Używanie ++ i zamiast i ++ ze względu na wydajność (lub dowolną inną mikro-mikrooptymalizację)
źródło
Kod posypany:
lub
bez dodatkowych informacji.
źródło
Iterator dla manekinów:
Fabryka Singletono:
rozwój oparty na if-else (zwany również zasadą otwartego zamknięcia - otwarty na modyfikację zamknięty dla zrozumienia):
StringPattern (zwany także StringObject):
źródło
else if
to jednak często jedyny sposób na załatwienie sprawy. Myślę o strunach; nie mogę użyć przełącznika. Warunki powinny być podobne, aby były użyteczne.getInstance
zwraca tę samą instancję. Takie założenie złamałoby enkapsulację i jest w rzeczywistości jednym z najczęstszych anty-wzorów.Nie jest to tak naprawdę wzór kodowania, ale wzór behawioralny, jest jednak dość zły: modyfikowanie czegoś w kodzie (powiedzmy, że wymagania się zmieniły), a następnie dostosowywanie wszystkich testów jednostkowych, aż kod przejdzie. Ulepszenie lub po prostu usunięcie całego kodu testowego z metody testowej, ale pozostawienie tej metody.
Jest to powiązane z bardziej ogólnym wzorcem That will do , oto reprezentatywna linia kodu:
W końcu to działa.
źródło
Absolutnie nienawidzę odwracania abstrakcji lub ponownego wymyślania prymitywów niskiego poziomu na rzecz prymitywów wysokiego poziomu. Czasami jednak jest to spowodowane przez złych projektantów języka, a nie złych programistów. Przykłady:
Użycie jednej klasy metody bez zmiennych składowych i odpowiedniego interfejsu (zaimplementowanej w postaci tabel wskaźników funkcji) zamiast wskaźnika funkcji. Pamiętaj, że w językach takich jak Java możesz nie mieć wyboru.
W MATLAB i R nacisk kładziony jest na to, że wszystko jest wektorem / macierzą, a nie prymitywem.
Kiedy walimy MATLAB, co powiesz na fakt, że nie ma liczb całkowitych, więc kiedy potrzebujesz liczby całkowitej, musisz użyć podwójnej.
Czysto funkcjonalne języki, w których musisz używać wywołań funkcji do napisania pętli.
źródło
To byłoby zdecydowanie kopiowanie / wklejanie, widziałem wiele złego kodu z tego powodu, to i kodowanie kowboja i wszystko, co z tego wynika. (Boskie klasy, bardzo duże metody, błędne algorytmy itp.)
A jeśli wzorce projektowe są dozwolone, powiedziałbym: Wykonanie projektu jako zestawu działań z planu, bez przeprowadzania analizy projektu lub domeny.
źródło
Fasola java wielokrotnego użytku -
Fasola java z wieloma zmiennymi, używana w kilku różnych rodzajach operacji. Każda operacja używa dowolnego dowolnego podzbioru zmiennych komponentu bean i ignoruje inne. Kilka zmiennych dla stanu gui, kilka zmiennych wprowadzanych do przekazywania między komponentami, kilka, które prawdopodobnie nawet nie są już używane. Najlepsze przykłady nie mają dokumentacji, która utrudniałaby uznanie wzoru.
Nie można też zapomnieć o ukochanej
źródło
Były współpracownik miał zwyczaj ponownego wykorzystywania obiektów przez nadpisywanie ich właściwości, zamiast po prostu tworzenia nowych. Nigdy nie wyobrażałem sobie problemów, jakie spowodowało to przy wdrażaniu nowych funkcji.
źródło
Coś, co wywołało u mnie wiele żalu, to wzór „Duża mapa na niebie”. Rzucanie po mapie zamiast używania odpowiednich obiektów. Nie masz pojęcia, jakie „zmienne” zawiera bez debugowania i nie wiesz, co może zawierać bez śledzenia kodu wstecz. Zazwyczaj odwzorowuje ciągi na obiekty lub ciągi na ciągi, które potencjalnie mają zostać przetworzone na prymitywy.
źródło
Jednym z moich ulubionych anty-wzorców programistycznych jest użycie „projektu” bazy danych, który wymaga ciągłego dodawania dodatkowych kolumn do jednej lub więcej tabel programowo . Jest to kuzyn „projektu”, który tworzy nową tabelę dla każdej instancji bytu. Oba nieuchronnie uderzają w ograniczenia serwera bazy danych, ale zwykle dopiero, gdy system jest produkowany od dłuższego czasu.
źródło
Myślę, że jednym z najgorszych anty-wzorów, jakie widziałem, jest użycie tabeli bazy danych jako pamięci tymczasowej zamiast użycia pamięci komputera.
Domena problemowa jest zastrzeżona, co uniemożliwia mi jej wyjaśnienie, ale nie jest konieczne zrozumienie podstawowego problemu. To była aplikacja GUI napisana w Javie z backendową bazą danych. Miał pobrać określone dane wejściowe, zmanipulować je, a następnie zatwierdzić przetworzone dane w bazie danych.
Nasz projekt ma dość skomplikowany algorytm, który zapisuje wartości pośrednie do późniejszego przetworzenia. Zamiast enkapsulować obiekty tymczasowe w ... obiektach, utworzono tabelę bazy danych, taką jak „t_object”. Za każdym razem, gdy wartość była obliczana, była dodawana do tej tabeli. Po zakończeniu działania algorytmu wybierze wszystkie wartości pośrednie i przetworzy je wszystkie w jednym dużym obiekcie Map. Po zakończeniu całego przetwarzania pozostałe wartości, które zostały oznaczone do zapisania, zostaną dodane do rzeczywistego schematu bazy danych, a tymczasowe wpisy w tabeli „t_object” zostaną odrzucone.
Tabela była również używana jako unikalna lista, dane mogły istnieć tylko raz. Mogłoby to być przyzwoitą cechą projektu, gdybyśmy wdrożyli Ograniczenia na stole, ale zakończyliśmy iterację po całej tabeli, aby sprawdzić, czy dane istnieją, czy nie. (Nie, nawet nie korzystaliśmy z zapytań, w których zastosowano klauzule where z CONTAINS)
Niektóre problemy, na które natrafiliśmy w związku z tym projektem, były w szczególności debugowaniem. Aplikacja została zbudowana w celu potokowania danych, aby istniało wiele GUI, które wstępnie przetwarzałyby dane, zanim dotrą do tego algorytmu. Proces debugowania polegał na przetworzeniu przypadku testowego, a następnie wstrzymaniu natychmiast po zakończeniu powyższej sekcji. Następnie zapytalibyśmy bazę danych, aby zobaczyć, jakie dane były zawarte w tej tabeli.
Innym problemem, który odkryliśmy, było to, że dane nie były poprawnie usuwane z tej tabeli tymczasowej, co w przyszłości mogłoby zakłócać działanie programu. Odkryliśmy, że było to spowodowane tym, że wyjątki nie były odpowiednio obsługiwane, a zatem aplikacja nie wychodzi poprawnie i nie usuwa danych z tabeli, nad którą sprawuje kontrolę.
Gdybyśmy użyli podstawowego projektowania obiektowego i zachowali wszystko w pamięci, powyższe problemy nigdy by nie wystąpiły. Po pierwsze, debugowanie byłoby proste, ponieważ moglibyśmy łatwo ustawić punkty przerwania w aplikacji, a następnie sprawdzić pamięć w stosie i stercie. Po drugie, po nieprawidłowym wyjściu z aplikacji pamięć java zostałaby naturalnie wyczyszczona bez obawy o usunięcie jej z bazy danych.
UWAGA: Nie twierdzę, że ten wzorzec jest z natury zły, ale w tym przykładzie uznałem, że nie jest potrzebny, gdy wystarczyłyby podstawowe zasady OO.
Nie jestem pewien nazwy tego anty-wzoru, ponieważ po raz pierwszy widziałem coś takiego. Jakieś dobre imiona, które możecie wymyślić dla tego wzoru?
źródło
Cart-Before-The-Horse - alias YouMightNeedIt
Na przykład:
źródło
IMO najgorszym anty-wzorem, jaki widziałem, jest „Nie potrzebujemy żadnych śmierdzących wzorów”. Anty-wzór: Idea, że wzorce projektowe są stratą czasu i możesz szybciej pisać kod, po prostu rozrzucając go i kopiując / wklejanie w razie potrzeby.
Wyróżnienie dotyczy kodu, który ładuje obiekt z bazy danych przy użyciu starego stylu VB6:
nie jest to właściwie anty-wzór, ale pokazuje brak korzystania z właściwej architektury i oddzielenia problemów.
Ponadto takie rzeczy:
źródło