Skąd wiecie, że piszecie najbardziej niezawodny kod bez nadmiernej inżynierii?
Uważam, że za dużo myślę o każdej możliwej ścieżce, którą może podążać mój kod, i czasami wydaje mi się to stratą czasu. Wydaje mi się, że zależy to od rodzaju pisanego programu, ale nie chcę poświęcać zbyt wiele czasu, biorąc pod uwagę sytuacje, które nigdy się nie zdarzają.
self-improvement
programming-practices
Fran Sevillano
źródło
źródło
Odpowiedzi:
Co uważasz za solidny kod? Kod, który jest już gotowy na przyszłość i tak potężny, że poradzi sobie w każdej sytuacji? Źle, nikt nie może przewidzieć przyszłości! I znowu źle, ponieważ będzie to skomplikowany, niemożliwy do utrzymania bałagan.
Stosuję różne zasady: przede wszystkim YAGNI (jeszcze) i KISS , więc nie piszę niepotrzebnego kodu. To również skutecznie zapobiega nadmiernej inżynierii. Refaktoryzuję aplikację, gdy potrzebne są rozszerzenia. Nowoczesne narzędzia do refaktoryzacji pozwalają dość łatwo tworzyć interfejsy i wymieniać implementacje, gdy są potrzebne.
Następnie staram się, aby kod, który piszę, był jak najbardziej niezawodny, co obejmuje eliminację tylu ścieżek, które program może obrać (i również stanów), jak to możliwe, i trochę programowania Spartan . Dużą pomocą są funkcje / metody „atomowe”, które nie polegają na stanach zewnętrznych lub przynajmniej nie pozostawiają programu w niespójnym stanie, gdy zawodzą. Jeśli zrobisz to dobrze, jest bardzo mało prawdopodobne, że kiedykolwiek skończysz z kodem spaghetti i jest to błogosławieństwo dla łatwości konserwacji. Ponadto w projektowaniu obiektowym zasady SOLID są doskonałym przewodnikiem po solidnym kodzie.
Naprawdę dowiedziałem się, że często możesz zmniejszyć złożoność, na przykład kombinatoryczne wybuchy ścieżek lub stanów programu, głęboko zastanawiając się, jak zaprojektować to jako najprostszą możliwą ścieżkę. Staraj się ograniczyć możliwe kombinacje do minimum, wybierając najlepszą kolejność podprogramów i projektując je do tego celu.
Solidny kod to zawsze prosty i przejrzysty kod, ale prostota jest cechą, która nie zawsze jest łatwa do osiągnięcia. Jednak powinieneś do tego dążyć. Zawsze po prostu pisz najprostszy możliwy kod i dodawaj złożoności tylko wtedy, gdy nie masz innego wyboru.
Prostota jest solidna, złożoność delikatna.
Złożoność zabija.
źródło
Staram się zachować równowagę, koncentrując się na
Jest to niewyraźny obszar graniczny - czasem udaje mi się wykonać trochę niepotrzebnej pracy, czasem nie udaje mi się zrobić czegoś, co później okazuje się konieczne. Jeśli tęsknoty nie są duże, wszystko w porządku. W każdym razie staram się uczyć na własnych błędach.
źródło
Różnica między solidnym a zaawansowanym inżynierią polega na tym, że z wdziękiem radzi sobie ze wszystkimi możliwymi przypadkami użycia, nawet dziwacznymi i skrajnymi przypadkami użycia, które NIE POWINNY się zdarzyć. Kiedy mówię z wdziękiem, mam na myśli, że użytkownik wprowadza dziwny przypadek wyjątku lub napotyka sytuację, która wymaga nieobsługiwanej lub nieokreślonej funkcji, która nie została zdefiniowana, a kod z wdziękiem kończy działanie bez awarii lub informuje użytkownika o nieobsługiwanej funkcjonalności.
Z drugiej strony nadinżynieria może wchodzić w zakres pełnej implementacji funkcji, które nie były potrzebne lub o które prosiło (niektóre funkcje, których klient NIE POTRZEBUJE, ale których nigdy nie wymagano!) LUB można je zdefiniować poprzez uzyskanie zbyt złożonego projektu lub zbyt złożonego kod do obsługi stosunkowo prostego problemu.
źródło
1) Uzyskaj wymagania.
2) Napisz minimalny kod, aby spełnić wymagania. Jeśli coś jest niejednoznaczne, zgadnij. Jeśli jest to bardzo niejednoznaczne, wróć do 1.
3) Wyślij do testowania.
4) Jeśli testerzy stwierdzą, że jest to dobre, udokumentuj zgodę. Jeśli coś jest nie tak, wróć do 1.
Skoncentruj się na zdaniu testów, a nie przewidywaniu testów. Jeśli nie masz testerów ... zdobądź testerów! Są one niezbędne nie tylko do weryfikacji poprawności kodu, ale także do całego procesu programowania.
źródło
Po pierwsze, należy maksymalnie znormalizować dane (nie nadmiarowe). Jeśli dane są w pełni znormalizowane, żadna pojedyncza aktualizacja danych nie może spowodować niespójności.
Nie zawsze możesz znormalizować dane, innymi słowy, możesz nie być w stanie wyeliminować nadmiarowości, w którym to przypadku mogą mieć niespójne stany. Następnie należy tolerować niespójność i okresowo ją naprawiać za pomocą jakiegoś programu, który przesuwa ją i łata.
Istnieje silna tendencja do ścisłego zarządzania redundancją za pomocą powiadomień. Są one nie tylko trudne do upewnienia się, że są poprawne, ale mogą prowadzić do ogromnej nieefektywności. (Część pokusy pisania powiadomień powstaje, ponieważ w OOP są one praktycznie zachęcane).
Ogólnie rzecz biorąc, wszystko, co zależy od sekwencji zdarzeń, komunikatów itp., Będzie podatne na atak i będzie wymagało mnóstwa kodowania obronnego. Zdarzenia i komunikaty są charakterystyczne dla danych z redundancją, ponieważ komunikują zmiany między częściami, próbując zapobiec niespójności.
Jak powiedziałem, jeśli musisz mieć nadmiarowość (a szanse są całkiem spore, musisz), najlepiej być w stanie a) tolerować ib) naprawiać. Jeśli spróbujesz zapobiec niespójności wyłącznie za pomocą wiadomości, powiadomień, wyzwalaczy itp., Bardzo trudno będzie uczynić ją niezawodną.
źródło
błędy pojawią się po drodze, ale (na szczęście) zostaną zlokalizowane i (w większości przypadków) pojawią się na bardzo wczesnym etapie testów. drugą zaletą ponownego użycia jest to, że klient / osoba dzwoniąca może zapisać większość sprawdzania błędów / rusztowań przy użyciu tego, co wynika z implementacji.
twoje testy określą następnie możliwości twojego programu i ich wytrzymałość - dodawaj kolejne testy, aż będziesz zadowolony ze wskaźników sukcesu i wkładu; w razie potrzeby ulepszanie, rozszerzanie i wzmacnianie.
źródło
Rozróżniam to, pisząc kod z dobrze zdefiniowanym, ale niekoniecznie optymalnym zachowaniem dla bardzo mało prawdopodobnych przejść. Na przykład, kiedy jestem całkiem pewien (udowodniony, ale nie przetestowany), że macierz będzie dodatnio określona, wstawiam twierdzenie lub wyjątek do programu, aby przetestować stan, ale nie piszę dla niego własnej ścieżki kodu. W ten sposób zachowanie jest zdefiniowane, ale nieoptymalne.
źródło
Solidność: stopień, w jakim system nadal działa w obecności nieprawidłowych danych wejściowych lub stresujących warunków środowiskowych. (Code Complete 2, s. 464)
Ważne pytanie dotyczy tego, jak ważna jest dla ciebie solidność. Jeśli jesteś na Facebooku, bardzo ważne jest, aby Twoja strona internetowa nadal działała, gdy ktoś wprowadza znaki specjalne, i aby twój serwer pozostał, gdy 100 milionów użytkowników jest zalogowanych jednocześnie. Jeśli piszesz skrypt do wykonania typowej operacji, którą wykonujesz tylko Ty, nie przejmujesz się tym zbytnio. Pomiędzy nimi jest wiele poziomów. Ocena, jakiej solidności potrzebujesz, jest jedną z ważnych umiejętności, których powinien nauczyć się programista.
Zasada YAGNI dotyczy dodawania funkcji, które mogą być potrzebne programowi. Ale ta zasada nie dotyczy solidności. Programiści zwykle przeceniają prawdopodobieństwo, że dane przyszłe rozszerzenie będzie potrzebne (zwłaszcza jeśli jest fajne), ale nie doceniają prawdopodobieństwa, że coś pójdzie nie tak. Ponadto, jeśli okaże się, że później potrzebna jest pominięta funkcja, programista może napisać ją później. Jeśli okaże się, że mimo wszystko konieczne jest sprawdzenie pominiętego błędu, uszkodzenie może zostać wyrządzone.
Dlatego w rzeczywistości lepiej jest popełnić błąd po stronie, sprawdzając, czy występują nietypowe błędy. Ale jest równowaga. Niektóre rzeczy do rozważenia w tej równowadze:
Nie zapominaj, że ludzie mogą - i będą - próbować korzystać z twojego programu w nieoczekiwany sposób. Lepiej jest, gdy dzieje się coś przewidywalnego.
Jako ostatnią linię obrony użyj twierdzenia lub zamknięcia. Jeśli wydarzy się coś, czego nie możesz znaleźć, jak sobie z tym poradzić, zamknij program. Zwykle jest to lepsze niż pozwolenie programowi na kontynuowanie i zrobienie czegoś nieprzewidywalnego.
źródło