Podczas programowania wszyscy rozwijamy praktyki i wzorce, których używamy i na których polegamy. Jednak z biegiem czasu, gdy zmienia się nasze zrozumienie, dojrzałość, a nawet wykorzystanie technologii, zdajemy sobie sprawę, że niektóre praktyki, które kiedyś uważaliśmy za świetne, nie są (lub już nie mają zastosowania).
Przykładem praktyki, której kiedyś używałem dość często, ale w ostatnich latach uległa zmianie, jest użycie wzorca obiektu Singleton .
Na podstawie własnego doświadczenia i długich debat z kolegami zdałem sobie sprawę, że singletony nie zawsze są pożądane - mogą utrudniać testowanie (hamując techniki takie jak kpiny) i mogą tworzyć niepożądane sprzężenia między częściami systemu. Zamiast tego używam teraz fabryk obiektów (zwykle z kontenerem IoC), które ukrywają naturę i istnienie singletonów przed częściami systemu, których to nie obchodzi - lub które muszą wiedzieć. Zamiast tego polegają na fabryce (lub lokalizatorze usług), aby uzyskać dostęp do takich obiektów.
Moje pytania do społeczności, w duchu samodoskonalenia, są następujące:
- Jakie wzorce lub praktyki programistyczne rozważaliście ostatnio, a teraz staracie się unikać?
- Czym zdecydowałeś się je zastąpić?
źródło
Pojedyncze punkty zwrotne.
Kiedyś wolałem jeden punkt zwrotny dla każdej metody, ponieważ dzięki temu mogłem zapewnić, że żadne czyszczenie wymagane przez rutynę nie zostanie przeoczone.
Od tego czasu przeszedłem do znacznie mniejszych procedur - więc prawdopodobieństwo przeoczenia czyszczenia jest zmniejszone, a potrzeba czyszczenia jest zmniejszona - i stwierdziłem, że wczesne zwroty zmniejszają pozorną złożoność (poziom zagnieżdżenia) kodu. Artefakty pojedynczego punktu powrotu - utrzymywanie zmiennych „wynikowych” w pobliżu, przechowywanie zmiennych flag, klauzule warunkowe dla sytuacji, które nie zostały jeszcze wykonane - sprawiają, że kod wydaje się znacznie bardziej złożony niż jest w rzeczywistości, czyniąc go trudniejszym do odczytania i utrzymania. Wczesne wyjścia i mniejsze metody są do zrobienia.
źródło
Jednym słowem przepracowanie .
źródło
Notacja węgierska (zarówno formy, jak i systemy). Kiedyś wszystko poprzedzałem. strSomeString lub txtFoo. Teraz używam someString i textBoxFoo. Jest znacznie bardziej czytelny i łatwiejszy do przyjścia i odebrania przez kogoś nowego. Dodatkową korzyścią jest to, że zachowanie spójności jest trywialne - camel Umieść kontrolkę i dodaj użyteczną / opisową nazwę. Forms Hungarian ma tę wadę, że nie zawsze jest konsekwentny, a Systems Hungarian niewiele daje. Dzielenie wszystkich zmiennych razem nie jest zbyt przydatne - szczególnie w przypadku nowoczesnych IDE.
źródło
Architektura „doskonała”
TĘ architekturę wymyśliłem kilka lat temu. Posunąłem się technicznie tak daleko, jak mogłem, więc było 100% luźno powiązanych warstw, szerokie wykorzystanie delegatów i lekkie obiekty. To było techniczne niebo.
I to było bzdury. Czystość techniczna architektury po prostu spowolniła mój zespół programistów w dążeniu do doskonałości nad wynikami i prawie osiągnąłem całkowitą porażkę.
Mamy teraz znacznie prostszą, mniej technicznie doskonałą architekturę, a nasz współczynnik dostaw gwałtownie wzrósł.
źródło
Zastosowanie kafiny. Kiedyś nie dawało mi to zasnąć i był we wspaniałym nastroju programowania, w którym kod leciał z moich palców z gorączkową płynnością. Teraz nic nie robi, a jeśli go nie mam, boli mnie głowa.
źródło
Komentowanie kodu. Kiedyś myślałem, że ten kod jest cenny i nie można po prostu usunąć tych pięknych klejnotów, które stworzyłeś. Usuwam teraz każdy skomentowany kod, który napotkam, chyba że jest dołączone TODO lub NOTE, ponieważ jest zbyt niebezpieczne, aby je zostawić. To znaczy, natknąłem się na stare klasy z ogromnymi zakomentowanymi częściami i naprawdę pomyliłem się, dlaczego one były: czy zostały niedawno skomentowane? czy to zmiana środowiska deweloperskiego? dlaczego robi ten niepowiązany blok?
Poważnie rozważ nie komentowanie kodu i po prostu jego usunięcie. Jeśli tego potrzebujesz, nadal podlega kontroli źródła. YAGNI chociaż.
źródło
Nadużywanie / nadużywanie dyrektyw #region. To drobiazg, ale w C # poprzednio używałem dyrektyw #region w każdym miejscu do organizowania moich zajęć. Na przykład zgrupowałbym wszystkie właściwości klas razem w regionie.
Teraz spoglądam wstecz na stary kod i głównie go denerwują. Nie sądzę, aby to naprawdę przez większość czasu wyjaśniało sytuację, a czasami po prostu spowalniało. Więc teraz zmieniłem zdanie i czuję, że dobrze rozplanowane klasy są w większości czystsze bez dyrektyw regionalnych.
źródło
Rozwój kaskadowy w ogóle, a w szczególności, praktyka pisania kompletnych i kompleksowych specyfikacji funkcjonalnych i projektowych, które w jakiś sposób mają być kanoniczne, a następnie oczekuje się, że ich implementacja będzie poprawna i akceptowalna. Widziałem, jak zastąpiono go Scrumem i powiem, że pozbyłem się go. Prosty fakt jest taki, że zmieniający się charakter potrzeb i pragnień klientów sprawia, że każda ustalona specyfikacja jest faktycznie bezużyteczna; jedynym sposobem, aby naprawdę właściwie podejść do problemu, jest podejście iteracyjne. Oczywiście Scrum nie jest srebrną kulą; Wiele razy widziałem to nadużywane i nadużywane. Ale to bije wodospad.
źródło
Nigdy się nie rozbija.
Wydaje się, że to dobry pomysł, prawda? Użytkownicy nie lubią programów, które ulegają awariom, więc piszmy programy, które się nie psują, a użytkownicy powinni lubić ten program, prawda? Tak zacząłem.
Obecnie jestem bardziej skłonny myśleć, że jeśli to nie działa, nie powinno udawać, że działa. Awaria tak szybko, jak to możliwe, z dobrym komunikatem o błędzie. Jeśli tego nie zrobisz, twój program będzie się zawieszał jeszcze mocniej, zaledwie kilka instrukcji później, ale z jakimś nieokreślonym błędem pustego wskaźnika, którego debugowanie zajmie Ci godzinę.
Mój ulubiony wzorzec „zapobiegaj awariom” to:
Teraz zamiast prosić użytkowników o skopiowanie / wklejenie komunikatu o błędzie i wysłanie go do Ciebie, będziesz musiał zagłębić się w dzienniki, próbując znaleźć wpis dziennika. (A ponieważ wprowadzili nieprawidłowy identyfikator użytkownika, nie będzie wpisu w dzienniku).
źródło
null
lub pusty ciąg znaków).Pomyślałem, że sensowne jest stosowanie wzorców projektowych, gdy tylko je rozpoznałem.
Nie wiedziałem, że faktycznie kopiuję style z obcych języków programowania, podczas gdy język, z którym pracowałem, pozwalał na znacznie bardziej eleganckie lub łatwiejsze rozwiązania.
Używanie wielu (bardzo) różnych języków otworzyło mi oczy i uświadomiło mi, że nie muszę źle stosować rozwiązań innych ludzi do problemów, które nie są moje. Teraz wzdrygam się, gdy widzę wzór fabryczny zastosowany w języku takim jak Ruby.
źródło
Testy obsesyjne. Byłem zaciekłym zwolennikiem rozwoju najpierw testowego. W przypadku niektórych projektów ma to duży sens, ale zdałem sobie sprawę, że niewolnicze trzymanie się doktryny pisania testów jednostkowych dla każdego elementu funkcjonalności jest nie tylko niewykonalne, ale wręcz szkodliwe dla wielu projektów.
Naprawdę niewolnicze trzymanie się wszystkiego może być szkodliwe.
źródło
To drobiazg, ale: dbanie o to, gdzie są nawiasy klamrowe (w tym samym czy następnym wierszu?), Sugerowane maksymalne długości wierszy kodu, konwencje nazewnictwa zmiennych i inne elementy stylu. Przekonałem się, że wszystkim zależy na tym bardziej niż mnie, więc po prostu idę z prądem każdego, z kim obecnie pracuję.
Edycja: Wyjątek od tej istoty, oczywiście, kiedy to ja najbardziej zależy mi na tym (lub to ja jestem w stanie ustawić styl dla grupy). W takim razie robię, co chcę!
(Zauważ, że to nie to samo, co brak spójnego stylu. Myślę, że spójny styl w bazie kodu jest bardzo ważny dla czytelności).
źródło
Być może najważniejszą „praktyką programistyczną”, na temat której zmieniłem zdanie, jest przekonanie, że mój kod jest lepszy od wszystkich innych. Jest to typowe dla programistów (zwłaszcza początkujących).
źródło
Biblioteki narzędziowe. Kiedyś nosiłem zespół z różnymi metodami pomocniczymi i klasami z teorią, że mógłbym ich kiedyś użyć gdzie indziej.
W rzeczywistości właśnie stworzyłem ogromną przestrzeń nazw z wieloma źle zorganizowanymi fragmentami funkcjonalności.
Teraz po prostu zostawiam je w projekcie, w którym je stworzyłem. Najprawdopodobniej nie będę tego potrzebować, a jeśli to zrobię, zawsze mogę je później przerobić na coś do ponownego wykorzystania. Czasami oznaczam je za pomocą // TODO w celu ewentualnego wyodrębnienia do wspólnego zestawu.
źródło
Projektuję więcej niż kodowałem. Po chwili zamienia się w paraliż analityczny.
źródło
Użycie DataSet do wykonywania logiki biznesowej. To wiąże kod zbyt mocno z bazą danych, również DataSet jest zwykle tworzony z SQL, co czyni rzeczy jeszcze bardziej delikatnymi. Jeśli SQL lub baza danych ulegnie zmianie, ma tendencję do przesączania się do wszystkiego, czego dotknie DataSet.
Wykonywanie dowolnej logiki biznesowej wewnątrz konstruktora obiektów. Dziedziczenie i możliwość tworzenia przeciążonych konstruktorów utrudniają konserwację.
źródło
Skrócenie nazw zmiennych / metod / tabel / ...
Robiłem to cały czas, nawet pracując w językach bez narzuconych ograniczeń długości nazw (no cóż, prawdopodobnie było ich 255 lub coś podobnego). Jednym z efektów ubocznych było wiele komentarzy w całym kodzie wyjaśniających (niestandardowe) skróty. I oczywiście, gdyby nazwy zostały zmienione z jakiegokolwiek powodu ...
Teraz zdecydowanie wolę nazywać rzeczy tym, czym naprawdę są, z dobrymi, opisowymi nazwami. w tym tylko standardowe skróty. Nie ma potrzeby dołączania zbędnych komentarzy, a kod jest dużo bardziej czytelny i zrozumiały.
źródło
Foo(int arg0, String arg1, float arg2)
itp.Pakowanie istniejących składników dostępu do danych, takich jak biblioteka przedsiębiorstwa, niestandardową warstwą metod pomocniczych.
źródło
Po raz pierwszy usłyszałem o programowaniu obiektowym czytając o Smalltalk w 1984 roku, ale nie miałem dostępu do języka oo, dopóki nie użyłem kompilatora cfront C ++ w 1992 roku. W końcu zacząłem używać Smalltalk w 1995 roku. technologii i przekonał się, że pozwoli to zaoszczędzić rozwój oprogramowania.
Teraz widzę oo jako jedną technikę, która ma pewne zalety, ale to tylko jedno narzędzie w zestawie narzędzi. Większość pracy wykonuję w Pythonie i często piszę samodzielne funkcje, które nie są członkami klas, i często zbieram grupy danych w krotki lub listy, w których w przeszłości utworzyłbym klasę. Nadal tworzę klasy, gdy struktura danych jest skomplikowana lub potrzebuję zachowania związanego z danymi, ale zwykle się temu opieram.
Właściwie jestem zainteresowany pracą w Clojure, gdy mam czas, co nie zapewnia funkcji oo, chociaż może używać obiektów Java, jeśli dobrze rozumiem. Nie jestem gotów powiedzieć, że cokolwiek takiego jak oo nie żyje, ale osobiście nie jestem tym fanem, jakim byłem.
źródło
W C # przy użyciu
_notation
dla członków prywatnych. Teraz myślę, że jest brzydki.Potem zmieniłem na
this.notation
dla prywatnych członków, ale stwierdziłem, że nie jestem konsekwentny w używaniu go, więc też go porzuciłem.źródło
this
orMe
(odpowiednio C # i VB.NET) podczas wywoływania metod i właściwości. IMO sprawia, że mój kod jest łatwiejszy do odczytania i zrozumienia później, zwłaszcza gdy w tym konkretnym zakresie znajdują się cztery lub więcej obiektów.Przestałem chodzić na zalecaną przez uniwersytet metodę projektowania przed wdrożeniem. Praca w chaotycznym i złożonym systemie zmusiła mnie do zmiany nastawienia.
Oczywiście nadal badam kod, zwłaszcza gdy mam zamiar dotknąć kodu, którego nigdy wcześniej nie dotykałem, ale zwykle staram się skupić na jak najmniejszych implementacjach, aby coś działało jako pierwsze. To jest główny cel. Następnie stopniowo udoskonalaj logikę i pozwól, aby projekt pojawił się sam. Programowanie jest procesem iteracyjnym i działa bardzo dobrze z podejściem zwinnym i dużą ilością refaktoryzacji.
Kod nie będzie wyglądał tak, jak początkowo myślałeś, że będzie wyglądał. Dzieje się za każdym razem :)
źródło
Kiedyś lubiłem projektować według kontraktu. Oznaczało to umieszczenie wielu sprawdzeń błędów na początku wszystkich moich funkcji. Kontrakty są nadal ważne, z punktu widzenia rozdzielenia obaw, ale zamiast próbować narzucić to, czego mój kod nie powinien robić, staram się używać testów jednostkowych, aby zweryfikować, co robi.
źródło
Używałbym statycznych w wielu metodach / klasach, ponieważ były bardziej zwięzłe. Kiedy zacząłem pisać testy, praktyka zmieniła się bardzo szybko.
źródło
Sprawdzone wyjątki
Niesamowity pomysł na papierze - jasno określa umowę, nie ma miejsca na pomyłkę lub zapominanie o sprawdzeniu wyjątku. Zostałem sprzedany, kiedy pierwszy raz o tym usłyszałem.
Oczywiście w praktyce okazał się takim bałaganem. Do tego stopnia, że mamy dziś biblioteki takie jak Spring JDBC, które ukrywały sprawdzone wyjątki jako jedną z głównych funkcji.
źródło
Że wszystko, co warte zachodu, zostało zakodowane tylko w jednym języku. W moim przypadku wierzyłem, że C jest najlepszym językiem wszechczasów i nigdy nie miałem powodu, aby kodować cokolwiek w innym języku ... nigdy.
Od tego czasu doceniłem wiele różnych języków i zalety / funkcje, które oferują. Jeśli chciałbym zakodować coś małego - szybko - użyłbym Pythona. Jeśli chcę pracować nad dużym projektem, kodowałbym w C ++ lub C #. Jeśli chcę rozwinąć guza mózgu, kodowałbym w Perlu .
źródło
Kiedy musiałem przeprowadzić refaktoryzację, pomyślałem, że szybsze i czystsze będzie rozpoczęcie od razu i wdrożenie nowego projektu, naprawianie połączeń, aż zaczną działać. Wtedy zdałem sobie sprawę, że lepiej jest przeprowadzić serię małych refaktoryzacji, aby powoli, ale niezawodnie przejść do nowego projektu.
źródło
Być może największą rzeczą, która zmieniła się w moich praktykach kodowania, a także w innych, jest akceptacja zewnętrznych klas i bibliotek pobranych z Internetu jako podstawy zachowań i funkcjonalności w aplikacjach. W szkole w czasie, gdy chodziłem do college'u, zachęcano nas, abyśmy wymyślili, jak ulepszyć sytuację za pomocą własnego kodu i polegać na języku, aby rozwiązać nasze problemy. Wraz z postępem we wszystkich aspektach interfejsu użytkownika i wykorzystania usług / danych nie jest to już realistyczne pojęcie.
Są pewne rzeczy, które nigdy się nie zmienią w języku, a posiadanie biblioteki, która opakowuje ten kod w prostszą transakcję i mniejszą liczbę wierszy kodu, które muszę napisać, jest błogosławieństwem. Łączenie się z bazą danych zawsze będzie takie samo. Wybór elementu w DOM nie zmieni się. Wysyłanie wiadomości e-mail za pośrednictwem skryptu po stronie serwera nigdy się nie zmieni. Konieczność pisania tego raz po raz marnuje czas, który mógłbym wykorzystać na ulepszenie mojej podstawowej logiki w aplikacji.
źródło
Inicjowanie wszystkich członków klasy.
Kiedyś jawnie inicjowałem każdy element klasy czymś, zwykle NULL. Zdałem sobie sprawę, że to:
źródło
Podobnie jak Ty, zastosowałem wzorce IoC w zmniejszaniu sprzężeń między różnymi komponentami moich aplikacji. Sprawia, że konserwacja i wymiana części są znacznie prostsze, o ile mogę utrzymać każdy element tak niezależny, jak to tylko możliwe. Używam także bardziej obiektowo-relacyjnych struktur, takich jak NHibernate, aby uprościć zadania związane z zarządzaniem bazą danych.
Krótko mówiąc, używam „mini” frameworków, aby pomóc w szybszym i wydajniejszym tworzeniu oprogramowania. Te mini-frameworki oszczędzają dużo czasu, a jeśli zostaną wykonane prawidłowo, mogą sprawić, że aplikacja będzie bardzo prosta w utrzymaniu. Podłącz i graj, aby wygrać!
źródło