Jak powinienem uporządkować moje drzewo źródłowe?

89

Jestem indywidualnym programistą pracującym głównie nad projektami internetowymi (W / LAMP), a czasami nad projektami C / C ++ (nie GUI) o średniej skali.

Często mam problemy ze strukturą drzewa kodu źródłowego. W rzeczywistości zazwyczaj nie kończę projektu bez zrzucenia całego drzewa i uporządkowania kawałków trzy-cztery razy, co naprawdę zajmuje dużo wysiłku, a ponadto efekt końcowy wydaje się kompromisem.

Czasami kończę na nadmiernej klasyfikacji źródła - bardzo długim drzewie folderów i podfolderów. Innym razem po prostu koncentruję wszystkie pliki w określonym folderze na podstawie ich większego celu, co prowadzi do „chaotycznych” folderów w źródle.

Chciałbym zapytać:

  • Czy są jakieś zasady / logika / najlepsze praktyki, które mogą pomóc mi lepiej ustrukturyzować moje drzewo źródłowe?
  • Czy istnieją jakieś techniki graficzne / schematyczne (np .: DFD w przypadku przepływu danych), które mogą pomóc mi wcześniej zobrazować moje drzewo źródłowe na podstawie analizy projektu?
  • Jaką strategię zastosować, aby ustrukturyzować drzewo plików multimedialnych powiązane z projektem?

O nagrody : doceniam istniejące odpowiedzi, w których członkowie dzielą się własnymi praktykami, jednak chciałbym zachęcić bardziej ogólne i pouczające odpowiedzi (lub zasoby) i więcej odpowiedzi od członków.

check123
źródło
8
Nie mam teraz czasu na esej, ale „nazwij rzeczy takimi, jakie są”, „umieść rzeczy tam, gdzie należą”, „trzymaj podobne rzeczy blisko siebie”, a na koniec „nie martw się o to , mamy nadzieję, że masz IDE, które pomoże ci szybko nawigować między fragmentami kodu ".
John Saunders,
@John, nie jestem zbyt dobry w IDE (ach), generalnie wyciągam Notepad ++ lub vi w zależności od systemu operacyjnego. To czyni sprawy nieco trudniejszymi. Pozostałe punkty są pomocne, ale znów sprowadza się do podejmowania trudnych decyzji, takich jak funkcje dziennika (dzienniki błędów itp.), Które są bliższe logice aplikacji lub DAL, zarządzaniu pamięcią podręczną lub menedżerom widoków. Błędy mają prawie równe prawdopodobieństwo wystąpienia w dowolnym z nich.
sprawdź123
3
Być może, kiedy dojdziesz do tego rodzaju pytań, nadszedł czas, aby niektóre narzędzia wykonały za ciebie część pracy. Logowanie jest oczywiście kwestią wielofunkcyjną, używaną przez wszystkie części aplikacji (jeśli używasz kodu wymagającego logowania). Innym małym powiedzeniem jest: „umieść kod nad kodem, który go używa”, więc rejestrowanie powinno być u góry, być może w \ utilities.
John Saunders
@John: Bardzo doceniam. Być może powinienem zacząć szukać IDE. Zaćmienie wydaje się obiecujące.
sprawdź123,
1
@ check123 „… trzykrotnie zmienia układ elementów…” Powszechna praktyka: „Dlatego pytanie zarządcze nie polega na tym, czy zbudować system pilotażowy i go wyrzucić. Zrobisz to. Jedyne pytanie brzmi, czy planować z wyprzedzeniem, czy zbudować coś na wynos, czy też obiecać, że dostarczysz go klientom ”. - Frederick P. Brooks Jr., The Mythical Man-Month: Essays on Software Engineering
shawnhcorey

Odpowiedzi:

25

Układ drzewa źródłowego powinien odzwierciedlać architekturę; w następstwie tego dobrze zorganizowana architektura może prowadzić do dobrze zorganizowanego układu drzewa źródeł. Sugeruję przeczytanie wzorca warstw POSA1 , próbę dopasowania architektury do struktury warstwowej, a następnie nazwanie każdej z powstałych warstw i wykorzystanie jej jako podstawy hierarchii źródłowej. Przyjmując wspólną architekturę trójwarstwową jako podstawę:

  • prezentacja / webService (zaprezentuj interfejs naszej usługi logice biznesowej)
  • logic / * (moduły logiki biznesowej przejdź tutaj)
  • storage / sql (tutaj interfejsy API pamięci masowej zaplecza - używa interfejsu SQL do przechowywania danych w bazie danych)
  • util / * (kod narzędzia - możliwy do użycia przez wszystkie inne warstwy, ale nie odnosi się do zewnętrznego wykorzystania, tutaj)

Zauważ, że warstwy nie zawierają kodu bezpośrednio, ale są ściśle używane do organizowania modułów.

W module używam następującego rodzaju układu:

  • <module> (ścieżka do modułu bezpośrednio; definiuje interfejs modułowy)
  • <module>/impl/<implName> (konkretna implementacja interfejsu modułowego)
  • <module>/doc (Dokumentacja korzystania z modułu)
  • <module>/tb (kod testu jednostkowego modułu)

gdzie <module>znajduje się w repozytorium zgodnie z warstwą, do której należy.

Aidan Cully
źródło
5
+1: układ drzewa źródłowego powinien odzwierciedlać architekturę - oczywistą rzecz, którą przeoczyłem.
sprawdź123,
Jak zarządzasz bezpiecznymi plikami - plikami, do których dostęp mają tylko zalogowani użytkownicy?
sprawdź123
@ check123 Nie jestem pewien, czy rozumiem pytanie. Skoncentrowałem się na organizacji modułów źródłowych, a nie na obsłudze plików dla projektu, a kod źródłowy jest zwykle przeznaczony dla wszystkich. (Są wyjątki, a ja używam katalogu dist / przede wszystkim kodu z niestandardowymi ograniczeniami użycia / modyfikacji.)
Aidan Cully
48

Naprawdę nie mogę dać ci wielu rad związanych z projektami internetowymi, ale oto jak ustrukturyzować moje drzewo w projekcie programistycznym (głównie z perspektywy C / C ++):

  • /
    • src - Pliki źródłowe napisane przeze mnie
    • ext - Zawiera biblioteki stron trzecich
      • libname-1.2.8
        • obejmują - nagłówki
        • lib - Skompilowane pliki lib
        • Donwload.txt - zawiera link do pobrania używanej wersji
    • ide - przechowuję tutaj pliki projektu
      • vc10 - Aranżuję pliki projektu w zależności od IDE
    • bin - skompilowany plik exe idzie tutaj
    • build - pliki kompilacji kompilatora
    • doc - Dokumentacja dowolnego rodzaju
    • CZYTAJ
    • ZAINSTALOWAĆ
    • BIUROWY

Kilka uwag:

  1. Jeśli piszę bibliotekę (i używam C / C ++), najpierw uporządkuję pliki źródłowe w dwóch folderach o nazwach „include” i „src”, a następnie według modułów. Jeśli jest to aplikacja, zamierzam uporządkować je według modułu (nagłówki i źródła przejdą do tego samego folderu).

  2. Pliki i katalogi wymienione powyżej kursywą nie dodam do repozytorium kodu.

Paweł
źródło
Jaka jest różnica między ide a build ?
M. Dudley,
3
idewłaśnie tam przechowuję same pliki projektu. buildzawiera pliki obiektowe generowane przez kompilator. Różne IDE mogą korzystać z tego samego kompilatora, dlatego trzymam pliki projektu IDE oddzielnie od plików obiektowych zbudowanych przez kompilator.
Paul,
więc build == obj (termin używany przez wiele innych systemów)
gbjbaanb
@gbjbaanb Tak, tak myślę. To naprawdę nie ma znaczenia, ponieważ ten katalog nie jest wypychany do repozytorium. :) Nazwałem to „build”, ponieważ tak właśnie nazywało się IDE, którego używałem att (Visual Studio).
Paul,
Co jeśli twój exe potrzebuje trochę dll do uruchomienia? Czy kopiujesz wszystkie pliki dll do tego samego katalogu co exe? Czy używasz niektórych zdarzeń po kompilacji?
Wakan Tanka,
14

Chociaż Maven Standard Directory Layout jest swoisty dla Javy, może jednak służyć jako dobra podstawa dla innych typów projektów.

Oto podstawowa struktura (możesz zamienić katalogi „java” na „php”, „cpp” itp.):

src/main/java       Application/Library sources 
src/main/resources  Application/Library resources  
src/main/filters    Resource filter files 
src/main/assembly   Assembly descriptors 
src/main/config     Configuration files 
src/main/webapp     Web application sources 
src/test/java       Test sources 
src/test/resources  Test resources 
src/test/filters    Test resource filter files 
src/site            Site 
LICENSE.txt         Project's license 
NOTICE.txt          Notices and attributions required by libraries
README.txt          Project's readme

Struktura zasadniczo dzieli się na „src / main” i „src / test”, a następnie pogrupowane według typu.

Michał Miller
źródło
5

Naprawdę nie wiem o konwencjach, ale wszystkie moje główne projekty są realizowane przy użyciu Symfony Framework i przyzwyczaiłem się do struktury drzewa, jak poniżej:

korzeń/

  • aplikacje
  • Nazwa aplikacji
    • config (pliki konfiguracyjne specyficzne dla aplikacji)
    • lib (pliki php specyficzne dla aplikacji)
    • moduły (modułowy rozkład funkcjonalności)
      • Nazwa modułu
        • szablony (HTML)
        • akcje (kod php)
  • confing (pliki konfiguracyjne projektu)
  • lib (kod php, który może być użyty w projekcie otworu)
  • model (klasy reprezentujące informacje o projekcie)
    • baza
  • form (pliki php obsługujące formularze, może to być dość trudne do osiągnięcia bez symfony)
    • base (klasy klas podstawowych)
  • sieć
  • css
    • zdjęcia
    • plik.css
  • js
  • log (pliki dziennika, które mogą zostać wygenerowane)
  • dane (informacje specyficzne dla danych, takie jak łatki SQL itp.)
  • sql
  • wtyczki (używane biblioteki, które można połączyć z dowolną aplikacją projektu)

Zainteresowanych prosimy o zapoznanie się z dokumentacją symfony w tej sprawie w celu uzyskania dalszych informacji ( MVC i Code Organization on Symfony ).

guiman
źródło
Czy Twój folder CSS jest scentralizowany? Mam na myśli, że wszystkie twoje CSS (w całym projekcie) są w tym samym katalogu?
sprawdź123
Niekoniecznie, możesz to podzielić, ale ponieważ większość moich projektów ma zwykle tylko 2 aplikacje (frontend i backend), nie ma zbyt wielu plików css (wtyczki zawsze mają własny folder internetowy do abstrakcji)
guiman
5

W idealnym przypadku organizacja ma jedno repozytorium, którego struktura ma na celu zwiększenie zaangażowania między inżynierią i biznesem oraz promowanie ponownego wykorzystania.

...\products\
...\products\productName\
...\products\productName\doc\

...\systems\
...\systems\systemName\
...\systems\systemName\doc\
...\systems\systemName\res\
...\systems\systemName\build\
...\systems\systemName\test\

...\library\
...\library\libraryName\
...\library\libraryName\doc\
...\library\libraryName\build\
...\library\libraryName\test\

...\devops\

produkty

Jeden folder na produkt; pomaga komunikować, w jaki sposób oprogramowanie obsługuje firmę.

W idealnym przypadku każdy „produkt” to niewiele więcej niż plik konfiguracyjny wskazujący, które systemy należy wywołać i jak należy je skonfigurować. Podfolder dokumentów może zawierać krótkie \ specyfikacje i wszelkie materiały promocyjne itp ...

Rozdzielając produkty i systemy, informujemy o możliwości ponownego wykorzystania strony biznesowej po stronie klienta i dzielimy silosy na poszczególne produkty. (Kontrastuje to z podejściem „linii produktów” do tego samego problemu)

systemy

Jeden folder na system; pomaga komunikować podstawowe możliwości i możliwości / wartość zawartości repozytorium.

  1. Pliki „zarządzania konfiguracją” określające środowiska kompilacji i wdrażania.
  2. Konfiguracja testowania na poziomie systemu (może to być znacząca ilość).
  3. Logika i funkcjonalność najwyższego poziomu; większość ciężkich operacji podnoszenia wykonuje się za pomocą funkcji bibliotecznych.

biblioteka

Komponenty wielokrotnego użytku wywoływane przez różne systemy. Większość działań programistycznych skupia się na tworzeniu bibliotek, a nie systemów, dlatego ponowne wykorzystanie jest „włączane” w proces rozwoju.

devops

Kompilacja, ciągła integracja i inne funkcje automatyzacji programowania.

Wniosek

Drzewo źródłowe jest kluczową dokumentacją i kształtuje podejście, strukturę i psychologię relacji firmy z jej zastrzeżoną technologią.

Sterowniki tego podejścia wyjaśniono nieco głębiej w mojej odpowiedzi na to pytanie: https://softwareengineering.stackexchange.com/questions/43733/who-organizes-your-matlab-code/59637#59637

William Payne
źródło
Uwaga: Przydatne może być nazwanie folderów w sposób zgodny z rodzajem hierarchii produktów omówionym w podręczniku inżynierii systemów INCOSE.
William Payne
3

To, co próbuję zrobić dla każdego projektu, jest podobne:

  • src - pliki źródłowe, folder dla każdej przestrzeni nazw / pakietu do łatwego pobierania plików (nawet pliki nagłówkowe dla C / C ++)
  • ext - w przypadku bibliotek zewnętrznych / bibliotek stron trzecich można łatwo dodać zewnętrzne (takie jak repozytoria SVN). Wewnątrz folder dla każdej biblioteki (pliki binarne i dołączane pliki)
  • bin - dla wbudowanych plików binarnych można je szybko wyeksportować w celu wydania
    • inc - dla pliku nagłówków C / C ++ (skopiowane przez IDE / makefile / etc ...)
  • out - dla wszystkich plików generowanych tymczasowo (.class, .obj itp ...) i można je zignorować (na przykład przez SVN)
  • doc - dla dowolnej dokumentacji, zwykle generowanej za pomocą Doxygen
  • res - umieszczając tutaj zasoby, można oddzielić pliki źródłowe tekstu i zasoby binarne używane przez program. Tak naprawdę nie mam w sobie określonej hierarchii.
    • config - dla niektórych plików konfiguracyjnych
    • drawable - dla niektórych zdjęć lub ikon

Wszystkie pliki IDE lub pliki makefile są zapisywane bezpośrednio w katalogu głównym, jeśli używasz tylko jednego z nich.

Ninfomane
źródło
2

Robię coś takiego. Działa dobrze w grze na wielu platformach, którą wykonuję w wolnym czasie. Niestety w pracy sprawy są znacznie mniej zorganizowane ...

Output                      <-- Build outputs
Docs
External
   <libname>
      Include
      Lib
Data
<ProjectName>.xcodeproj
<ProjectName>VS2010
Source
Temp                        <-- Intermediate stuff from builds and other tools
Tools
Pułkownik Panika
źródło
2

Dla moich zespołów staramy się narzucić standardową strukturę w różnych projektach, aby łatwo było znaleźć rzeczy, ponieważ zespół zmienia kontekst i aby uniknąć konieczności ponownego uczenia się za każdym razem. Nie wszystkie projekty wymagają wszystkich systemów, więc zaczynamy od minimalnego zestawu.

/ Source / Component / Language

/ Source / Component / Third Party /

/Wymogi dokumentacyjne

/ Dokumentacja / Projekt

/ Testy / Automatyzacja / Jednostka

/ Testy / Automated / ToolName

/ Testy / Podręcznik

Powoduje to pewne powielanie, szczególnie w kodzie i bibliotekach stron trzecich, ale przynajmniej nigdy nie zapominamy odpowiedzi na coś takiego jak „Co używa RogueWave Editor?”

Christopher Bibbs
źródło
1
Skapitalizowane elementy ścieżki wyglądają dla mnie naprawdę głupio i bezcelowo. Dlaczego wiele małych liter? Jest to o wiele łatwiejsze do pisania dla ludzi (podczas gdy narzędzia nie dbają o to, w tym menedżery plików WIMP ) i odczytuje równie dobrze dzięki separatorom ścieżek. Ostateczne zwycięstwo dla mnie.
ulidtko
2

Podoba mi się pomysły przedstawione na tej stronie www.javapractices.com/topic/TopicAction.do?Id=205 . Zasadniczo zaleca się zorganizowanie projektu w funkcje (lub moduły, komponenty). Oprócz przedstawionych tam powodów:

  1. Mniejsze obciążenie poznawcze, kiedy myślisz o zakresie kodu, nad którym pracujesz, ponieważ masz gwarancję, że każdy kod w funkcji, nad którą pracujesz, jest „cechą prywatną”.
  2. Dodatkowym poczuciem bezpieczeństwa jest zagwarantowanie, że modyfikujesz kod tylko dla danej funkcji. Np. Nie złamiesz niczego innego niż funkcja, nad którą pracujesz. Ponownie dzieje się tak z powodu „funkcji prywatnej”.
  3. Proste ładowanie poznawcze jest proste, ponieważ dla danego pakietu jest mniej plików. Jestem pewien, że każdy widział pakiet zawierający ponad 15 plików.

Uwaga: koncentruje się na pakietach Java (czyli przestrzeniach nazw). W przypadku dużych projektów polecam, z tych samych powodów, podzielenie projektu na wiele projektów (jak w wielu projektach maven), które reprezentują funkcję biznesową. W przypadku projektów maven polecam tę lekturę .

Jak dotąd projekty, w które byłem / jestem zaangażowany, nie są zgodne z nimi. Jest wiele powodów, ale oto kilka:

  1. Niezrozumienie domyślnego modyfikatora dostępu Java (najbardziej niezrozumiany modyfikator dostępu według tej książki )
  2. „Argumentum ad populum”: dominująca kultura pakiet po warstwie (prawdopodobnie spowodowana Powodem 1)

Myślę, że nie ma szansy na uniknięcie złożoności, jeśli organizacja źródła projektu nie jest traktowana poważnie na początku projektu, jak powiedział architekt Alexander:

„Jak powie każdy projektant, najważniejsze są pierwsze kroki w procesie projektowania. Kilka pierwszych pociągnięć, które tworzą formę, niosą w sobie przeznaczenie reszty”. - Christopher Alexander

W zależności od wielkości i złożoności projektu, utracona szansa na obniżenie kosztów lub ROI może być naprawdę duża. (Jestem zainteresowany, aby zobaczyć badanie, aby zobaczyć dokładne liczby dla tego)

trzynaście
źródło
2

Polecam pobrać różne frameworki lub silniki i zobaczyć, jak ogromne zespoły programistyczne radziły sobie z układem folderów.

Istnieje tak wiele sposobów organizowania plików, że lepiej jest wybrać jeden i spróbować trzymać się go w dowolnym projekcie. Trzymaj się określonej konwencji, aż do zakończenia lub przebudowy, aby uniknąć błędów i stracić niepotrzebny czas.

Możesz pobrać frameworki Laravel, Symphony lub Codeigniter dla projektów internetowych, aby mieć natychmiastowy układ folderów, który działa.

Spróbuję więc przekazać układ folderów wspólny dla każdego projektu:

MVC (Model View Controller) zapewnia dobry paradygmat organizacji.

Podstawowym kodem źródłowym może być src (C ++) lub aplikacja (tworzenie stron internetowych)

Struktura plików, która nie ma jasnego celu dla grup, które grupuje, z pewnością spowoduje zamieszanie. Służy nie tylko do porządkowania kodu, ale może obsługiwać automatyczne programy ładujące, fabrykę klas, owijanie pamięci lokalnej, pamięć zdalną i przestrzeń nazw.

Ta struktura folderów została wyprowadzona i uproszczona z Laravel Framework . Preferuję ten post w liczbie mnogiej, ale w swoich projektach używam pojedynczych słów.


implementacje src / storage (modele / implementacje plików / api / mysql / sql-lite / memcached / redis)

src / repositories (opakowanie „implementacji pamięci” z pewną logiką pamięci, wspólnym interfejsem i konwencją zwracania wyników).

src / services | logika | podmioty (logika biznesowa aplikacji)

src / kontrolery (Używany w programowaniu WWW do kierowania żądań serwera do twoich usług)

src / modules | systemy ( Systemy modułowe, które rozszerzają ogólną funkcjonalność frameworka. Usługi mogą korzystać z modułów, ale nie odwrotnie)

src / helpers (klasy pomocnicze lub otoki jak np. manipulacja ciągami. Wiele razy może to być na libs vendor, gdy osoba trzecia)

src / types (nazwane wyliczenia)

publiczne | buduj | wyjście (web lub c ++)

config (pliki instalacyjne. YAML staje się popularny wśród plików konfiguracyjnych między platformami)

Pamięć podręczna

logi

lang (en / es / ru / ...)

bootstrap (Uruchamia platformę i aplikację)

docs (Dokumentacja napisana w formacie markdown .md)

testy ( testy jednostkowe)

baza danych / migracje (Utwórz strukturę bazy danych od podstaw)

baza danych / nasiona (wypełnia bazę danych fałszywymi danymi do przetestowania)

libs | sprzedawca (całe oprogramowanie stron trzecich. „libs” w C ++ i „vendor” zwykle w php)

aktywa | zasoby (obrazy / dźwięki / skrypty / json / dowolne media)

Heroselohim
źródło
1

W przypadku języków zorientowanych obiektowo masz możliwość budowania przestrzeni nazw. Ten logiczny podział używany do oddzielania części aplikacji w celu uniknięcia sprzężenia jest głównym źródłem logicznego podziału lokalizacji pliku. Wykorzystywanie sprzężenia jako przyczyny rozbijania przestrzeni nazw jest dobrym miejscem do rozpoczęcia http://en.wikipedia.org/wiki/Software_package_metrics .

Inni mówili o konfigurowaniu projektu w odniesieniu do kompilacji, ale kiedy przejdziesz do samego źródła, chodzi o to, co ma sens - po prostu użyj tego, jak logicznie rozbijasz kod mimo to.

Travis
źródło