Jako programista znalazłem się w dylemacie, w którym chcę, aby mój program był jak najbardziej abstrakcyjny i jak najbardziej ogólny.
Takie postępowanie zazwyczaj pozwala mi ponownie użyć mojego kodu i uzyskać bardziej ogólne rozwiązanie problemu, który może (lub nie musi) pojawić się ponownie.
Wtedy ten głos w mojej głowie mówi: po prostu rozwiąż problem, manekin, to takie proste! Po co spędzać więcej czasu niż trzeba?
Wszyscy rzeczywiście zmierzyliśmy się z tym pytaniem, gdzie Abstrakcja jest na twoim prawym ramieniu, a Rozwiąż to głupie po lewej.
Czego słuchać i jak często? Jaka jest twoja strategia? Czy wszystko powinieneś streścić?
time-management
problem-solving
abstraction
Bryan Harrington
źródło
źródło
Odpowiedzi:
Nigdy nie abstrakcyjne, dopóki nie musisz.
Na przykład w Javie musisz używać interfejsów. Są abstrakcją.
W Pythonie nie masz interfejsów, masz Duck Typing i nie potrzebujesz wysokich poziomów abstrakcji. Więc po prostu nie.
Nie streszczaj, dopóki nie napiszesz tego trzy razy.
Raz jest - cóż - raz. Wystarczy go rozwiązać i przejść dalej.
Dwukrotnie oznacza, że może istnieć tutaj wzór. Lub może nie. To może być po prostu zbieg okoliczności.
Trzykrotnie jest początkiem wzoru. Teraz wykracza poza przypadek. Możesz teraz pomyślnie streścić.
Nie.
Rzeczywiście, nigdy nie powinieneś niczego abstrakować, dopóki nie masz absolutnego dowodu, że robisz właściwy rodzaj abstrakcji. Bez „Reguły trzech powtórzeń” napiszesz rzeczy bezużytecznie abstrakcyjne w sposób, który nie jest pomocny.
Jest to założenie, które często jest fałszywe. Abstrakcja może wcale nie pomóc. Można to zrobić źle. Dlatego nie rób tego, dopóki nie musisz.
źródło
Ach, YAGNI. Najbardziej nadużywana koncepcja programowania.
Istnieje różnica między dostosowaniem kodu a wykonaniem dodatkowej pracy. Czy powinieneś poświęcić dodatkowy czas na luźne powiązanie kodu i łatwą adaptację do innych celów? Absolutnie. Czy powinieneś spędzać czas na wdrażaniu niepotrzebnych funkcji? Nie. Czy powinieneś poświęcić czas na dostosowanie kodu do innego kodu, który nie został jeszcze zaimplementowany? Nie.
Jak mówi przysłowie: „Zrób najprostszą rzecz, która może działać”. Chodzi o to, że ludzie zawsze mylą proste z łatwym . Prostota wymaga pracy. Ale warto spróbować.
Czy możesz wyjść za burtę? Oczywiście. Ale z mojego doświadczenia wynika, że niewiele firm potrzebuje bardziej podejścia „zrób to teraz” niż ma to już miejsce. Większość firm potrzebuje więcej osób, które przemyślą wszystko z wyprzedzeniem. W przeciwnym razie zawsze kończą się samowystarczalnym problemem, w którym nikt nigdy nie ma czasu na nic, wszyscy są w pośpiechu i nikt nic nie robi.
Pomyśl o tym w ten sposób: są duże szanse, że Twój kod zostanie jakoś ponownie wykorzystany. Ale nie zamierzasz poprawnie przewidzieć w ten sposób. Dlatego twój kod powinien być czysty, abstrakcyjny i luźno powiązany. Ale nie staraj się, aby Twój kod działał z konkretnymi funkcjami, które jeszcze nie istnieją. Nawet jeśli wiesz, że będzie istniał w przyszłości.
źródło
simple
ieasy
!Syllogizm:
Generalność jest droga.
Wydajesz pieniądze innych ludzi.
Dlatego koszt ogólności musi być uzasadniony dla zainteresowanych stron.
Zadaj sobie pytanie, czy naprawdę rozwiązujesz bardziej ogólny problem, aby później zaoszczędzić pieniądze interesariuszy, czy może po prostu uważasz, że podjęcie niepotrzebnie ogólnego rozwiązania stanowi wyzwanie intelektualne.
Jeśli ogólność zostanie uznana za pożądaną , należy ją zaprojektować i przetestować jak każdą inną cechę . Jeśli nie możesz napisać testów, które pokazują, w jaki sposób ogólność, którą zaimplementowałeś, rozwiązuje problem wymagany przez specyfikację, nie zawracaj sobie tym głowy! Funkcja, która nie spełnia żadnych kryteriów projektowych i nie może być przetestowana, jest funkcją, na której nikt nie może polegać.
I na koniec, nie ma czegoś takiego jak „tak ogólne, jak to możliwe”. Załóżmy, że piszesz oprogramowanie w języku C #, tylko ze względu na argument. Czy chcesz, aby każda klasa implementowała interfejs? Każda klasa abstrakcyjna klasa bazowa z każdą metodą abstrakcyjną metodą? To dość ogólne, ale nie jest to wcale „tak ogólne, jak to możliwe”. To pozwala ludziom zmieniać implementację dowolnej metody poprzez podklasowanie. Co jeśli chcą zmienić implementację metody bez podklasy? Możesz uczynić każdą metodę faktycznie właściwością typu delegowanego, z ustawiaczem, aby ludzie mogli zmienić każdą metodę na coś innego. Ale co, jeśli ktoś chce dodać więcej metod? Teraz każdy obiekt musi być rozszerzalny.
W tym momencie powinieneś porzucić C # i włączyć JavaScript. Ale wciąż nie jesteś wystarczająco ogólny; co jeśli ktoś chce zmienić sposób, w jaki działa wyszukiwanie członków dla tego konkretnego obiektu? Może zamiast tego powinieneś napisać wszystko w Pythonie.
Rosnąca ogólność często oznacza porzucenie przewidywalności i masywne zwiększenie kosztów testowania, aby zapewnić, że zaimplementowana ogólność rzeczywiście spełni rzeczywiste potrzeby użytkowników . Czy koszty te są uzasadnione korzyściami dla interesariuszy, którzy za nie płacą? Być może są; to do ciebie należy rozmowa z interesariuszami. Moi interesariusze wcale nie są skłonni do porzucenia pisania statycznego w celu uzyskania całkowicie niepotrzebnego i niezwykle kosztownego poziomu ogólności, ale być może są twoje.
źródło
Żeby było jasne, zrobienie czegoś uogólnionego i wdrożenie abstrakcji to dwie zupełnie różne rzeczy.
Rozważmy na przykład funkcję kopiującą pamięć.
Ta funkcja jest abstrakcją, która ukrywa sposób kopiowania 4 bajtów.
int copy4Bytes (char * pSrc, char * pDest)
Uogólnienie polegałoby na skopiowaniu przez tę funkcję dowolnej liczby bajtów.
int copyBytes (char * pSrc, char * pDest, int numBytesToCopy)
Abstrakcja nadaje się do ponownego użycia, podczas gdy uogólnienie sprawia, że abstrakcja jest przydatna w wielu przypadkach.
Bardziej konkretnie związane z twoim pytaniem, Abstrakcja jest przydatna nie tylko z perspektywy ponownego użycia kodu. Często poprawne wykonanie kodu sprawi, że Twój kod będzie bardziej czytelny i łatwy w utrzymaniu. Korzystając z powyższego przykładu, co jest łatwiejsze do odczytania i zrozumienia, jeśli przeglądasz kod copyBytes () lub pętlę for iterującą po tablicy przenoszącej dane jeden indeks na raz? Abstrakcja może zapewnić rodzaj własnej dokumentacji, która moim zdaniem ułatwia pracę z kodem.
Zgodnie z moją podstawową zasadą, jeśli mogę wymyślić dobrą nazwę funkcji, która dokładnie opisuje to, co zamierzam zrobić, to piszę dla niej funkcję, niezależnie od tego, czy myślę, że użyję jej ponownie.
źródło
Dobrą ogólną zasadą tego rodzaju rzeczy jest zero, jeden, nieskończoność. Oznacza to, że jeśli potrzebujesz tego, co piszesz więcej niż jeden raz, możesz założyć, że będziesz potrzebować tego jeszcze więcej razy i uogólnij. Ta zasada oznacza, że nie zawracasz sobie głowy abstrakcją przy pierwszym napisaniu czegoś.
Innym dobrym powodem tej reguły jest to, że przy pierwszym pisaniu kodu niekoniecznie będziesz wiedział, co abstrahować, ponieważ masz tylko jeden przykład. Prawo Murphy'ego oznacza, że jeśli po raz pierwszy napiszesz kod abstrakcyjny, drugi przykład będzie miał różnice, których się nie spodziewałeś.
źródło
Eric Lippert zwraca uwagę na trzy rzeczy, które moim zdaniem mają zastosowanie w jego artykule dotyczącym przyszłego projektu . Myślę, że jeśli będziesz go przestrzegać, będziesz w dobrej formie.
źródło
To zależy od tego, dlaczego programujesz, od celu twojego projektu. Jeśli wartość twojego kodu rozwiązuje konkretny problem, to chcesz to zrobić i przejść do następnego problemu. Jeśli istnieją szybkie i łatwe rzeczy, które możesz zrobić, aby ułatwić przyszłym użytkownikom kodu (w tym tobie), to zrób wszystko, co należy, aby zapewnić odpowiednie zakwaterowanie.
Z drugiej strony zdarzają się przypadki, gdy kod, który piszesz, ma bardziej ogólny cel. Na przykład, gdy piszesz bibliotekę dla innych programistów, którzy będą jej używać w wielu różnych aplikacjach. Potencjalni użytkownicy są nieznani i nie możesz zapytać ich dokładnie, czego chcą. Ale chcesz, aby Twoja biblioteka była ogólnie użyteczna. W takich przypadkach spędzam więcej czasu próbując wesprzeć ogólne rozwiązanie.
źródło
Jestem wielkim fanem zasady KISS.
Skupiam się na zapewnieniu tego, o co mnie proszono, a nie na najlepszym rozwiązaniu. Musiałem porzucić perfekcjonizm (i OCD), ponieważ sprawiało to, że byłem nieszczęśliwy.
źródło
Nie zgadzam się z „rozwiązać to głupio” , myślę, że może być bardziej „rozwiązać to mądrze” .
Co jest mądrzejsze:
Domyślnym wyborem powinien być drugi. Chyba że potrafisz wykazać potrzebę pokoleń.
Uogólnione rozwiązanie powinno być dostępne tylko wtedy, gdy wiesz, że jest to coś, co zostanie wykorzystane w wielu różnych projektach / przypadkach.
Zazwyczaj uważam, że uogólnione rozwiązania najlepiej nadają się jako „kod biblioteki podstawowej”
źródło