Właśnie przeczytałem opublikowany link do artykułu, muszę powiedzieć, że Fowler napisał kilka bardzo dobrych punktów i wiele rzeczy, które powiedział, opowiadam się z naszym zespołem od lat.
IMO, jeśli wykonasz jakiś porządny projekt, nie powinieneś wchodzić w sytuację, która byłaby uważana za ślepą uliczkę. Zawsze uważałem oprogramowanie za zbudowane z elementów . Nadal wierzę w pewne wstępne projekty, ale głównym celem nie jest zaprojektowanie całego produktu, ale zapewnienie ogólnej architektury / kierunku, aby Twój zespół mógł wyobrazić sobie wspólny obraz, nad którym wszyscy pracujemy. Jeśli masz kilka kostek i trójkątów, warto naszkicować, w jaki sposób zamek zostałby złożony, zanim zaczniesz po prostu uderzać klockami.
Ponieważ pochodzę z ziemi OO, dla mnie każdy blok jest klasą, a powierzchnia tego bloku jest interfejsem publicznym (co jest widoczne dla klas zewnętrznych lub pochodnych). Jeśli będziesz przestrzegać dobrych zasad SOLID, upewnisz się, że każdy blok jest wyjątkowo prosty i ma intuicyjny interfejs publiczny. Wracając do mojej analogii, chcesz mieć pewność, że kod tworzy tylko proste kształty. Za każdym razem, gdy tworzysz zbyt złożone klasy (wiele funkcji, wiele zmiennych), tworzysz kształty, które trudno wykorzystać ponownie, gdy zmieniają się wymagania.
Zgadzam się z Fowlerem, że największym ryzykiem / wyzwaniem związanym z projektowaniem ewolucyjnym jest pozostawienie decyzji projektowych czasowi kodowania i oczekiwanie od każdego dewelopera podjęcia takich decyzji. W tym miejscu system może się zepsuć, jeśli nie masz odpowiednich mechanizmów sprzężenia zwrotnego. Ilekroć pojawia się prośba o nową funkcję, niezwykle kuszące jest po prostu znalezienie funkcji, którą należy rozszerzyć, umieszczenie w niej jakiegoś warunku i dodanie do niej całej wiązki kodu. Czasami może to być wszystko, czego potrzeba, ale jest to również (IMO) najczęstsza praktyka prowadząca do ślepych zaułków. Nie ma to nic wspólnego z projektowaniem ewolucyjnym. To się nazywa „brak projektu”.
Tak długo, jak poświęcisz czas, aby się cofnąć i powiedzieć: poczekaj chwilę, ta klasa ma już 15 zmiennych składowych, pozwól mi wyodrębnić 6 z nich i umieścić je w swojej własnej, zamkniętej klasie, twoje oprogramowanie będzie się składać z bardzo lekkiego - lekkie, elastyczne i wielokrotnego użytku bloki konstrukcyjne. Jasne, że jeśli pojawią się premierzy i zmienią o połowę wymagania dotyczące produktów, być może będziesz musiał usunąć niektóre swoje klocki, odłożyć je z powrotem na półkę i dobrać nowe (tak jak podczas budowania zamku, nie możesz użyć wszystkich twoje cylindry). Ale w tym momencie to tylko część robienia interesów. Wymagania się zmieniły i zachowując elastyczność i modułowość kodu, powinieneś być w stanie zmienić swój produkt, aby dostosować go do nowego kierunku działalności.
Wierzę, że to ewolucyjne podejście do projektowania działa na każdym poziomie umiejętności inżyniera. Osobiście tworzyłem oprogramowanie przez bardzo długi czas i zanim nasz zespół przeszedł na zwinną metodologię, byłem odpowiedzialny za wysyłkę kilku głównych komponentów z mojego komputera deweloperskiego prawie bezpośrednio do klienta przy prawie żadnej kontroli jakości. Jednocześnie elementy te zawsze były elastyczne i łatwe w utrzymaniu.
Próbuję tylko powiedzieć, że uważam się za względnie przyzwoitego w projektowaniu oprogramowania. Jednocześnie, jeśli poprosiłeś mnie o napisanie 100-stronicowego dokumentu projektowego, przekazanie go programistowi i oczekiwanie, że zadziała, prawdopodobnie nie mógłbym zaprojektować się z papierowej torby. Kiedy zaczynałem pracę, czasami szkicowałem kilka diagramów podobnych do UML (bardzo uproszczonych, ale nie w pełnym języku), ale kiedy zaczynam kodować, refaktoryzowałem według potrzeb, a mój końcowy kod nigdy nie wyglądałby tak, jak pierwotnie narysowałem. Nawet jeśli spędzam miesiąc lub dwa, zastanawiając się nad każdym najmniejszym szczegółem, nie mogę sobie wyobrazić, że ktoś inny może wziąć moje diagramy i wymyślić solidne oprogramowanie bez zmiany projektu podczas kodowania.
Na drugim końcu spektrum, obecnie w moim zespole (teraz zwinny i w pełni to popieram) mamy kilku facetów, którzy dołączyli do nas z zagnieżdżonej ziemi, gdzie zajmowali C tylko przez ostatnie 15 lat. Oczywiście pomogłem przy wstępnym planowaniu i układaniu klas, ale zadbałem również o regularne przeglądy kodu i sesje burzy mózgów, podczas których omawiamy zastosowania SOLID i zasad projektowania. Stworzyli kod spaghetti, który sprawił, że trochę się skrzywiłem, ale po lekkim trąbieniu zacząłem refaktoryzować to, co już zostało wyprodukowane, a zabawne jest to, że jeden z nich wrócił do mnie kilka dni później i powiedział: Nienawidzę żeby to powiedzieć, ale po przeniesieniu tego kodu wygląda to o wiele bardziej czytelnie i zrozumiale. Ślepy zaułek odwrócony. Punkt I Staram się, aby nawet ktoś, kto jest zupełnie nowy w OO, mógł stworzyć całkiem przyzwoity kod, o ile ma mentora z większym doświadczeniem, aby przypomnieć mu, że „projekt ewolucyjny” to nie to samo, co „brak projektu”. I nawet niektóre z jego „bardziej złożonych” klas nie są aż tak przerażające, ponieważ każda klasa nie ma tak dużej odpowiedzialności (tj. Niezbyt dużego kodu), więc najgorsze staje się gorzej, jeśli ta klasa „ślepych zaułków”, my rzuć to i napisz klasę zastępczą, która ma ten sam publiczny interfejs (do tej pory nigdy nie widziałem potrzeby takiej nieprzewidzianej treści w żadnym napisanym artykule i robiłem recenzje kodu dwa razy w tygodniu).
Na koniec jestem również zwolennikiem dokumentów projektowych (przynajmniej w warunkach biznesowych mojego obecnego zespołu), ale głównym celem naszych dokumentów projektowych jest Pamięć Organizacyjna , więc rzeczywiste dokumenty są pisane po wygenerowaniu kodu i odnowione. Przed kodowaniem generalnie mamy szybką (czasem nie tak szybką) fazę projektowania, w której szkicujemy klasy na serwetkach / mspaint / visio i zawsze przypominam ludziom, że ta faza tworzy ścieżkę do naśladowania, a nie plan, a kiedy zaczynają kodować, wszystko, co nie ma sensu, powinno zostać zmienione. Nawet z tymi przypomnieniami nowi faceci starają się przywrócić kod do oryginalnego projektu, bez względu na to, jak nienaturalnie wydaje się im nawet. Zwykle pojawia się to w recenzjach kodu.
Dang, dużo pisałem. Przepraszam za to.
Powiedziałbym, że zjawisko „projektowania ślepego zaułka” jest ortogonalne w stosunku do metod zwinnych. Mam na myśli to, że można zrobić wodospad, spędzić dużo czasu z góry na (złym) projekcie. Następnie poświęć dużo czasu na jego wdrożenie, aby znaleźć się w ślepym zaułku.
W ogóle metody zwinne powinny pomóc ci wcześniej odkryć, że dokonałeś złych wyborów projektowych. Powodem tego jest to, że twoje zaległości powinny najpierw wykonać elementy o najwyższej wartości dla klienta i powinieneś skupić się na dostarczaniu użytecznych przyrostów oprogramowania. Jeśli twój projekt pozwala na dostarczenie wysokiej wartości i użyteczności, jest już na coś dobry :-) W przeciwieństwie do tego, możesz mieć zły projekt w wodospadzie, w którym przez wiele lat możesz się nie dowiedzieć, że ten projekt nie może dostarczyć dowolna wartość i użyteczność - wszystko, co masz, to złudzenie, że jest to dobry projekt. Jak mówią, dowodem jest pudding.
Drugą stroną jest to, że nawet w metodach zwinnych ważne jest, aby mieć realną wizję projektu systemu, który kieruje decyzjami od iteracji do iteracji. Myślę, że Ken Schwabber powiedział coś takiego: jeśli masz zespół okropnych programistów, będą oni produkować złe oprogramowanie konsekwentnie iteracyjnie przez iterację. Zwinność oznacza po prostu, że nie spędzasz dużo czasu z góry, ponieważ masz ograniczoną wiedzę, którą możesz się nauczyć lub sobie wyobrazić przed rozpoczęciem wdrażania ( a wymagania również się zmieniają). Są jednak sytuacje, w których musisz wykonywać pracę z góry (np. Badania), a następnie musisz to zrobić.
Jak uniknąć ślepych uliczek?
Powiedziałbym głównie, przewidując przyszłe wymagania. Jest to coś, co zyskujesz dzięki doświadczeniu i znajomości podobnych projektów / produktów. To oczekiwanie jest częściowo tym, co pomaga wdrożyć dobry projekt, ponieważ zadajesz sobie wiele pytań „a co jeśli” na temat twojego obecnego systemu. Dla mnie jest to kluczowy element. Techniki takie jak OO pomagają ci, gdy już wiesz, co robisz.
Co robisz, jeśli masz ślepy zaułek?
„Ślepy zaułek” nie różni się niczym od jakiegokolwiek innego bloku technicznego, który trafisz podczas opracowywania czegoś nowego. Pierwszą rzeczą do zrozumienia jest to, że tak naprawdę nie ma prawdziwych „ślepych zaułków”, które zmusiłyby cię do całkowitego wycofania się. Przynajmniej nauka do tego momentu pozwala ci iść naprzód, więc wysiłek nie został zmarnowany. Kiedy trafisz w ślepy zaułek, masz problem . Problemem jest to, co należy zmienić, aby spełnić nowe (lub stare) wymagania i jak zoptymalizować dokonanie tej zmiany. Wszystko, co musisz teraz zrobić, to rozwiązać ten problem. Bądź wdzięczny, że jest to oprogramowanie, a nie np. Projekt samolotu, ponieważ zmiana jest znacznie łatwiejsza. Zidentyfikuj problemy, napraw je == refactor == inżynieria oprogramowania. Czasami wymaga to dużo pracy ...
Jeśli używasz Scruma, zmiana ta powinna oczywiście wynikać z historii użytkowników (co użytkownik zyskuje na tej zmianie?). Proces zaczynałby się od jednej historii, która nie może być łatwo zaakceptowana przez obecny projekt (ups) i odbyłaby się dyskusja z właścicielem produktu na temat tego, jak rozbić tę historię. Przez tę zmianę nadal stosujesz zwinne zasady.
Kilka znanych wielkich zmian wymagań ze świata OS, które przychodzą mi do głowy:
Niezależnie od tego, jak na nie spojrzysz, są to dużo pracy. Oryginalny projekt prawie na pewno nie uwzględniał możliwości takiego zdarzenia (tj. Poręczność nie była dużym wymogiem). To, czy projekt był OO, czy też nie, prawdopodobnie nie jest dużym czynnikiem. W dobrym projekcie części specyficzne dla platformy byłyby nieco odizolowane, a praca byłaby łatwiejsza.
źródło
Stale zmieniam projekty i korzystam z diagramów klas UML. Mam na myśli to, że tworzę jeden lub więcej diagramów klas według pakietów. Każdy diagram jest zapisywany w katalogu głównym pakietu. Każdy klasyfikator UML ma własny identyfikator, który jest odwzorowany na powiązany identyfikator Java. Oznacza to, że kiedy otwieram mój diagram, jest on automatycznie aktualizowany do najnowszych zmian refaktoryzacji kodu. Mogę również bezpośrednio zmieniać diagramy klas na poziomie graficznym, a cały mój projekt jest natychmiast refaktoryzowany. Działa całkiem dobrze, ale nigdy nie zastąpi człowieka. Mój diagram klas UML jest również tylko graficznym widokiem mojego kodu. Bardzo ważne jest, aby nie mieszać kodu i modelu, takiego jak zaćmienie EMF, ponieważ po dokonaniu refaktoryzacji tracone są również informacje o modelu. Nigdy nie używam generatora kodu Model Driven Development, ponieważ jest to bezużyteczne. Ja nie
Powiedziawszy, że posiadanie ponad 100 klasowych diagramów reprezentujących wszystkie szczegóły struktury mojego projektu i pełne notatek wszędzie jest naprawdę pomocne. Tworzę tylko diagramy klas dla projektów, ponieważ zwykle programiści nie mają czasu na naukę lub używanie innych diagramów. Diagramy klas są również bardzo dobre, ponieważ są automatycznie aktualizowane. Diagramy klas można tworzyć po kodzie, po prostu odwracając pakiet i dodając notatki. Jest szybki i zawsze dokładny oraz w 100% iteracyjny.
Proszę nie mylić rozwoju opartego na modelu, który jest kodem generującym model, i zwykle używa UML jako prezentacji graficznej z diagramami klas UML zaktualizowanymi z kodu. Tylko zsynchronizowany kod UML ma dla mnie prawdziwą wartość, jeśli jest wiele iteracji.
Przepraszam, że tak długo, ale myślę, że powinniśmy dać drugą szansę diagramom klas UML, jeśli byłyby użyte tylko jako graficzny widok naszego projektu. Oznacza to, że UML obejmuje pełny projekt i ma jeden model złożony z diagramów dużych klas reprezentujących pełny projekt. Byłoby absurdalnie mieć setki małych widoków i model dla każdego widoku w projekcie mającym setki widoków :-)
źródło
Osiągnąłem ślepy zaułek mój kod i inne kody z powodu złego projektu, zmiany kierunku itp. Widziałem również wiele innych osób napotykających ten problem. Wielkim błędem (przynajmniej wydaje mi się, że to pomyłka) jest natychmiastowe pragnienie wyrzucenia działającego kodu i ponownego wdrożenia wszystkiego od podstaw.
Do każdej sprawy podszedłem w ten sam sposób, który wydawał się działać dobrze:
Koszty:
Korzyści:
źródło
Około miesiąc lub dwa lata temu nasz obecny projekt utknął w martwym punkcie z powodu złych decyzji projektowych (i braku dużej ilości projektu w jednym miejscu) w stylu rozwoju SCRUM.
Naszym rozwiązaniem (i moim zdaniem standardowym dla SCRUM) było poświęcenie całego sprintu (~ 2 tygodnie) wyłącznie na refaktoryzację. W tym czasie nie dodano żadnej nowej funkcji, ale mogliśmy pomyśleć o obecnej bazie kodu i zaprojektować znacznie lepszy system do tego, co robiliśmy.
Przeszliśmy już tę przeszkodę i ponownie dodaliśmy nowe funkcje.
źródło
Kluczem do ograniczenia kosztów zmian w projekcie jest utrzymanie kodu w stanie SUCHYM, jak to możliwe. Spowoduje to przeniesienie większości kodu aplikacji na bardzo wysoki poziom, gdzie większość kodu bezpośrednio wyraża intencję, a stosunkowo mało określa mechanizm. Jeśli to zrobisz, decyzje projektowe będą miały najmniejsze możliwe wyrażenie w kodzie, a zmiany projektowe będą miały możliwie najmniejszy koszt.
źródło
Kluczem do uniknięcia ślepych uliczek projektu jest jak najwcześniejsze rozpoznanie, kiedy projekt wymaga zmiany, a następnie zmiana. Największe problemy nie wynikają z ciągłej ewolucji projektu, ale z odmowy rozwinięcia projektu, dopóki nie stanie się on wielkim problemem.
Na przykład Netflix ma funkcję profilu, w której różni członkowie rodziny mogą rozliczać się z tego samego planu, ale mają osobne kolejki. Kilka lat temu ogłosili, że będą musieli anulować tę funkcję, ponieważ tylko około 10% jej użytkowników korzystało z niej, ale z powodu włamania do implementacji pochłaniała ona nadmierną ilość prac konserwacyjnych. Po wrzawie ugryzli kulę i przeprowadzili kosztowną przeprojektowanie, aby zatrzymać tych klientów.
Jestem pewien, że byli inżynierowie, którzy rozpoznali nieoptymalny projekt, kiedy po raz pierwszy dodali tę funkcję. Gdyby to wtedy zmienili, nie byłoby to aż tak duże.
źródło
Czy to nie Fred Brooks powiedział coś w stylu „Plan wyrzucenia pierwszego”? Nie czuj się zbyt ponuro, ślepe projekty pojawiają się również w projektach, które starają się wykonać cały projekt z góry. Przeprojektowanie ma miejsce we wszystkich rodzajach rozwoju, czy to dlatego, że od samego początku był to niewykonalny projekt (te ostatnie 20%, które zostały pomalowane - „diabeł tkwi w szczegółach”), czy też dlatego, że klient zmienił skupienie. Nie ma potrzeby używania dzwonków alarmowych, nie martw się zbytnio.
źródło