Jak profesjonalne zespoły programistów radzą sobie ze złożonością projektu w nietrywialnych projektach?

9

Po pierwsze, zdaję sobie sprawę, że to pytanie może być nieco długie i niejasne i przepraszam za to. Jest to prawdopodobnie podstawowy problem z krótką nazwą dla każdego, kto go „rozumie”, ale ponieważ brakuje mi w tym względzie, proszę o wyrozumiałość przy opisywaniu problemu.

Programowałem w ten czy inny sposób, odkąd miałem około 11 lat. Oznacza to, że głównie od samego początku uczyłem się wszystkiego. Uzyskałem wykształcenie techniczne, ale nie wyłącznie informatyki (ukończyłem studia z inżynierii fotonicznej). Oczywiście mieliśmy kursy programowania, ale były to dla mnie głównie podstawowe rzeczy i nie nauczyłem się zbyt wielu nowych rzeczy. Ciągle kształciłem się po drodze z radości i zawsze wiedziałem, że będę kontynuował karierę programistyczną, ale wszystkie moje projekty były wtedy dość małe. Nie miałem problemu z utrzymaniem ich w pamięci i utrzymaniem ich.

Teraz uważam się za lidera w zespole, ale nie w środowisku korporacyjnym - pracuję dla uniwersytetu opracowując oprogramowanie naukowe (w C ++) do zastosowań inżynieryjnych. Nagle projekt staje się (relatywnie) duży i przez większość czasu nie mogę się nim skupić. Tracę dużo czasu i wysiłku głównie na dwie rzeczy:

  1. Kiedy muszę wrócić do części kodu, nad którą nie pracowałem przez jakiś czas, mam trudności z zapamiętaniem, jak to działało. Spędzam dużo czasu przeglądając pliki nagłówkowe odpowiednich klas i czytając komentarze, które umieszczałem po drodze w plikach źródłowych. Chciałbym mieć jakąś formę „schematu”, którą mógłbym łatwiej dostrzec i odzyskać obraz;
  2. Kiedy wprowadzam zmiany, czasami zdaję sobie sprawę, że to, co próbuję zrobić, psuje rzeczy gdzie indziej (lub, co gorsza, pojawia się tylko w czasie wykonywania jako niespodzianka). Cofam się i zaczynam robić to inaczej, tylko po to, by przekonać się, że zaniedbałem wpływ na jakiś inny komponent. Chciałbym mieć jakiś „schemat architektury”, w którym mogłem zobaczyć, jak się to robi, jak to, co próbuję zrobić, wpłynie na inne komponenty i sposób, w jaki szczegółowo planuję, zanim zacznę wdrażać zmiany.

Większość ludzi, z którymi pracuję, ma podobne historie jak moja - silną orientację techniczną i czasem świetne umiejętności, ale bez możliwości zorganizowania swojej pracy. Jednak ich projekty są zwykle znacznie mniejsze niż moje, więc jakoś sobie z tym radzą. W każdym razie oznacza to dla mnie, że jestem sam i nie mam z kogo uczyć się dobrych praktyk.

Wziąłem podyplomowe szkolenie z zarządzania IT i chociaż uważam, że jest to całkiem satysfakcjonujące, jest ono skierowane głównie do nie-programistów, ucząc o metodologii zarządzania projektami, szacunkach budżetu / harmonogramu, architekturze przedsiębiorstwa itp. - a nie o projektowaniu i planowaniu jako takim. Zgadza się, ja też próbuję się tego nauczyć. Oczywiście wprowadzono niektóre narzędzia (takie jak UML) i typy procesów tworzenia oprogramowania (kaskadowe, iteracyjne, zwinne ...), ale oczywiście nie są one zbyt szczegółowe i trudno mi zdecydować, co powinienem wybrać i użyć ( i do jakiego stopnia).

Czytałem wiele pytań i odpowiedzi na temat projektowania oprogramowania na SO - wiele jest na temat robienia tego przy użyciu tego lub tego konkretnego narzędzia lub metodologii, a jeśli byłbym przekonany, że dokumentacja UML rozwiąże moje problemy - wybrałbym to i zacznij go używać. Ale niektórzy przysięgają, inni twierdzą, że jest to bezużyteczne. Szukam odpowiedzi na wyższym poziomie abstrakcji - czy są sposoby na rozwiązanie dwóch moich problemów i jak to robisz osobiście? Czego powinienem się nauczyć, aby móc to zrobić, być może bez powiązania z jednym konkretnym narzędziem? Te pojawiają się i znikają od czasu do czasu, i spodziewam się, że ich zastosowanie różni się w zależności od rodzaju projektu.

Bardzo dziękuję za czytanie, ale nie byłem w stanie powiedzieć, co mam na myśli w skrócie (brak doświadczenia w projektowaniu oprogramowania i słownictwa).

neuviemeporte
źródło
2
Myślę, że najczęstszą profesjonalną odpowiedzią na trudności, o których mówisz, jest „Pierdol to”, a następnie obwinianie zarządzania, produktu lub innego losowego SOB.
Edward Strange

Odpowiedzi:

9

Kiedy muszę wrócić do części kodu, nad którą nie pracowałem przez jakiś czas, mam trudności z zapamiętaniem, jak to działało. Spędzam dużo czasu przeglądając pliki nagłówkowe odpowiednich klas i czytając komentarze, które umieszczałem po drodze w plikach źródłowych.

Wyobraź sobie, jak ten biedny facet, który przyjdzie za tobą, poczuje się - nie ma nawet korzyści, że kiedyś wiedział, jak działa Twój kod. Zamiast próbować odszyfrować kod, powinieneś przejrzeć dokumentację napisaną dla danego modułu. Dokumentacja ta powinna zapewniać dość dokładny obraz tego, co moduł robi, dlaczego. Nie chodzi o to, że „moduł rozpoczyna od zainicjowania trzech tablic przy użyciu potrójnej pętli for ...”, ale zamiast tego: „ten moduł pobiera dane zebrane przez główny czujnik Fabulotron, przestawia go na standardowy format neopolitański (czekoladowy, waniliowy, truskawkowy), i dostarcza go do modułu analizy ”.

W idealnym świecie miałbyś dokument projektowy, który określa różne moduły w systemie i opisuje ich odpowiednie obowiązki, a każdy z twoich modułów może po prostu odwołać się do tego dokumentu, aby wyjaśnić, co robią: „Ten moduł zapewnia Usługa gromadzenia danych Fabulotron, jak szczegółowo opisano w sekcji 4.8 dokumentu projektowego: http://fabulotron.org/design/section4-8.html . ” Jeśli nie masz czegoś takiego, zacznij spisywać przegląd każdego modułu, pracując nad nim. Nie musisz pisać książki - często wystarczy kilka akapitów, aby uzyskać orientację.

Kiedy wprowadzam zmiany, czasami zdaję sobie sprawę, że to, co próbuję zrobić, psuje rzeczy gdzie indziej (lub, co gorsza, pojawia się tylko w czasie wykonywania jako niespodzianka). Cofam się i zaczynam robić to inaczej, tylko po to, by przekonać się, że zaniedbałem wpływ na jakiś inny komponent.

Może to wskazywać, że Twoje moduły są zbyt połączone. Im bardziej niezależne możesz uczynić swoje moduły / klasy / jednostki, tym mniej prawdopodobne jest, że napotkasz tego rodzaju problem. Staraj się, aby interfejsy między modułami były jak najbardziej wyraźne i ograniczaj je do tego, co musi tam być. Interfejs jest umową - jeśli wiesz, że jakiś moduł spełnia swoje obowiązki określone w interfejsie, nie musisz nic więcej o nim wiedzieć. Zapobiega to wpływowi zmian w module, nad którym pracujesz, na inne moduły.

Chciałbym mieć jakiś „schemat architektury”, w którym mogłem zobaczyć, jak się to robi

Zastosowanie standardowych części może w tym pomóc. C ++ zapewnia standardowe części w postaci Standardowej Biblioteki Szablonów, a użycie tych części w odpowiednich przypadkach pozwala pracować na wyższym poziomie abstrakcji. Jeśli napisałeś własny kod do zarządzania strukturami danych, takimi jak listy, ty i te, które będziesz za nimi podążał, będziesz musiał stale czytać źródło, aby dowiedzieć się, co się dzieje. Jeśli zamiast tego użyjesz standardowych części dostarczonych przez STL, każdy programista C ++ będzie w stanie szybko powiedzieć, co robi Twój kod, bez wnikania w procedury zarządzania danymi.

Kolejny rodzaj części standardowej pochodzi z wzorów projektowych. Są to standardowe pojęcia, które można wykorzystać jako skrót do wyjaśnienia, jak działa relacja między dwoma obiektami.

Caleb
źródło
Dziękuję za odpowiedź. Oczywiście używam STL od wielu lat, ale sekwencja kroków, które wykonuje mój program, aby wykonać przemyślane obliczenia, jest czasami trudna do wyobrażenia w całości, nawet przy jego użyciu. To samo dotyczy modułów. Nie miałem na myśli zmiany jednego, który się psuje, ale raczej tego, że zmiana czegoś gdzieś powoduje usterkę, np. Gdy użytkownik robi coś niestandardowego w interfejsie GUI, gdzie skomplikowana sekwencja jest dodatkowo komplikowana przez nieprzewidywalną kolejność kroków, które należy wykonać, aby to zrobić.
neuviemeporte
5

Byłem profesjonalnym programistą tylko przez krótki okres czasu i miałem problemy z tym, jak to zrobić, kiedy zaczynałem. Byłem przede wszystkim samokształcony, nawet przez uniwersytet. Na szczęście dla mnie ludzie, z którymi pracowałem, mają duże doświadczenie i byli w stanie nauczyć mnie sposobów zarządzania dużymi projektami i pracy z nimi.

Jedną z pierwszych rzeczy, które mnie zmusiły, było usiąść i przeczytać czysty kod . To fantastyczna książka, która pomogła mi zrozumieć, jak napisać kod, który mógłbym zrozumieć, gdy wróciłem do niego lub który mógłby zrozumieć ktoś inny.

Drugą rzeczą było napisanie testów dobrej jakości, Jednostka, Integracja, Akceptacja. Jeśli Twój kod jest dobrze przetestowany, szybko dowiesz się, kiedy coś zepsułeś i szybko będziesz w stanie zdiagnozować problem. W Internecie jest mnóstwo dobrych zasobów do testowania i nie jestem pewien, które z nich najlepiej Ci zasugerować.

Moje kluczowe punkty to Testowanie i Czysty kod.

Klee
źródło
Dzięki za sugestię, z pewnością sprawdzę książkę (nawet jeśli „zwinność” w podtytule wydaje się wskazywać, że jest ona najbardziej odpowiednia dla tej metodologii). Mam testy i po przeczytaniu wielu książek w stylu kodowania (np. Pragmatic Programmer) Zawsze staram się tworzyć czyste i dobrze oddzielone interfejsy, ale jeden automatyczny test jest trudny dla części GUI mojej aplikacji i nadal nie mam sposób na robienie dobrego ogólnego projektu na większą skalę, który wykracza poza wdrażanie „czystych” praktyk na stosunkowo małych fragmentach kodu.
neuviemeporte
2

Oto kilka pomysłów wysokiego poziomu na organizowanie dużych systemów oprogramowania. Większość mojego doświadczenia dotyczy systemów internetowych, ale myślę, że te pomysły dotyczą oprogramowania inżynierskiego.

  • Rozdziel funkcjonalność na względnie izolowane bloki modułowe. Na przykład możesz mieć moduł dla każdej rodziny obliczeń zapewnianych przez twoje oprogramowanie.
  • Zastosuj wzorzec projektowy MVC dla interfejsu użytkownika, jeśli taki istnieje. Zachowaj interfejs i model oddzielone dobrze zdefiniowanymi granicami.
  • Rozważ użycie warstw do grupowania modułów. W aplikacji wykorzystującej warstwy abstrakcji każda warstwa zależy tylko od warstwy poniżej.
  • Pisząc dokumentację, załóż, że zapomnisz wszystkich szczegółów implementacji. Przy takim założeniu napiszesz dużo dokumentacji - być może nawet połowa twojego kodu to komentarze, ale później będziesz o wiele mniej zdezorientowany.
  • Automatyczne testy jednostkowe, integracyjne i akceptacyjne są świetne w niektórych przestrzeniach, ale programiści C ++ wydają się mieć mieszane odczucia na ich temat.
  • Rysuj mocno na wzorach projektowych . Oprócz ogólnie dobrych pomysłów, wzorce projektowe zapewniają wspólne słownictwo w inżynierii oprogramowania. Nazywanie klasy WidgetFactory to zwięzły sposób komunikowania, że ​​jest to klasa, która służy do tworzenia widżetów.

Minęło dużo czasu, odkąd pracowałem z oprogramowaniem inżynieryjnym, więc twój przebieg może się różnić w zależności od tych sugestii. Powodzenia!

greg
źródło
1

Odpowiedzią jest inżynieria oprogramowania.

Oznacza to, że w przypadku dużych projektów przestrzega się ustalonej sekwencji zbierania wymagań, definicji procesu, specyfikacji itp. Na długo przed faktycznym kodowaniem.

Istnieją różne metodologie stosowane w zależności od środowiska i kultury. Firmy typu korporacyjnego zwykle stosują się do „ Rational Unified Process ” lub podobnego, start-upy technologiczne zwykle zmieniają Agile , a departamenty rządowe przepracowały metodologię Wodospadu .

We wszystkich przypadkach proces pomaga dokładnie określić, co robisz, a pod koniec projektu pozwala udowodnić, że to zrobiłeś.

James Anderson
źródło
Zakładając, że wymagania się nie zmieniają (nierealne założenie w wielu przypadkach, wiem), czy rzeczywiście można dokładnie wszystko określić przed kodowaniem, a następnie stworzyć działające oprogramowanie ze specyfikacji bez większych zmian po drodze? Po prostu nie mogę sobie tego wyobrazić. Muszę zacząć kodować, żeby się poczuć. popraw trochę,
popraw
Może to działać w przypadku małych projektów, ale w przypadku dużych projektów musisz najpierw zmierzyć się z wymaganiami. Istotną częścią RUP jest także modelowanie proponowanego systemu za pomocą diagramów UML i Sekwencji. Znacznie łatwiej jest poprawiać i refaktoryzować model niż rzeczywisty kod.
James Anderson
@neuviemeporte: To zależy. Czasami wymagania zmieniają się lub nowe wymagania są wykrywane podczas programowania. Czasami wymagania są jasne od samego początku i tylko niektóre drobne szczegóły zmienią się podczas rozwoju, ale ogólna architektura pozostanie taka sama.
Giorgio
1

Gorąco polecam skorzystanie z Enterprise Architect , który, choć nie jest darmowy, oferuje ceny akademickie. To doskonałe narzędzie do tworzenia schematów projektów zarówno na poziomie makro, jak i mikro. Może również odtwarzać pliki źródłowe w diagramy klas, co prawdopodobnie byłoby dobrym początkiem w dokumentowaniu i reorganizacji sposobu, w jaki aplikacja współpracuje.

Poparłbym również rekomendacje @ Klee. Nie zniechęcaj się rzekomymi „zwinnymi” narzędziami, ponieważ są to po prostu najlepsze praktyki, które są również przydatne (jeśli nie obowiązkowe), jeśli postępujesz zgodnie ze zwinnym procesem. Ale ciągła integracja (na przykład) jest cenna bez względu na twoją metodologię. Co więcej, testy jednostkowe (cppUnit?) Są Twoimi przyjaciółmi. Testy jednostkowe powinny być bardzo wykonalne, jeśli przetestujesz klasy logiczne wywoływane przez interfejs użytkownika, zamiast testować interfejs bezpośrednio. Istnieją również narzędzia, które mogą pomóc w automatyzacji testowania interfejsu użytkownika, ale najpierw postaram się zebrać zaplecze.

Powodzenia!

Matthew Flynn
źródło
1

Uważam, że twój problem ma trzy wymiary

  1. Zorientowany na programistę
  2. Zorientowany na program
  3. Konserwacja programu - zorientowana

Jeśli chodzi o pierwszy problem, możesz mieć programistów, którzy nie rozumieją pojęcia tego, co robi program (często zdarza się to w konfiguracjach korporacyjnych). Ale przechodząc do pytania i domeny, w której się znajdujesz, wydaje się, że ty i twój zespół kontrolujesz, co robi program, ale po prostu nie możesz szybko przetłumaczyć go na działający program (aby zacytować przykład, słyszałem o ludziach posiadanie stopnia doktora habilitowanego fizyki, trudności ze zrozumieniem wskaźników w programowaniu i jestem pewien, że fizyka jest znacznie trudniejsza niż C ++). W takim przypadku problem dotyczy głównie Programu (musisz mieć szczęście, że ludzie wokół ciebie mogą zrozumieć, co robi Twój program i docenić to).

W przypadku problemów zorientowanych na program, jedną z moich oburzających sugestii byłoby przejście na wyższy poziom abstrakcji niż C ++, na przykład uczenie się nowego języka jako Python lub Haskell (Python jest dość łatwy do nauczenia się, a jeśli masz dobrych matematyków, Haskell jest po prostu świetny). Przejście na wyższy poziom abstrakcji pozwoliłoby zmniejszyć rozmiar kodu, było łatwe do zrozumienia i utrzymania na dłuższą metę, a efekt zmian szybko. Więc możesz mieć 10 linii kodu zamiast oryginalnych 50 linii kodu. Pomocne byłoby też posiadanie kogoś z doświadczeniem w programowaniu komputerowym. Będąc na uniwersytecie, możesz również zaangażować kilku studentów w GUI i interfejsy, abyś mógł bardziej skoncentrować się na funkcjonalności. Polecam także książkę Large Software Scale C ++ Software Design autorstwa Johna Lakosa(Jest to dość duża książka, możesz zostać biegłym programistą w języku Python w czasie, gdy zajmie Ci to przeczytanie książki)

Jeśli usuniesz dwa pierwsze wymiary problemu, trzeci zostanie automatycznie rozwiązany. Ponieważ uważam, że pracujesz nad jednym dużym projektem, każde przyzwoite oprogramowanie do zarządzania projektami pomoże Ci przejść. Konieczne jest wcześniejsze planowanie. Jeśli zaczniesz pisać od razu, możesz zbyt mocno zaangażować się w program, aby zapomnieć o dużym obrazie. Pamiętając o tym, nie przydałby się duży projekt. Umieść wszystko na papierze (lub na komputerze). Użyj wiki, aby udostępnić informacje. Jeśli chodzi o metodologie, wolę metodologię zwinną (po prostu zwinna to stylowa nazwa przyrostowego rozwoju oprogramowania). Proponuję również zatrudnić kogoś z doświadczeniem w tej dziedzinie, aby zajął się nimi, abyś mógł skoncentrować się na swoim podstawowym programie. Najważniejsze jest to, że wszystkie metodologie zarządzania projektami są tylko sposobem na zapewnienie sukcesu programu; dzięki czemu możesz wybrać osobę, która Ci odpowiada, i zespół, zamiast wybierać coś, co ktoś najlepiej poleca. Również poniższe oprogramowanie może ci pomóc

  • Darmowy umysł - oprogramowanie do mapowania myśli
  • Trac - Szybki i łatwy program do usuwania błędów oraz wiki
  • MoinMoin - szybkie wiki umożliwiające dzielenie się wiedzą na temat programu

Chociaż powyższe wskazówki zajęłyby trochę krzywej uczenia się, warto na dłuższą metę. I wreszcie, programowanie jest łatwiejsze niż Photonic Engineering (choć nie programowanie w C ++)

Ubermensch
źródło
0

Podobnie jak twoje pytanie, każda przydatna odpowiedź będzie bardzo długa i niejasna - ale krótka odpowiedź to „Inżynieria oprogramowania”

Sugeruję, abyś poświęcił trochę wolnego czasu, o ile to możliwe, jeśli poważnie myślisz o karierze programisty i zacznij od odwiedzenia strony Steve'a McConnellsa . Programowanie jest łatwe i może być nauczane w semestrze, inżynieria oprogramowania jest o rząd wielkości bardziej złożona i wymaga dużo więcej czasu na naukę.

mattnz
źródło