Jesteś głupi, aby uzyskać lepszą wydajność?

112

Spędziłem dużo czasu na czytaniu różnych książek o „dobrym projektowaniu”, „wzorach projektowych” itp. Jestem wielkim fanem podejścia SOLID i za każdym razem, gdy muszę napisać prosty kawałek kodu, myślę o przyszłość. Tak więc, jeśli implementacja nowej funkcji lub poprawki błędu wymaga jedynie dodania trzech wierszy kodu:

if(xxx) {
    doSomething();
}

To nie znaczy, że zrobię to w ten sposób. Jeśli wydaje mi się, że ten fragment kodu prawdopodobnie powiększy się w najbliższej przyszłości, pomyślę o dodaniu abstrakcji, przeniesieniu tej funkcji gdzie indziej i tak dalej. Celem, do którego dążę, jest utrzymanie średniej złożoności na tym samym poziomie, co przed moimi zmianami.

Uważam, że z punktu widzenia kodu jest to całkiem dobry pomysł - mój kod nigdy nie jest wystarczająco długi i dość łatwo jest zrozumieć znaczenie różnych jednostek, takich jak klasy, metody i relacje między klasami a obiektami.

Problem polega na tym, że zajmuje to zbyt wiele czasu i często wydaje mi się, że byłoby lepiej, gdybym po prostu wdrożył tę funkcję „tak jak jest”. Chodzi o „trzy wiersze kodu” vs. „nowy interfejs + dwie klasy do wdrożenia tego interfejsu”.

Z punktu widzenia produktu (kiedy mówimy o wyniku ) rzeczy, które robię, są zupełnie bezsensowne. Wiem, że jeśli będziemy pracować nad kolejną wersją, dobry kod jest naprawdę świetny. Ale z drugiej strony czas poświęcony na „dobry” kod mógł zostać wykorzystany na wdrożenie kilku przydatnych funkcji.

Często czuję się bardzo niezadowolony z moich wyników - dobry kod, który potrafi tylko A, jest gorszy niż zły kod, który potrafi A, B, C i D.

Czy takie podejście może przynieść dodatni zysk netto dla projektu oprogramowania, czy może to strata czasu?

loki2302
źródło
141
zobaczę twój SOLID i rasie ty YAGNI i KISS
jk.
16
Boom strzał w głowe.
Robert S.,
16
Problem „nadmiernej inżynierii” jest czasem przejawem procesu wychwytywania wymagań, który nie działa prawidłowo. Jeśli zmagasz się z „co-jeśli”, a następnie sam na nie odpowiadasz BEZ interakcji interesariusza / klienta, pozwoli Ci to przewidzieć przyszłość. Być może poświęcisz trochę wysiłku i wrócisz do lepszego zrozumienia wymagań przed wprowadzeniem większej złożoności do kodu?
Angelo
4
Może to tylko ja, ale uważałbym za „głupie” zmuszanie mojego klienta / pracodawcy do wydawania pieniędzy na coś, o co nie prosili / nie chcieli: S
Thomas Bonini
2
Prawie nigdy nie będzie trudniej dodać funkcji w przyszłości, gdy będzie ona faktycznie potrzebna. Teraz nic nie zyskujesz, robiąc to.
Hardwareguy

Odpowiedzi:

153

dobry kod, który potrafi tylko A, jest gorszy niż zły kod, który potrafi A, B, C, D.

Pachnie mi to jak spekulatywna ogólność . Nie wiedząc (a przynajmniej nie mając pewności), że Twoi klienci będą potrzebować funkcji B, C i D, po prostu niepotrzebnie komplikujesz projekt. Bardziej złożony kod jest trudniejszy do zrozumienia i utrzymania na dłuższą metę. Dodatkową złożoność uzasadniają jedynie użyteczne dodatkowe funkcje. Ale zazwyczaj bardzo źle przewidujemy przyszłość. Większość funkcji, które naszym zdaniem mogą być potrzebne w przyszłości, nigdy nie będą wymagane w prawdziwym życiu.

Więc:

Dobry kod, który potrafi tylko A (ale robi to tylko jedno i proste) jest LEPSZY niż zły kod, który może zrobić A, B, C, D (niektóre z nich mogą być potrzebne w przyszłości).

Péter Török
źródło
87
+1 za „zazwyczaj bardzo źle przewidujemy przyszłość” Użytkownik najprawdopodobniej poprosi o E :)
Michał Piaskowski
1
+1 Nie można zgodzić się więcej. Niedawno skończyłem pracę w firmie i uważam tę najważniejszą lekcję, której się nauczyłem.
Wipqozn
4
@ Michał, czy to przepowiednia? ;-)
Péter Török
10
Nawet jeśli poproszą cię o D, prawdopodobnie będą mieli inny model mentalny i poprosą o nieco inny rodzaj D, którego twoje abstrakcje nie obsługują ...
Chris Burt-Brown
„Jeśli problem nie jest w pełni zrozumiały, prawdopodobnie najlepiej nie zapewniać żadnego rozwiązania” lub „Nie dodawaj nowej funkcjonalności, chyba że implementator nie ukończy prawdziwej aplikacji bez niej”. dotyczy tutaj. Via en.wikipedia.org/wiki/X_Window_System#Principles
nwahmaet
87

Czas anegdoty:

Pracowałem dla dwóch programistów, którzy w ten sposób skłaniali się ku nadmiernej inżynierii.

W przypadku jednego z nich w zasadzie zatrzymano jego produktywność, szczególnie przy rozpoczynaniu nowego projektu. Szczególnie, jeśli projekt był z natury dość prosty. Ostatecznie potrzebujemy oprogramowania, które teraz działa. Stało się tak źle, że musiałem pozwolić mu odejść.

Drugi programista, który miał skłonność do nadmiernej inżynierii, nadrobił to, będąc niezwykle produktywnym. Jako taki, pomimo całego obcego kodu, wciąż dostarczał szybciej niż większość. Jednak teraz, gdy się przeprowadził, często denerwuje mnie ilość dodatkowej pracy, która jest potrzebna do dodania funkcjonalności, ponieważ musisz zmodyfikować (całkowicie niepotrzebne) warstwy abstrakcji itp.

Morał jest taki, że nadmierna inżynieria pochłonie dodatkowy czas, który można by lepiej wykorzystać na robienie użytecznych rzeczy. I to nie tylko twój czas, ale także tych, którzy muszą pracować z twoim kodem.

Więc nie rób tego.

Chcesz, aby Twój kod był tak prosty, jak to możliwe (i nie prostszy). Radzenie sobie z „maybes” nie upraszcza rzeczy, jeśli pomylisz się, to sprawisz, że kod stanie się bardziej skomplikowany, bez realnych korzyści.

Kris
źródło
10
+1 za tak proste, jak to możliwe, ale nie prostsze.
Julian
33
„Projektant wie, że osiągnął doskonałość nie wtedy, gdy nie ma już nic do dodania, ale kiedy nie ma już nic do zabrania”. Antoine de Saint-Exupery
Arkh
unikajcie powielania jak zarazy, a nie popełnicie błędu.
Kevin
@arkh ... Chciałem użyć tego samego cytatu: P
Michael Brown
6
Ujmę to w ten sposób: każda linia kodu ma z tym związane wysokie koszty. Zatem minimalizuj koszty, minimalizując kod. Usuwanie niepotrzebnego kodu jest tak samo produktywne (może nawet bardziej produktywne) niż pisanie nowego kodu.
Kristopher Johnson
26

Zasady SOLID i KISS / YAGNI są prawie biegunowymi przeciwieństwami. Jeden powie ci, że jeśli doSomething () nie może być uzasadniony jako integralna część zadania, które wykonuje klasa, która go wywołuje, powinien on należeć do innej klasy, która jest luźno powiązana i wstrzykiwana. Drugi powie ci, że jeśli jest to jedno miejsce, doSomething jest używane, nawet wyodrębnienie go w metodzie może być przesadą.

To sprawia, że ​​dobrzy programiści są na wagę złota. „Właściwa” struktura stanowi indywidualną podstawę, wymagającą znajomości aktualnej bazy kodu, przyszłej ścieżki programu oraz potrzeb biznesowych stojących za programem.

Lubię stosować tę prostą trzyetapową metodologię.

  • Przy pierwszym przejściu spraw, by działało.
  • Przy drugim przejściu wyczyść.
  • Przy trzecim przejściu ustaw SOLID.

Zasadniczo w ten sposób łączysz KISS z SOLID. Kiedy po raz pierwszy napiszesz wiersz kodu, dla wszystkich wiesz, że będzie to jednorazowy; po prostu musi działać i nikogo to nie obchodzi, więc nie bądź fantazyjny. Za drugim razem, gdy umieścisz kursor w tym wierszu kodu, obaliłeś swoją pierwotną hipotezę; odwiedzając ponownie ten kod, prawdopodobnie rozszerzasz go lub zaczepiasz z innego źródła. Teraz powinieneś to trochę posprzątać; wyodrębnij metody dla często używanych ciekawostek, zmniejsz lub wyeliminuj kodowanie kopiuj / wklej, dodaj kilka komentarzy itp. Za trzecim razem, gdy wrócisz do tego kodu, jest to główne skrzyżowanie ścieżek wykonywania programu. Teraz powinieneś traktować go jako podstawową część swojego programu i stosować reguły SOLID tam, gdzie to możliwe.

Przykład: Musisz napisać prosty wiersz tekstu na konsoli. Za pierwszym razem Console.WriteLine () jest w porządku. Następnie wracasz do tego kodu, gdy nowe wymagania nakazują również zapisanie tego samego wiersza w dzienniku wyjściowym. W tym prostym przykładzie może nie być wielu powtarzalnych kodów „kopiuj / wklej” (a może jest), ale nadal możesz wykonać podstawowe czyszczenie, wyodrębnić metodę lub dwie, aby uniknąć wbudowywania operacji we / wy w głębszą logikę biznesową . Następnie wracasz, gdy klient chce tego samego wyjścia tekstowego do nazwanego potoku dla serwera monitorowania. Teraz ta procedura wyjściowa jest czymś wielkim; Nadajesz ten sam tekst na trzy sposoby. Jest to podręcznikowy przykład algorytmu, który skorzystałby ze wzoru złożonego; opracować prosty interfejs IWriter za pomocą metody Write (), zaimplementuj ten interfejs, aby utworzyć klasy ConsoleWriter, FileWriter i NamedPipeWriter, i jeszcze raz, aby utworzyć klasę kompozytową „MultiWriter”, a następnie ujawnij zależność IWriter od swojej klasy, skonfiguruj kompozyt MultiWriter z trzema rzeczywistymi pisarzami i podłącz go. Teraz jest dość SOLIDNY; od tego momentu, gdy wymagania określają, że dane wyjściowe powinny iść gdziekolwiek nowe, wystarczy utworzyć nowy IWriter i podłączyć go do MultiWriter, bez potrzeby dotykania żadnego działającego kodu.

KeithS
źródło
Zgadzam się, ale zwykle po przejściu pierwszego kroku nigdy nie możesz wrócić do drugiego lub trzeciego, ponieważ teraz funkcja jest „na żywo” i jest więcej funkcji nadchodzących, więc nie możesz wrócić i naprawić pierwsza funkcja. Przekonasz się, że wszystko, co możesz zrobić, to pierwszy krok z każdą funkcją, a następnie pozostanie Ci bagno.
Wayne Molina,
2
@Wayne M - Z pewnością może się tak zdarzyć w wodospadzie SDLC lub w krótkich scenariuszach. W takich przypadkach cenne jest wykonanie zadania zgodnie z oryginalnymi specyfikacjami w terminie, a nie utrzymanie kodu. Jeśli chcesz docenić jakość kodu źródłowego, musisz po prostu wbudować czas w harmonogram refaktoryzacji. Podobnie jak jeśli cenisz jakość treści w jakimkolwiek innym zadaniu polegającym na tworzeniu pisemnych informacji, poświęcasz czas na sprawdzenie i edycję.
KeithS,
Twoja linia początkowa jest myląca - mówisz, że są przeciwni, a następnie opisz najlepszy sposób ich wspólnego wykorzystania. Nie wiem, czy powinienem głosować za złą linię, czy głosować za dobrą radą.
Sean McMillan,
1
Nie sądzę, żebym się zaprzeczył. Są przeciwieństwami niemal biegunowymi; przynależność religijna do jednego lub drugiego z konieczności będzie oznaczać odrzucenie drugiego. Nie oznacza to jednak, że wzajemnie się wykluczają; nie musisz wybierać w 100% do żadnej z metodologii. To był sedno odpowiedzi; jak osiągnąć równowagę, gdy wiąże się to z dawaniem i wyciąganiem wniosków z każdej zasady?
KeithS
Naprawdę fajny proces: działa, czysty, SOLIDNY. Zastanawiam się, czy następstwem tego jest „nie próbuj niczego projektować bez zhakowanego prototypu”.
Steve Bennett
17

dobry kod, który potrafi tylko A, jest gorszy niż zły kod, który potrafi A, B, C, D.

1) Posiadaj kod, który robi tylko to, co powinien.

Jeśli wydaje mi się, że ten fragment kodu prawdopodobnie powiększy się w najbliższej przyszłości, pomyślę o dodaniu abstrakcji, przeniesieniu tej funkcji gdzie indziej i tak dalej.

2) Jeśli planujesz zrobić kod A, B, C i D, klient ostatecznie poprosi o E.

Twój kod powinien robić to, co powinien, nie powinieneś teraz myśleć o przyszłych implementacjach, ponieważ nigdy nie przestaniesz ciągle zmieniać kodu, a co ważniejsze, przeprojektujesz kod. Powinieneś ponownie kodować kod, gdy tylko poczujesz, że go potrzebuje ze względu na obecne funkcje, nie walcząc o przygotowanie go na coś, czego jeszcze nie zrobi, chyba że oczywiście zaplanowałeś go jako część architektury projektu.

Proponuję przeczytać dobrą książkę: The Pragmatic Programmer . Otworzy twój umysł i nauczy cię, co powinieneś robić, a czego nie.

Również Code Complete to świetny zasób pełen przydatnych informacji, które powinien przeczytać każdy programista (nie tylko programista).

rev. Jose Faeti
źródło
12

bardzo czas muszę napisać prosty kawałek kodu, myślę o przyszłości

Może tu jest problem.

Na wczesnym etapie nie masz pojęcia, jaki byłby produkt końcowy. A jeśli masz, to źle. Na pewno. To jak 14-letni chłopiec, który kilka dni temu zapytał na Programmers.SE, czy musi w swojej przyszłej karierze wybierać między aplikacjami internetowymi, a ja nie pamiętam, co jeszcze: to oczywiste, że za kilka lat rzeczy będą jak on zmieni się, zainteresują go inne domeny itp.

Jeśli, aby napisać trzy wiersze kodu, utworzysz nowy interfejs i dwie klasy, jesteś nadmiar inżynierii. Otrzymasz kod, który będzie trudny do utrzymania i trudny do odczytania , tylko dlatego, że dla każdej użytecznej linii kodu masz dwie linie kodu, których nie potrzebujesz. Nie licząc dokumentacji XML, testów jednostkowych itp.

Pomyśl o tym: jeśli chcę wiedzieć, jak funkcja jest zaimplementowana w twoim kodzie, czy łatwiej byłoby mi odczytać dwadzieścia wierszy kodu, czy też szybciej i łatwiej byłoby otworzyć dziesiątki półpustych klas i interfejsy, aby dowiedzieć się, który z nich korzysta, w jaki sposób są one powiązane itp.?

Pamiętaj: większa baza kodów oznacza więcej czynności konserwacyjnych. Nie pisz więcej kodu, jeśli możesz tego uniknąć.

Twoje podejście jest również szkodliwe z innych stron:

  • Jeśli chcesz usunąć funkcję, czy nie jest łatwiej dowiedzieć się, gdzie jest stosowana konkretna metoda dwudziestoliniowa, niż marnować czas na zrozumienie zależności między dziesiątkami klas?

  • Czy podczas debugowania nie jest łatwiej mieć ślad małego stosu, czy wolisz czytać dziesiątki linii, aby dowiedzieć się, jak to się nazywa?

Podsumowując, wydaje się podobny do przedwczesnej optymalizacji . Próbujesz rozwiązać problem, nawet nie mając pewności, czy jest problem w pierwszej kolejności i gdzie on jest. Pracując nad wersją 1 produktu, zaimplementuj funkcje, które musisz zaimplementować już teraz; nie myśl o czymś, co spodziewasz się zaimplementować za dwa lata w wersji 14.

MainMa
źródło
„dziesiątki półpustych klas” mają dodatkową wadę, że nie ma wystarczającej ilości materiału, aby zrozumieć, do czego te klasy są dobre.
gnasher729
5

Pisanie dużej ilości kodu, który (prawdopodobnie) nigdy nie będzie używany, jest bardzo dobrym sposobem na wydanie P45 . Nie masz kryształowej kuli i nie masz pojęcia, jaki będzie ostateczny kierunek rozwoju, więc spędzanie czasu na tych funkcjach kosztuje tylko pieniądze bez zwrotu.

uɐɪ
źródło
3

Próba przewidzenia, co może być potrzebne w przyszłości w kodzie, często kończy się niepotrzebną nadmierną inżynierią (nawyk, który próbuję obecnie potrząsnąć). Powiedziałbym, żeby zrobić tylko trzy linie. Gdy zajdzie taka potrzeba (a nie wcześniej), refaktoryzuj. W ten sposób Twój kod zawsze robi to, czego potrzebuje, bez nadmiernego skomplikowania i ewoluuje naturalnie dobrą strukturę poprzez refaktoryzację.

Gyan alias Gary Buyn
źródło
3

Często mówię, że kodowanie jest jak jasna / ciemna strona Mocy - strona „jasna” wymaga więcej wysiłku, ale daje lepsze wyniki. „Ciemna” strona jest szybka i łatwa i daje większe korzyści natychmiast, ale psuje cię na drodze. Gdy zaczniesz ciemną ścieżkę, na zawsze zdominuje twoje przeznaczenie.

Wpadam na to cały czas, przy każdej pracy, jaką kiedykolwiek miałem, to jak klątwa, przed którą nie mogę uciec. Kultura firmy jest zawsze ścieżką ciemnej strony, a szybkie hacki / poprawki mają na celu wypchnięcie nowych funkcji, a moje prośby i okrzyki o poprawnym przetwarzaniu i pisaniu kodu trafiają do głuchych uszu, jeśli nie prowadzi to do mojego rozwiązania dla „ próbuję coś zmienić ”(nie żartowałem, że zdarzyło mi się to kilka razy, ponieważ chciałem wprowadzić wzory i odejść od szybkich hacków).

Smutna prawda jest taka, że ​​często głupią / ciemną stroną jest sposób, w jaki musisz stąpać, musisz tylko stąpać lekko. Powoli i ze smutkiem zdałem sobie sprawę, że programiści, którzy rozumieją właściwy sposób pisania oprogramowania, tj. Postępują zgodnie z SOLID, używają wzorców projektowych, przestrzegają SoC itp., Są znacznie mniej powszechni niż nieświadomi włamania, którzy napiszą ifinstrukcję naprawy błędu, i gdy pojawi się więcej błędów, po prostu dodaj do tego oświadczenia, zamiast myśleć: „Być może jest lepszy sposób” i zmieniając kod, aby był odpowiednio rozszerzalny.

Wayne Molina
źródło
3
ifjest o wiele łatwiejszy w utrzymaniu niż IAbstractBugFixerz IAbstractBugFixerFactory. Kiedy i JEŚLI możesz dodać sekundę if, czas na refaktoryzację. Wzorce projektowe i SOLID są bardzo ważne na etapie architektury, ale nie wtedy, gdy produkt jest już uruchomiony i jest napisany w jednym stylu, na który zgodzili się wszyscy członkowie zespołu.
Koder,
@ Koder Staraj się nie zakładać, że architektura nie może się zmienić w żadnym momencie. Może i robi.
Ricky Clarkson
1
Wayne M., potrafię wczuć się w twoje sytuacje w pracy. Pozostań przy Mocy. :)
Jennifer S,
3

Świadomość tego, co może się wydarzyć (w przyszłości), nigdy nie jest zła. Myślenie o tym, co może być lepszym sposobem na zrobienie czegoś, jest częścią tego, co czyni cię dobrym w pracy. Trudniejsze jest ustalenie, czy stosunek czasu do wypłaty jest uzasadniony. Wszyscy widzieliśmy sytuacje, w których ludzie robią „łatwe, jeśli”, aby zatrzymać natychmiastowe krwawienie (i / lub krzyczenie), a gdy te się sumują, dostajesz mylący kod. Wielu z nas doświadczyło również przesadzonej abstrakcji, która jest tajemnicą, gdy oryginalny koder przechodzi do następnego etapu, co również powoduje mylący kod.

Spojrzałbym na twoją sytuację i zadałbym następujące pytania:

  1. Czy ten kod jest kluczowy dla misji i czy będzie znacznie bardziej stabilny, jeśli zmienię kod? Mówiąc chirurgicznie, czy to refaktoryzacja ratuje życie, czy może jest tylko fakultatywne i kosmetyczne?

  2. Czy rozważam kod refaktoryzacyjny, który zamierzamy zastąpić za 6 miesięcy?

  3. Czy jestem gotów poświęcić tyle samo czasu na udokumentowanie projektu i mojego rozumowania dla przyszłych programistów, ile mam poświęcić na refaktoryzację?

  4. Jeśli chodzi o mój elegancki wygląd dodawania przyszłych funkcji, czy jest to kod, do którego użytkownicy domagają się zmian co tydzień, czy też po raz pierwszy go dotknąłem w tym roku?

Są chwile, w których YAGNI i KISS wygrywają dzień, ale są dni, w których fundamentalna zmiana doprowadzi cię do upadku spirali w dół do crappiness. Tak długo, jak realistycznie oceniasz nie tylko to, czego chcesz, ale także to, co inni będą musieli zrobić, aby utrzymać twoją pracę, będziesz w stanie lepiej określić, która sytuacja jest w danym momencie. Och, i nie zapomnij zapisać tego, co zrobiłeś i dlaczego. Uratuje tych, którzy podążają za tobą, ale także ciebie, kiedy będziesz musiał wrócić później.

Jennifer S.
źródło
3

W drugim wydaniu Stroustrups „The C ++ language language” (nie mam dostępnej strony) czytam

Nie dodawaj kodu spontanicznie na miejscu.

i poszedłem dobrze postępując zgodnie z radą Oczywiście są kompromisy i musisz znaleźć równowagę, ale krótkie fragmenty lepiej sprawdzają się niż duży bałagan spaghetti.

Często doświadczyłem, że rozróżniając jeden przypadek na dwa przypadki, jeśli myślisz o 2 przypadkach n, otwierasz drzwi do wielu nowych możliwości, o których być może nie pomyślałeś.

Ale musisz zadać pytanie YAGNI: czy warto? Czy to naprawdę będzie przydatne? Doświadczenie oznacza, że ​​rzadko się mylicie, a jako początkujący częściej.

Powinieneś być wystarczająco krytyczny, aby rozpoznać wzorzec i wykryć, czy twój kod jest trudny w utrzymaniu z powodu zbyt dużej abstrakcji, czy trudny w utrzymaniu, ponieważ wszystko zostało rozwiązane na miejscu.

Rozwiązaniem nie jest to czy tamto, ale o tym pomyśleć. :)

nieznany użytkownik
źródło
2

„dobry kod, który potrafi tylko A, jest gorszy niż zły kod, który potrafi A, B, C i D.”

Może to mieć sens przy opracowywaniu produktu; Ale większość specjalistów IT pracuje w „projektach”, a nie w rozwoju produktu.

Jeśli w „projektach informatycznych” zaprogramujesz dobry komponent, będzie on działał płynnie przez cały czas jego trwania - który może nie trwać dłużej niż 5 lub 10 lat, do tego czasu scenariusz biznesowy może być przestarzały i nowy projekt / ERP produkt mógł go wymienić. W ciągu 5/10 lat życia, chyba że w twoim kodzie występują wady, nikt nie zauważy, że istnieje, a zasługi twoich najlepszych myśli pozostaną niezauważone! (chyba że jesteś dobry w głośnym stawianiu własnej trąby!)

Niewielu ma możliwość zaprogramowania „Windows Ctl + Alt + Del”, a ci nieliczni mają taką szansę, mogą nie zdawać sobie sprawy z przyszłego potencjału swojego kodu!

Jose
źródło
1

Wiele książek o szczupłym i / lub zwinnym rozwoju pomoże wzmocnić to podejście: zrób to, co jest teraz konieczne. Jeśli wiesz, że budujesz strukturę, dodaj abstrakcje. W przeciwnym razie nie dodawaj złożoności, dopóki jej nie potrzebujesz. Polecam Lean Software Development , które wprowadzi wiele innych koncepcji, które mogą znacząco wpłynąć na wydajność.

sfuqua
źródło
1

To zabawne, jak ludzie mówią o właściwym sposobie działania. Jednocześnie zadanie programowania jest wciąż boleśnie trudne i nie daje dobrych rozwiązań do pisania dużych, złożonych systemów.

Być może pewnego dnia my, programiści, w końcu wymyślimy, jak pisać skomplikowane oprogramowanie. Do tego czasu sugeruję, aby zawsze zaczynać od „głupiej” implementacji prototypu, a następnie poświęcić tyle czasu na refaktoryzację, aby uczelnie mogły śledzić kod.

AareP
źródło
1
W większości przypadków nigdy nie będziesz mieć specjalnego czasu na refaktoryzację - to prawdopodobnie główny powód tych wszystkich „Nie możemy tego zaimplementować bez ponownej implementacji” ;-) Albo robisz to od samego początku lub robisz to cały czas w niewłaściwy sposób.
Andrey Agibalov,
@ loki2302: Pamiętaj, że pisanie nowego kodu jest zawsze łatwiejsze. Będziesz dwa razy szybszy podczas prototypowania głupiego kodu, po czym Twoja wydajność spadnie do zera przez około połowę czasu. W końcu programiści będą próbowali zaprojektować właściwą drogę.
AareP
1

Widząc tak przedwcześnie uogólnione projekty, które wcale nie pasowały do ​​rzeczywistych wymagań, które przyszły później, opracowałem dla mnie zasadę:

W przypadku wymagań hipotetycznych należy pisać tylko hipotetyczny kod.

Oznacza to, że dobrze jest pomyśleć o zmianach, które mogą wystąpić później. Ale wykorzystaj te spostrzeżenia, aby wybrać projekt kodu, który można łatwo zmienić i zrefaktoryzować, jeśli te wymagania rzeczywiście się pojawią. Możesz nawet napisać w głowie jakiś kod (hipotetyczny kod), który chciałbyś w takim przypadku napisać, ale nie pisz żadnego rzeczywistego kodu!

Hans-Peter Störr
źródło
0

Myślę, że sposób myślenia, który pomoże ci, to zawsze dążyć do konkretnych rozwiązań problemów z kodowaniem zamiast rozwiązań abstrakcyjnych. Abstrakcje należy dodawać tylko wtedy, gdy faktycznie upraszczają bazę kodu (gdy na przykład pozwalają zmniejszyć bazę kodu).

Wielu programistów odkryło, że abstrakcje pojawiają się prawie same, kiedy SUSZĄ swój kod. Wzorce projektowe i najlepsze praktyki pomagają znaleźć możliwości, aby to zrobić, ale same w sobie nie są celami, które warto realizować.

KaptajnKold
źródło
0

Myślę, że nadmiar inżynierii często wynika z niepewności co do pisania kodu. Wszystkie abstrakcyjne zasady i wzorce należy traktować jako narzędzia, które mogą ci pomóc. Często zdarza się, że są one traktowane jako standardy, z którymi należy się dostosować.

Uważam, że programista jest zawsze w lepszej pozycji, aby zdecydować, jak abstrakcji niż aksjomat.

Resztę powiedział już KeithS

sabof
źródło
Myślę, że jednym ze sposobów na zapewnienie sobie bezpieczeństwa przy pisaniu kodu jest kodowanie jako root w systemie Linux. Jeśli wpiszesz willy-nilly, boom, będziesz musiał po prostu odtworzyć maszynę wirtualną. Bardzo szybko uczy wszystkich dobrych nawyków. Upewnij się, że Twoje pudełko żyje w prawdziwym Internecie, i spójrz na dzienniki. (ssh, http) To też jest świetna zabawa!
Christopher Mahan
Moja wersja brzmi: ignoruj ​​zasady, których nie rozumiesz. Jeśli zdecydujesz się ich użyć, nie traktuj ich bardziej poważnie niż ćwiczenia.
sabof
0

Zadaj sobie pytanie, jakie są zalety dobrego projektu:

  • Łatwiejszy do zrozumienia
  • Łatwiejsze utrzymanie
  • Przenośny
  • Przydaje się przez długi czas
  • Łatwe dodawanie nowych funkcji

Teraz zadaj sobie pytanie, czy dodanie tych wszystkich warstw abstrakcji naprawdę dodaje do któregokolwiek z wyżej wymienionych punktów. Jeśli tak nie jest, robisz to ŹLE .

Jeśli możesz dodać nowe funkcje, dodając 3 wiersze kodu w następujący sposób:

if (condition()) {
  doSomething()
}

Następnie proszę, proszę to zrobić. Oznacza to, że poprzedni projekt był dobry i łatwy do dostosowania. Dopiero gdy klasy zaczną rosnąć poza pewien zakres, użyj refaktoryzacji, aby podzielić funkcje i ewentualnie wyodrębnić nowe klasy.

Moja ogólna zasada polega na tym, że nowe funkcje powinny być wdrażane tak minimalistycznie, jak to możliwe, tylko wtedy, gdy coś jest zbyt duże, aby uchwycić je z góry (powiedzmy, że wdrożenie zajmuje więcej niż 1 dzień lub pół dnia), możesz dodać szorstki globalny projekt. Odtąd dodawaj warstwy abstrakcji tylko wtedy, gdy rośnie rozmiar kodu. Następnie dokonujesz refaktoryzacji! Po pewnym czasie powinno ci się nawet przydać, gdy musisz zaprojektować kawałek lub wybrać się na szybką drogę. Innym wskazaniem, że niektóre kody mogą korzystać z czyszczenia, jest ich ponowne użycie. Za każdym razem, gdy dodajesz nową funkcję lub wywołujesz stary kod w nowym miejscu, to dobry moment, aby spojrzeć na stary kod i sprawdzić, czy możesz go trochę poprawić, zanim dodasz go ponownie. W ten sposób gorący kod będzie powoli stawał się czystszy, podczas gdy nieciekawe części powoli gniją i nie zajmują cennego czasu.

Jeśli pracujesz w ten sposób, nigdy niczego nie przeprojektujesz. Powrót do starego kodu może wymagać pewnej dyscypliny, gdy chcesz dodać coś nowego lub pozostawić nowy kod nieco bardziej brzydki, niż chcesz, ale będziesz pracować nad czymś produktywnym, a nie nadmiernie zaprojektowanym.

Dorus
źródło