Nadużywane lub nadużywane techniki programowania [zamknięte]

38

Czy są jakieś techniki programowania, które okażą się nadużywane (IE są używane o wiele bardziej niż powinny) lub nadużywane, lub używane trochę do wszystkiego, nie będąc jednocześnie dobrym rozwiązaniem wielu problemów, które ludzie próbują rozwiązać z tym.

Mogą to być wyrażenia regularne, jakiś wzorzec projektowy, a może algorytm lub coś zupełnie innego. Może uważasz, że ludzie nadużywają wielokrotnego dziedziczenia itp.

Anto
źródło
33
Zgadzam się, że IE jest używany o wiele bardziej niż powinien, ale przede wszystkim przez nie-programistów. . .
Eric Wilson,
7
@FarmBoy - myślę, że miał na myśli IE: „Ie” oznacza po prostu „to znaczy”, który w całości napisany po łacinie to „id est”.
Raphael
Naprawiono to teraz :)
Anto
4
Każda technika może (i często jest nadużywana), po prostu musi być przedstawiona jako następna srebrna kula, a znajdziesz kogoś, kto traktuje każdy problem jak gwóźdź (mieszanie metafor).
ChrisF
8
@ Rheheal - oczywiście żartowałem. Dzięki za edukację.
Eric Wilson,

Odpowiedzi:

73

Komentarze w kodzie

Chciałbym tylko, żeby profesorowie uniwersyteccy zrozumieli, że nie muszą uczyć swoich studentów pisania 10 wierszy komentarzy stwierdzających, że poniższy kod jest pętlą for, iterującą od 1 do liczby x. Widzę to w kodzie!

Naucz je, jak najpierw napisać kod samokontrujący, a następnie odpowiednio komentować to, co nie może być odpowiednio samo-dokumentujące. Świat oprogramowania byłby lepszym miejscem.

Dan McGrath
źródło
26
Kod samodokumentujący nie jest. Również profesorowie robią to, aby uczyć studentów konceptualizacji problemu i sposobu podejścia do niego. Ponadto nigdy nie widziałem, aby ktokolwiek narzekał na zbyt wiele dokumentów. Zastrzeżenie dotyczące dokumentacji jest poprawne.
Woot4Moo 11.01.11
24
@ Woot4Moo: jeśli czytasz Clean Code, Fowler wyraźnie stwierdza, że ​​nieaktualna dokumentacja jest gorsza niż brak dokumentacji i że wszystkie komentarze mają tendencję do starzenia się i migrowania z dala od kodu, który dokumentują. Cała ta książka jest o tym, jak napisać samodokumentujący się kod.
Scott Whitlock,
12
Nauczenie ich zastępowania komentarzy kodem byłoby dobrym początkiem ...
Shog9
15
+1. W rzeczywistości widziałem w kodzie świata: „loopVar ++; // increment loopVar”. AAAAAAAAAAAAARRRRRGH!
Tabele Bobby'ego
7
@Bill: Uważam, że nie trzeba dokumentować ogólnej logiki i struktur kontrolnych, nawet jeśli są one stosunkowo złożone. Zasadniczo wszystko, co dobry programista, który zna język, powinien być w stanie wypracować poprzez analizę kodu, nie powinno wymagać komentarza. na przykład. Zestaw zagnieżdżonych pętli z pewnymi przerwami w nich itp. Ale POWINNY być skomentowane specyficzne dla aplikacji uzasadnienie, dlaczego kod podejmuje takie decyzje: np. „Jeśli jutro nowy programista rozpocznie pracę w firmie i przyjrzy się kodowi, czy to, co ma sens, nie zawiera wskazówek?”
Tabele Bobby'ego
57

Wzór singletonu.

Oczywiście, jest to użyteczny wzorzec, ale za każdym razem, gdy nowy programista dowiaduje się o tym wzorcu, zaczyna próbować zastosować go do każdej tworzonej przez siebie klasy.

Raphael
źródło
Każdego dnia używam tej źle zaprojektowanej wymówki. codeigniter.com/user_guide/libraries/email.html Myślą, że OOP poprzedza funkcje $this->. PHP jest zepsutym językiem, więc nie mogę oczekiwać, że frameworki będą doskonałe.
Keyo,
7
Myślę, że każdy programista, który wdraża singletona i nie żałuje, spłonie w ognistym piekle za grzech (grzechy), które popełnił.
2
Raz wdrożyłem singletona (w kontekście wielozadaniowości) i musiałem żałować za grzech, przepisując go.
Spoike 12.01.11
3
Singletony mogą być przydatne do kilku rzeczy, ale prawie zawsze są używane, gdy nie powinny. Nie oznacza to, że singletonów nigdy nie należy używać - tylko dlatego, że coś jest nadużywane, nie oznacza, że ​​nie można go użyć poprawnie.
konfigurator
2
@Rapahel: Właśnie dlatego uważam, że studiowanie wzorów nie jest dobrą rzeczą.
konfigurator
53

Najbardziej zła rzecz, aby chronić głupie programowanie. próbując złapać wszystko i nic nie robiąc z chwytem

        try
        {
            int total = 1;
            int avg = 0;
            var answer = total/avg;
        }
        catch (Exception)
        {

        }

Drżę, gdy widzę próbę złapania, która nic nie robi i jest zaprojektowana do obsługi głupiej logiki. Zasadniczo połowy próbne są nadmiernie wykorzystywane, jednak w niektórych przypadkach są bardzo przydatne.

Nickz
źródło
4
Zabawne - właśnie edytowałem plik, który robi to setki razy i nie bez powodu. Jest to plik testu jednostkowego, który sprawdza, czy różne metody zgłaszają wyjątek, gdy jest to oczekiwane. Blok try zawiera połączenie i raport o „oczekiwanym rzucie nie nastąpił”. Wyjątek jest oczekiwany i poprawny, więc nie ma żadnych działań naprawczych. Oczywiście testy jednostkowe są specjalnym przypadkiem, ale miałem podobne przypadki w prawdziwym kodzie. Czerwona flaga, tak, ale nie absolutna zasada.
Steve314,
5
@Steve przypadku, który opisałeś jest rzadkim warunkiem krawędzi. Kolejny, o którym myślę, to rejestrowanie kodu - jeśli samo logowanie się nie powiedzie, nie ma sensu próbować rejestrować wyjątku ani przerywać aplikacji.
dbkk 12.01.11
1
@dbkk - zgodził się na warunki brzegowe, i dodam, że gdy naprawdę potrzebujesz złapać wyjątek, ale nie potrzebujesz działań naprawczych, dodaj komentarz w bloku catch, aby wyjaśnić, że jest to niezbędne, jeśli tylko uspokoisz opiekunowie. To nie jest tak rzadkie w testach jednostkowych, więc w tym przypadku zostawiłbym komentarz.
Steve314,
5
w przypadku błędu wznów dalej
jk.
2
@ jk01 - wyjątek nie jest (koniecznie) błędem. To, czy jakikolwiek warunek jest błędem, zależy od kontekstu. Na przykład „nie znaleziono pliku” nie jest błędem, jeśli nie potrzebujesz pliku. Być może jest to tylko opcjonalny plik ustawień, który może, ale nie musi być, i możesz po prostu pozostawić swoje ustawienia domyślne, jeśli pliku nie ma (więc po złapaniu nie jest wymagana żadna akcja naprawcza).
Steve314,
47

Zaufaj StackOverflow, aby rozwiązać swoje problemy, zamiast rozwiązywać problemy.

Nowi programiści, którzy (zbyt często) znajdują bogactwo wiedzy na temat SO, zanim zaczną myśleć i wypróbowywać różne rzeczy.

W moich czasach musieliśmy kodować z książek, bez internetu, bez SO. A teraz zejdź z mojego trawnika.

Byron Whitlock
źródło
28
Muszę przyznać, że wzdrygam się na odważność niektórych pytań dotyczących SO. Albo dlatego, że są pytani wiele razy każdego dnia i oczywiście wcale nie przeszukali; lub jeszcze gorzej, traktują społeczność jako bezpłatną usługę outsourcingową.
Orbling
2
@dbkk: stackoverflow.com/questions/4665778/… -> pierwszy komentarz „Czy kiedykolwiek próbowałeś tego?”
Matthieu M.
5
Zacząłem uczyć się od książek, ale kiedy miałem podstawy, nauczyłem się prawie wszystkiego innego z internetowych forów dyskusyjnych. Nie poprzez pytanie, ale głównie (i na początku wyłącznie) przez czytanie. Ta metoda nauczyła mnie kilku języków programowania z niesamowitą głębią (z wieloma zakamarkami) i myślę, że to wcale nie jest zła metoda.
Konrad Rudolph
1
@Konrad Rudolph: Ta metoda jest dobra i mądra, czyta pytania, dobrze wyszukuje. Pytanie najlepiej wykonać, gdy pytający ma ramy do zrozumienia odpowiedzi. Zbyt często ludzie zadają pytania, których (jeszcze) nie są w stanie zrozumieć.
Orbling
3
Problem polega na tym, że SO zachęcają do tego, dając dużo przedstawicieli za zadawanie / odpowiadanie na bardzo proste pytania, na które można odpowiedzieć za pomocą prostego wyszukiwania w Google. bardzo trudne pytanie, na które ludzie odpowiadają tylko dlatego, że naprawdę tego chcą.
IAdapter
36

Oczywiście OOP. Jest bardzo cenny, ale w przypadku niewłaściwego użycia może całkiem łatwo ukryć czysty kod (niektóre przykłady programowania S4 w R przychodzą na myśl), i może powodować ogromny narzut, który jest niepotrzebny i może kosztować dużo czasu na wydajność.

Inną rzeczą jest to, że (np. Perl) OOP często sprowadza się do pisania tego samego na odwrót: result = $object ->function(pars)zamiast result = function(object, pars)To czasami ma sens, ale w połączeniu z programowaniem proceduralnym może powodować, że czytanie kodu jest dość mylące. Poza tym po prostu wprowadzasz więcej kosztów ogólnych tam, gdzie nie poprawia to projektu. Sprowadza się to również do tego, co mówi się o wzorze singletonu: należy go stosować, ale nie we wszystkim.

Sam korzystam z OOP, ale w mojej dziedzinie (obliczenia naukowe) wydajność jest dużą sprawą, a OOP jest często nadużywane, ponieważ wszyscy studenci otrzymują obecnie Javę. Doskonale nadaje się do radzenia sobie z większymi problemami, do konceptualizacji i tak dalej. Ale jeśli pracujesz np. Z sekwencjami DNA w BioPerl, używanie obiektów za każdym razem i konsekwentna praca z modułami pobierającymi i ustawiającymi może dziesięciokrotnie wydłużyć czas obliczeń. Kiedy Twój kod działa kilka dni zamiast kilku godzin, ta różnica naprawdę ma znaczenie.

Joris Meys
źródło
6
@Craige: Sam używam OOP, ale w mojej dziedzinie (obliczenia naukowe) wydajność jest ogromną sprawą, a OOP jest często nadużywane, ponieważ wszyscy studenci otrzymują obecnie Javę. Doskonale nadaje się do radzenia sobie z większymi problemami, do konceptualizacji i tak dalej. Ale jeśli pracujesz np. Z sekwencjami DNA w BioPerl, używanie obiektów za każdym razem i konsekwentna praca z modułami pobierającymi i ustawiającymi może dziesięciokrotnie wydłużyć czas obliczeń. Kiedy Twój kod działa kilka dni zamiast kilku godzin, ta różnica naprawdę ma znaczenie.
Joris Meys,
1
@Craige: Łączenie metod (jak Foo.DoX().DoY().DoZ()) jest fajne, ale zdecydowanie nie jest to jedyny sposób, aby coś zrobić. Kompozycja funkcji (jak doZ . doY . doX $ foojest całkowicie poprawną alternatywą.
Anon.
1
@Joris: coś, nad czym zastanawiałem się od dłuższego czasu (sam jestem bioinformatykiem): jeśli wydajność ma tak duże znaczenie, to po co używać Perla zamiast C ++? Jeśli martwisz się obniżeniem współczynnika 10 z czasu wykonywania (ważna obawa!), Przejście na C ++ zapewnia natychmiastową satysfakcję. Oczywiście język jest do bani… ale także Perl… i istnieją dobre biblioteki bioinformatyczne dla C ++.
Konrad Rudolph
1
@Konrad: To zależy. BioPerl ma prawdopodobnie najwięcej pakietów dla bioinformatyków ze wszystkich języków (myślę, że Python nadrabia zaległości). Ponadto w Perlu wykonano wiele pracy, a dostosowanie skryptu jest łatwiejsze niż przepisywanie wszystkiego w C ++. Wreszcie, nie służy do napisania kompletnej aplikacji, gdy zrobi to skrypt. Zgadnij, dlatego Perl wciąż jest w pobliżu. I szczerze mówiąc, nie mam nic przeciwko, lubię ten język. To wciąż najlepsze, co znam do pracy z ciągami i plikami. Obliczenia są oczywiście wykonywane w innych językach i powiązane z powrotem (co jest dość łatwe).
Joris Meys,
1
@Konrad: to zależy od tego, jak to się robi. Wszystko można zrobić w Perlu, ale Perl można łatwo połączyć z innymi narzędziami, szczególnie w Linuksie. Używam Perla jako zaawansowanego skryptu bash z silną manipulacją ciągami i łatwą konstrukcją zestawów danych, które można upuszczać do innych aplikacji.
Joris Meys,
27

Spędziłem kilka lat w formularzach internetowych ASP.NET, musiałbym powiedzieć jednoznacznie:

Inteligentny interfejs użytkownika

Chociaż tworzenie formularzy internetowych z możliwością testowania warstwowego jest całkowicie możliwe, Visual Studio ułatwia programistom jednokrotne kliknięcie w celu utworzenia formularzy ściśle powiązanych ze źródłem danych, z logiką aplikacji zaśmieconą wokół całego kodu interfejsu użytkownika.

Steve Sanderson wyjaśnia ten anty-wzór znacznie lepiej niż ja w swojej książce Pro ASP.NET MVC:

Aby zbudować aplikację Smart UI, programista najpierw tworzy interfejs użytkownika, zwykle przeciągając serię widgetów interfejsu użytkownika na obszar roboczy, a następnie wypełnia kod obsługi zdarzeń dla każdego możliwego kliknięcia przycisku lub innego zdarzenia interfejsu użytkownika. Cała logika aplikacji znajduje się w tych procedurach obsługi zdarzeń: logika do akceptowania i sprawdzania poprawności danych wejściowych użytkownika, wykonywania dostępu do danych i ich przechowywania oraz przekazywania opinii poprzez aktualizację interfejsu użytkownika. Cała aplikacja składa się z tych programów obsługi zdarzeń. Zasadniczo właśnie to wydaje się domyślnie, gdy umieścisz nowicjusza przed Visual Studio. W tym projekcie nie ma oddzielenia problemów. Wszystko jest połączone, ułożone tylko pod względem różnych zdarzeń interfejsu użytkownika, które mogą wystąpić. Gdy reguły logiczne lub biznesowe muszą być stosowane w więcej niż jednym module obsługi, kod jest zwykle kopiowany i wklejany, lub niektóre losowo wybrane segmenty są podzielone na statyczne klasy użyteczności. Z wielu oczywistych powodów ten rodzaj wzoru jest często nazywany anty-wzorem.

richeym
źródło
1
GUI to przynajmniej jakiś kod specyfikacji, do którego należy się stosować. Nie sądzę, aby opisywani przez niego programiści zrobiliby coś lepszego, gdyby zamiast tego otrzymali pusty plik tekstowy.
4
@qpr, nie wiem o tym. Gdyby mieli pusty plik tekstowy, mogliby nie być w stanie nic zrobić (co może być dodatkową korzyścią).
Ken Henderson
Jedną z wielu zalet korzystania z WPF jest to, że implementacja MVVM rozbija ten anty-wzór na drobne ekrany.
Robert Rossney,
2
Tysiąc razy to. Widzę nawet doświadczonych programistów platformy .NET, którzy polegają na tym „wzorze”, ponieważ jest to łatwiejsze niż zrozumienie lub dbanie o separację problemów. Nawet jeśli nie używają kreatorów „przeciągnij i upuść”, najczęstszym „wzorcem” w rozwoju .NET WebForms jest robienie wszystkiego w przypadku zdarzeń związanych z kodem i kopiowanie / wklejanie kodu w razie potrzeby.
Wayne Molina
23

Widzę to od czasu do czasu i zwykle wynika to z niepełnego zrozumienia wyrażeń boolowskich.

if (someCondition == true)
Corey
źródło
16
Ma tę zaletę, że czyni kod bardziej wyraźnym
Pemdas
7
Myślę, że spojrzenie na to pytanie jest w porządku: programmers.stackexchange.com/questions/12807/…
gablin 11.01.11
5
Nie robię tego, ale poważnie, przełam to. Tam jest o wiele gorzej. :)
MetalMikester 11.01.11
4
Jeśli poprawnie nazwałeś swoje zmienne, na przykład boolzaczynając od islub has, nie musisz uwydatniać kodu = true.
Nikt
3
@DisgruntledGoat, ponieważ nie powinien być w ogóle używany
Corey
19

Ponowne wdrożenie podstawowej (lub w inny sposób zapewnionej) funkcjonalności, albo z powodu niewiedzy o jej istnieniu, albo z powodu postrzeganej potrzeby dostosowywania.

l0b0
źródło
2
Uczenie się jest wyjątkiem. Studiując cokolwiek, często korzystne jest „wynalezienie koła”.
Maks.
Na pewno - powinienem był określić, że ma to znaczenie tylko przy tworzeniu oprogramowania produkcyjnego.
l0b0
1
Jest to szczególnie złe przy wdrażaniu czegokolwiek związanego z bezpieczeństwem. Dobre oprogramowanie zabezpieczające zapobiega atakom, o których większość ludzi nawet nie myśli.
David Thornley,
Widzę tę drogę zbyt często. Potrzebujemy X, napiszmy własne! Ale co z pakietem open source Y? Nie, potrzebujemy niestandardowego oprogramowania do naszych super tajnych tajemnic handlowych, które są takie same jak wszyscy inni w naszej branży, nie możemy używać zwykłego oprogramowania do śmieci!
Wayne Molina,
18

Dziedzictwo.

Nie egzekwuj, to nie ma sensu.

Zestaw
źródło
6
Problem polega na tym, że intuicyjnie „to-a” wydaje się bardzo często mieć sens (w szczególności dlatego, że każdy stosunek realizacji / umowy można potocznie wyrazić jako „jest-a”). Wymaga solidnego zrozumienia OOP, aby zdać sobie sprawę, że to w rzeczywistości błąd, a dziedziczenie i implementacja interfejsu są zasadniczo różne.
Konrad Rudolph
@Konrad - absolutnie się zgadzam. Staram się zachęcać ludzi, aby zaczynali od kompozycji , przechodzili do interfejsów i uważali dziedziczenie za ostatnie. (Z reguły oczywiście). Ale może to moje rozmowy na temat VB ... ;-)
Mike Woodhouse
1
Jest to jednak w dużej mierze kwestia projektowania języka. Powodem, dla którego powinieneś „preferować dziedziczenie kompozycji (implementacji)” w językach takich jak Java lub C #, jest to, że dziedziczenie implementacji jest do bani w tych językach. Niektórzy krytykują obiektową konstrukcję oprogramowania Bertranda Meyera za nadużywanie dziedziczenia, ale kiedy spojrzysz na Eiffla (język użyty w książce), zdajesz sobie sprawę, że został on zaprojektowany do dziedziczenia implementacji , a zatem jest w porządku używanie dziedziczenia nad kompozycja. W tym przypadku, co najmniej.
Jörg W Mittag
14

Dostosowywanie gotowego oprogramowania.

Chociaż mogę przyznać, że może to być przydatne, zastanawiam się, ile pieniędzy wydaje się na drobiazgi w celu uzyskania wątpliwych korzyści. W tym miejscu firma może wydawać setki tysięcy, jeśli nie miliony dolarów na licencje na niektóre oprogramowanie, które następnie dostosowuje się, ponieważ jest tak konfigurowalne, edytowalne i elastyczne, że tak naprawdę nie robi wiele domyślnie. Ostatecznie jest to aplikacja niestandardowa, ponieważ cały nowy kod dodaje to, co pierwotnie kupiono.

JB King
źródło
Czy nie jest tak bardziej prawdopodobne w przypadku niestandardowej aplikacji?
JeffO
13

Używanie kompilatora jako debuggera.

Ignorowanie ostrzeżeń użytkownika lub wyłączenie ich całkowicie.

Zmienne globalne.

Pemda
źródło
18
Co jest złego w „używaniu kompilatora jako debuggera”? Ogromną zaletą jest posiadanie kompilatora, który potrafi wskazywać błędy w kodzie, zanim staną się problemem w środowisku wykonawczym.
Mason Wheeler,
3
Polegam na kompilatorze wychwytującym moje błędy składniowe i niepoprawne błędy dopasowania typu. W przypadku błędów behawioralnych korzystam z przypadków testowych.
gablin
5
Problem polega na tym, że zaczynasz polegać na kompilatorze, aby zapewnić poprawność programu. Czy to się skompilowało? Nie, pozwól mi opisać tę małą sekcję i sprawdzić, czy to naprawiło. Czy to się skompilowało? Nie, pozwól mi dodać * tu i tam i sprawdzić, czy się kompiluje. ... ect. Oczywiście przydaje się to do poprawiania literówek
Pemdas,
2
Mówisz tak, jakby koder szperał po omacku ​​w ciemności, próbując coś zrobić - cokolwiek - aby kod się jakoś skompilował. Nie tak to działa IME; kompilator wyświetla przydatny komunikat o błędzie i wskazuje lokalizację błędu, a zwykle, jeśli coś się nie kompiluje, to nowy kod, który sam napisałeś, więc masz całkiem niezły pomysł, co jest nie tak i jak go naprawić, gdy zostanie wskazany na zewnątrz. (Chociaż jeśli rzucasz losowymi * s, możesz pracować w C ++, w którym błędy kompilatora są wyjątkowo nieprzydatne, więc to, co powiedziałem, może nie mieć zastosowania.)
Mason Wheeler
3
Poleganie na kompilatorze działa bardzo dobrze, biorąc pod uwagę wystarczająco silny system typów i dobrze napisaną bazę kodu. Często system typów może modelować ważne ograniczenia, dla których w innym przypadku musiałbyś pisać testy (np. W systemach słabo typowanych). Tak używany rozsądnie, kompilator (a zwłaszcza jego sprawdzanie typów) jest świetnym zasobem do testowania i debugowania i poleganie na nim nie jest niczym złym. W szczególności nie można powiedzieć, że kompilator może wyświetlać tylko błędy składniowe.
Konrad Rudolph
11

Wszystkie wzory projektowe.

Są jak sól lub cukier. Niektóre z nich sprawiają, że jest to świetne, wiele z nich sprawia, że ​​jedzenie jest do kitu.

Nie zrozum mnie źle. Wzory projektowe to wspaniałe techniki. Często ich używałem. Ale czasami znajduję programistów (niektórzy z nich byli moi szefowie), którzy mieli takie „musisz użyć wzorca projektowego”, nawet jeśli nie pasuje to do problemu !!!

Jednym z przykładów jest „Wzorzec gościa”, który jest bardziej ukierunkowany na „Kolekcje liniowe / sekwencyjne”. Raz musiałem pracować ze strukturą danych drzewa. Aby „odwiedzić” każdy element, koduję metodę wzoru innego niż projektowy, a były szef nalega na użycie lub dostosowanie „Wzorca gościa”. Następnie przeglądam sieć w celu uzyskania drugiej opinii. Cóż, inni programiści mieli tę samą sytuację i to samo rozwiązanie. I nazwij to „Drzewnym / Hierarchicznym Wzorem Odwiedzającym”, jako NOWY Wzorzec Projektu

Mam nadzieję, że został dodany jako nowy wzór do istniejących, w nowej wersji książki „Wzory projektowe”.

umlcat
źródło
3
Nigdy nie używam wzorców projektowych, chociaż czasem pojawiają się one naturalnie w moim kodzie.
konfigurator
Jak brzmi powiedzenie? Zaczynasz używać wzorców, nie wiedząc, że ich używasz, a następnie dowiadujesz się o nich i używasz ich wszędzie, a potem stają się drugą naturą, więc zaczynasz ich używać, nie wiedząc, że ich używasz?
Wayne Molina,
2
@configurator Kiedy czytam o wzorcach projektowych;
Odkrywam
9

Wykorzystanie wyjątków jako kontroli przepływu. Trochę podobne do tej odpowiedzi , ale różne.

Przełykanie wyjątków jest złą formą, ponieważ wprowadza tajemnicze, trudne do znalezienia błędy w kodzie. Z drugiej strony stosowanie wyjątków jako kontroli przepływu jest złe, ponieważ powoduje, że kod jest znacznie bardziej nieefektywny niż mógłby być i jest koncepcyjnie niechlujny.

Obsługa wyjątków powinna być wykorzystywana tylko do obsługi naprawdę wyjątkowych (duh), nieprzewidzianych scenariuszy, a nie do rzeczy takich jak użytkownik wpisujący alfabet, gdzie oczekiwana jest liczba. Ten rodzaj nadużywania wyjątków jest niezwykle powszechny wśród złych programistów w świecie Java.

Stoły Bobby'ego
źródło
Wyjątki powodujące nieefektywny kod zależą od twojego języka - tworzenie ramki stosu itp. W Squeak twój stos jest w pełni poprawiony, więc nie ma różnicy między używaniem wyjątków, czy nie. (Innymi słowy, wyjątki są częścią biblioteki, a nie językiem.) Jednak myląca jest praca z kontrolą kontrolowaną przez wyjątki : lshift.net/blog/2011/01/04/try-again-with-exceptions shows wyjątki dotyczące używania pętli, które niedawno znalazłem.
Frank Shearar
Jeśli chodzi o ostatni akapit, zależy to od twojego języka. Wyjątki („warunki”) we wspólnym Lisp są ścisłym nadzorem większości języków dotyczących wyjątków. Zobacz przykłady tutaj: gigamonkeys.com/book/… Jak ze wszystkim, możesz posunąć się za daleko!
Frank Shearar
Czytelność i łatwość konserwacji przeważają nad wydajnością. Przypadki, w których wykorzystam wyjątki do osiągnięcia sukcesu (co, jak zakładam, rozumiesz przez „kontrolę przepływu”), są bardzo rzadkie, ale mogą dać czystszy kod np. Przy złożonym wyszukiwaniu rekurencyjnym. Ogólnie jednak się zgadzam. Na przykład mam kontenery z metodami iteratora, które zwracają wartość false za wyjście poza zakres (często na końcu iteracji), ale zgłaszają wyjątek, jeśli iterator ma wartość „null” (prawdopodobny znak wewnętrznej niespójności)
Steve314,
7

Idę z nieelastycznością poprzez nadmierne ukrywanie danych.

Wszyscy wiemy, że abstrakcja i ukrywanie implementacji są dobre, ale więcej nie zawsze jest lepsze. Przesadzone, możesz uzyskać nieelastyczny wynik, który nie poradzi sobie ze zmianami wymagań. Aby poradzić sobie ze zmianą, musisz nie tylko zmodyfikować klasę, która musi poradzić sobie z tą zmianą, ale także stworzyć sposób, aby informacje, które nigdy wcześniej nie były potrzebne, były dostępne pomimo warstw ukrywania danych.

Problem polega na tym, że podobnie jak w przypadku wszystkich problemów związanych ze znalezieniem właściwej równowagi dla każdego kontekstu, potrzeba doświadczenia.

Steve314
źródło
6

Zmienny stan i pętle. Prawie nigdy ich nie potrzebujesz i prawie zawsze dostajesz lepszy kod bez nich.

Na przykład jest to pobierane bezpośrednio z wątku StackOverflow:

// ECMAScript
var thing, things_by_type = {};
for (var i = 0; i < things.length; i++) {
    thing = things[i];
    if(things_by_type[thing.type]) {
        things_by_type[thing.type].push(thing);
    } else {
        things_by_type[thing.type] = [thing];
    }
}

# Ruby
things_by_type = {}
things.each do |thing|
  (things_by_type[thing.type] ||= []) << thing
end

Oboje robią to samo. Ale nie mam pojęcia, co oni robią. Na szczęście pytanie faktycznie wyjaśnia, co robią, więc mogłem je przepisać w następujący sposób:

// ECMAScript
things.reduce(function (acc, thing) {
    (acc[thing.type] || (acc[thing.type] = [])).push(thing);
    return acc;
}, {});

# Ruby
things.group_by(&:type)

// Scala
things groupBy(_.type)

// C#
from thing in things group thing by thing.Type // or
things.GroupBy(thing => thing.Type);

Nie ma pętli i nie można zmieniać stanu. No dobrze, bez wyraźnych pętli i liczników pętli.

Kod stał się znacznie krótszy, o wiele prostszy, bardziej podobny do opisu tego, co powinien robić (szczególnie w przypadku Rubiego, prawie bezpośrednio mówi „pogrupuj rzeczy według typu”) i znacznie mniej podatny na błędy. Nie ma niebezpieczeństwa ucieczki z końca tablicy, błędów słupka ogrodzeniowego lub błędów pojedynczych z indeksami pętli i warunkami zakończenia, ponieważ nie ma wskaźników pętli i warunków zakończenia.

Jörg W Mittag
źródło
Wierzę, że w drugim wierszu twojego „naprawionego” ECMAScript powinien być czytany (acc[thing.type] || (acc[thing.type] = [])), w przeciwieństwie do `= [rzecz] , unless you want to add rzecz` na liście dwa razy ... Czy coś mi brakuje?
Austin Hyde,
@Austin Hyde: Masz rację.
Jörg W Mittag
1
Ten przykład ekmascript jest niezrozumiały dla wielu programistów. Opiera się na zbyt wielu sztuczkach składniowych. Pętla ma tę zaletę, że jest oczywista dla młodszych programistów.
Joeri Sebrechts,
6

Kpić. Wprowadza zbyt wiele sztucznych wymagań dla nadmiernego odsprzęgania w kodzie, prowadzi do nadmiaru kodu ravioli i zmusza projekt w stylu OO do gardła, gdy bardziej proceduralny lub funkcjonalny projekt może być prostszym rozwiązaniem problemu.

dsimcha
źródło
Uzgodnione w teorii; mocks są przydatne, ale nie ma ich mieć.
Wayne Molina
Inwazyjność kpiny zależy od używanego języka. W języku C # może być bardzo inwazyjny i dodaje tratwy niepotrzebnych interfejsów.
Frank Hileman
3

Programiści z Delphi na całym świecie odkrywali w ciągu ostatnich dwóch lat, jak źle jest używać tablic znaków do przechowywania bajtów ze względu na hurtową konwersję Unicode

I „wkrótce” dowiemy się, jak źle jest przechowywać liczby całkowite na listach, gdy chcemy zmienić na 64-bitowe.

Peter Turner
źródło
2
Myślę, że ogromna część problemów z Unicode nigdy by się nie pojawiła, gdyby Borland zadeklarował typ DataString, który był zasadniczo taki sam jak AnsiString, ale specjalnie do użytku z obiektami blob, a następnie upewnił się, że ludzie o tym wiedzą.
Mason Wheeler,
2

Nieruchomości. Wiem, że jest to kontrowersyjne, ale uważam, że właściwości .net są znacznie nadużywane.

Jaka jest różnica między tymi dwiema liniami?

public string Property { get; set; }

public string Field;

Dla programisty różnica polega na: absolutnie niczym. Skompilowana forma jest nieco inna, więc jeśli piszesz bibliotekę, a ta biblioteka będzie aktualizowana w programach, a nie możesz ponownie skompilować samych programów (na przykład, jeśli piszesz interfejs dla wtyczek, które powinien działać w różnych wersjach oprogramowania), nie powinieneś używać pól publicznych, ponieważ nie możesz ich zastąpić właściwościami. W każdym innym przypadku nie ma absolutnie żadnej różnicy między użyciem pola lub auto-właściwości bez modyfikatorów.

konfigurator
źródło
1
Zgoda; jeśli wiesz w 100%, że nigdy nie będziesz musiał nic robić z uzyskaniem / ustawieniem „właściwości”, to nie ma żadnego powodu, aby mieć właściwość. Jeśli jednak istnieje szansa, że ​​musisz coś zrobić (na przykład rejestrowanie zmiany wartości), powinieneś użyć właściwości. Osobiście nie widzę wystarczająco dużą różnicę do nie korzystania z nieruchomości, na wszelki wypadek zrobić trzeba go zmodyfikować później (wiem, wiem, YAGNIale czuję, odbiegające w tym przypadku nic nie kosztuje)
Wayne Molina
2
@Wayne: W jaki sposób przejście ;na { get { ... } set { ... } }więcej pracy niż przejście { get; set; }na { get { ... } set { ... } }?
konfigurator
Teraz, gdy o tym myślę, to słuszna kwestia.
Wayne Molina,