Legacy Code Nightmare [zamknięty]

Odziedziczyłem projekt, w którym diagramy klas bardzo przypominają pajęczą sieć na talerzu spaghetti. Napisałem około 300 testów jednostkowych w ciągu ostatnich dwóch miesięcy, aby zapewnić sobie zabezpieczenie obejmujące główny plik wykonywalny.

W każdej chwili mam w zasięgu moją bibliotekę agile development books:

  • efektywna praca z kodem starszym
  • Refaktoryzacja
  • Code Complete
  • wzorce zasad zwinności i Praktyki w C #
  • itd.

Problem w tym, że wszystko, czego dotknę, wydaje się łamać coś innego. Klasy interfejsu mają logikę biznesową i Kod bazy danych. Istnieją wzajemne zależności między wieloma klasami. Jest kilka klas Bożych, które się psują za każdym razem, gdy zmieniam inne klasy. Istnieje również zmutowana Klasa singleton / utility z około metodami pół instancji i pół metodami statycznymi (choć jak na ironię metody statyczne polegają na instancji i metody instancji nie).

Moi poprzednicy uważali nawet, że mądrze byłoby użyć wszystkich zestawów danych wstecz. Każda aktualizacja bazy danych jest wysyłana bezpośrednio do serwera db jako parametry w procedurze składowanej, a następnie zbiory danych są ręcznie odświeżane, dzięki czemu interfejs wyświetli najnowsze zmiany.

Czasami kusi mnie myśl, że używali jakiejś formy słabego zaciemniania dla bezpieczeństwa pracy lub jako ostatnie pożegnanie przed przekazaniem kodu.

Czy są jakieś dobre zasoby za rozczesywanie tego bałaganu? Książki, które mam, są pomocne, ale wydają się obejmować tylko połowę scenariuszy, na które wpadam.

Author: Kenneth Cochran, 2009-03-17

13 answers

Wygląda na to, że radzisz sobie z tym we właściwy sposób.

  • Test
  • Refaktor
  • Test ponownie

Niestety, może to być powolny i żmudny proces. Naprawdę nie ma zastąpienia kopania i zrozumienia, co kod próbuje osiągnąć.

Jedna książka, którą mogę polecić (Jeśli jeszcze jej nie masz pod " itd.") jest Refaktoryzacją do wzorców. Jest skierowany do ludzi, którzy są w twojej sytuacji.

 24
Author: Bill the Lizard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-17 16:12:26

Pracuję w podobnej sytuacji.

Jeśli nie jest to małe narzędzie, ale duży projekt przedsiębiorstwa, to jest to:

A) too late to fix it
b) poza możliwościami jednej osoby do próby a)
c) może być naprawiony tylko przez całkowite przepisanie rzeczy, które nie wchodzi w grę

Refaktoryzacja w wielu przypadkach może być podejmowana tylko w czasie prywatnym na własne ryzyko. Jeśli nie masz wyraźnego mandatu, aby to zrobić w ramach swojej codziennej pracy więc prawdopodobnie nawet nie dostaniesz za to uznania. Może być nawet krytykowany za "bezcelowe marnowanie czasu na coś, co doskonale działa już od dawna".

Po prostu kontynuuj hakowanie go w sposób, w jaki został wcześniej zhakowany, otrzymuj wypłatę i tak dalej. Kiedy będziesz całkowicie sfrustrowany lub system osiągnie punkt, w którym nie da się dalej zhakować, znajdź inną pracę.

EDIT: ilekroć próbuję poruszyć kwestię prawdziwej architektury i robienia rzeczy w odpowiedni sposób zwykle dostaję LOL w twarz bezpośrednio od odpowiedzialnych menedżerów, którzy mówią coś w stylu " mam gdzieś dobrą architekturę "(próba tłumaczenia z niemieckiego). Ja osobiście przyniósł jeden bardzo zły komponent do punktu non-hackability, podczas gdy oczywiście dał zaawansowane Ostrzeżenia miesięcy wcześniej. Następnie musieli anulować niektóre obiecane funkcje klientom, ponieważ nie było to już wykonalne. Nikt już go nie dotyka...

 18
Author: User,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-17 16:47:29

Pracowałem już w tej pracy. Spędziłem nieco ponad dwa lata na dziedzicznej bestii, która jest bardzo podobna. Dwóch z nas zajęło nam ponad rok, aby wszystko ustabilizować (nadal jest zepsute, ale jest lepiej).

Pierwsza rzecz -- uzyskać wyjątek logowania do aplikacji, Jeśli jeszcze nie istnieje. Użyliśmy FogBugz i zajęło nam około miesiąca, aby zintegrować raportowanie z naszą aplikacją; nie było to idealne od razu, ale automatycznie zgłaszało błędy. Zazwyczaj jest całkiem bezpiecznie zaimplementuj bloki try-catch we wszystkich swoich wydarzeniach, a to pokryje większość błędów.

Stamtąd naprawić błędy, które pojawiają się jako pierwsze. Następnie walcz w małych bitwach, zwłaszcza tych opartych na błędach. Jeśli naprawisz błąd, który nieoczekiwanie wpływa na coś innego, przefaktoruj ten blok tak, aby został oddzielony od reszty kodu.

Potrzeba ekstremalnych środków, aby przepisać dużą, krytyczną dla sukcesu firmy aplikację, bez względu na to, jak jest zła. Nawet Ty masz pozwolenie na tak więc będziesz spędzać zbyt dużo czasu na wspieraniu starszej aplikacji, aby i tak poczynić postępy w przepisywaniu. Jeśli zrobisz wiele małych refaktoringów, w końcu albo te duże nie będą aż tak duże, albo będziesz miał naprawdę dobre klasy fundamentowe do przepisywania.

Jedną rzeczą, którą należy od tego zabrać, jest to, że jest to wspaniałe doświadczenie. To będzie frustrujące, ale wiele się nauczysz.

 8
Author: Austin Salonen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-22 16:02:17

Kiedyś natknąłem się na kod, który był tak obłędnie splątany, że nie mogłem go naprawić funkcjonalnym duplikatem w rozsądnym czasie. To był szczególny przypadek, ponieważ był to parser i nie miałem pojęcia, ilu klientów może "używać" niektórych błędów, które miał. Renderowanie setek "działających" plików źródłowych nie było dobrym rozwiązaniem.

Przez większość czasu jest to wykonalne, po prostu zniechęcające. Przeczytaj tę refaktoryzację.

Ogólnie zaczynam naprawianie złego kodu poprzez przenoszenie rzeczy wokół (bez zmieniania kodu implementacji bardziej niż jest to wymagane), tak aby moduły I klasy były przynajmniej w pewnym stopniu spójne.

Kiedy to zrobisz, możesz wziąć swoją bardziej spójną klasę i przepisać jej wnętrzności, aby wykonać dokładnie w ten sam sposób, ale tym razem z sensownym kodem. Jest to trudna część z zarządzaniem, ponieważ na ogół nie lubią słyszeć, że zajmie ci tygodnie kodowanie i debugowanie czegoś, co zachowa się dokładnie tak, jak to możliwe to samo (jeśli wszystko pójdzie dobrze).

Podczas tego procesu gwarantuję, że odkryjesz mnóstwo błędów i głupstw projektowych. W porządku jest naprawiać trywialne błędy podczas rekodowania, ale w przeciwnym razie zostaw takie rzeczy na później.

Gdy zrobi się to za pomocą kilku klas, zaczniesz widzieć, gdzie rzeczy można lepiej modularyzować, lepiej zaprojektować itp. Plus będzie łatwiej dokonać takich zmian bez wpływu na niepowiązane rzeczy, ponieważ kod jest teraz bardziej modularny i pewnie wiesz dokładnie.

 4
Author: T.E.D.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-22 14:37:39

W większości, to brzmi dość źle. Ale nie rozumiem tej części:

Moi poprzednicy nawet myśleli, że będzie bądź sprytny, aby korzystać ze wszystkich zestawów danych do tyłu. Każda aktualizacja bazy danych jest wysyłane bezpośrednio do serwera db jako parametrów w procedurze składowanej, a następnie zestawy danych są ręcznie odświeżane tak interfejs wyświetli najnowszą zmiany.

To brzmi dość blisko sposobu, w jaki często piszę rzeczy. Co w tym złego? Co jest poprawne sposób?

 1
Author: recursive,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-17 16:15:56

Jeśli Twoje refaktoryzacje łamią kod, szczególnie kod, który wydaje się być niezwiązany, to próbujesz zrobić za dużo na raz.

Polecam refaktoryzację pierwszego przejścia, w której wszystko co robisz to ekstrakcja method: celem jest po prostu nazwanie każdego kroku w kodzie, bez żadnych prób konsolidacji.

Potem pomyśl o zerwaniu zależności, zastąpieniu singletonów, konsolidacji.

 1
Author: kdgregory,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-17 16:31:23

Jeśli Twoje refaktoringi niszczą rzeczy, oznacza to, że nie masz odpowiedniego pokrycia testów jednostkowych - ponieważ testy jednostkowe powinny być najpierw uszkodzone. Polecam uzyskać lepszy zasięg testów jednostkowych po zalogowaniu się do wyjątków.

Polecam najpierw zrobić małe refaktoryzacje-metodę wyodrębniania, aby rozbić duże metody na zrozumiałe części; wprowadzić zmienną, aby usunąć niektóre duplikacje w metodzie; może wprowadzić parametr, jeśli znajdziesz duplikację między zmienne używane przez rozmówców i rozmówcę.

I uruchom zestaw testów jednostkowych po każdym refaktoringu lub zestawie refaktoringów. Powiedziałbym, uruchom je Wszystkie dopóki nie zdobędziesz pewności, które testy będą musiały być powtarzane za każdym razem.

 1
Author: John Saunders,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-17 17:01:03

Żadna książka nie będzie w stanie pokryć wszystkich możliwych scenariuszy. Zależy to również od tego, czego będziesz oczekiwać od projektu i czy istnieje jakaś zewnętrzna Specyfikacja.

  • Jeśli będziesz musiał robić tylko sporadyczne małe zmiany, po prostu zrób to i nie kłopocz się zaczynaniem refakturowania.
  • Jeśli istnieje Specyfikacja (lub możesz poprosić kogoś, aby ją napisał), rozważ całkowite przepisanie, jeśli może to być uzasadnione przewidywalną ilością zmian w projekcie
  • Jeśli "implementacja jest specyfikacją" i zaplanowano wiele zmian, więc jesteś prawie gotowy. Napisz wiele testów jednostkowych i rozpocznij refaktoryzację w małych krokach.

Właściwie, testy jednostkowe będą bezcenne bez względu na to, co robisz (jeśli możesz je napisać do interfejsu, który nie zmieni się zbytnio przy refaktoringach lub przepisywaniu, czyli).

 1
Author: Michael Borgwardt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-22 15:59:13
 1
Author: Nicolas Dorier,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-22 16:58:30

Można wyodrębnić, a następnie refaktoryzować jego część, aby rozdzielić zależności i wyizolować warstwy na różne moduły, biblioteki, zespoły, katalogi. Następnie ponownie wstrzykuje się oczyszczone Części do aplikacji za pomocą aplikacji . / Align = "left" /

 0
Author: philant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-06 12:55:20

Powodzenia, to jest trudna część bycia deweloperem.

Myślę, że Twoje podejście jest dobre, ale musisz skupić się na dostarczaniu wartości biznesowej (liczba testów jednostkowych nie jest miarą wartości biznesowej, ale może dać ci wskazanie, czy jesteś na torze lub poza nim). Ważne jest, aby zidentyfikować zachowania, które należy zmienić, ustalić priorytety i skupić się na najlepszych.

Druga rada to pozostać pokornym. Uświadom sobie, że jeśli napisałeś coś tak dużego pod prawdziwe terminy i ktoś inny widział Twój kod, prawdopodobnie też miałby problemy ze zrozumieniem go. Jest umiejętność pisania czystego kodu, a jest ważniejsza umiejętność radzenia sobie z cudzym kodem.

Ostatnią radą jest próba wykorzystania reszty zespołu. Poprzedni członkowie mogą znać informacje o systemie, którego możesz się nauczyć. Mogą również pomóc w testowaniu zachowań. Wiem, że ideałem jest mieć zautomatyzowane testy, ale jeśli ktoś może pomóc weryfikując rzeczy dla Ciebie ręcznie rozważyć uzyskanie ich pomocy.

 0
Author: Frank Schwieterman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-22 16:04:13

Szczególnie podoba mi się schemat w Kod kompletny, w którym zaczynasz od kodu starszego, prostokąta o rozmytej szarej teksturze. Następnie po zastąpieniu niektórych z nich masz rozmyty szary na dole, biały na górze i postrzępioną linię reprezentującą interfejs między nimi.

Oznacza to, że wszystko jest albo 'paskudne stare rzeczy', albo 'ładne nowe rzeczy'. Po jednej lub drugiej stronie linii.

Linia jest postrzępiona, ponieważ migrujesz różne części system w różnym tempie.

W trakcie pracy, postrzępiona linia stopniowo opada, aż będziesz miał więcej bieli niż szarości, a w końcu tylko szarości.

Oczywiście, to nie ułatwia Ci szczegółów. Ale daje Ci model, którego możesz użyć do monitorowania swoich postępów. W każdym momencie powinieneś mieć jasne zrozumienie, gdzie znajduje się linia: które bity są nowe, które są stare i jak obie strony się komunikują.

 0
Author: slim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-22 16:05:55

Poniższy post może okazać się przydatny: http://refactoringin.net/?p=36

Jak to jest powiedziane w poście, nie odrzucaj pełnego nadpisania tak łatwo. Ponadto, jeśli to możliwe, spróbuj zastąpić całe warstwy lub warstwy rozwiązaniem innych firm, takim jak na przykład ORM dla trwałości lub nowym kodem. Ale co najważniejsze, spróbuj zrozumieć logikę (problem domeny) za kodem.

 0
Author: Dan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-11 08:24:09