Podział na pliki - ile podziału?

9

Jeśli powiem, że mam hierarchiczną strukturę encji, a nie model składowy. Coś w stylu:
(Tak, to jest wymyślone)

Broń-> Gun-> AutomaticGun-> MP44
Lub, bardziej klasyczny przykład:
Entity-> MovableEntity-> Enemy-> WalkingEnemy

Jak daleko podzielisz pliki źródłowe / nagłówkowe w celu zapewnienia czytelności i organizacji? Czy najlepiej wybrać coś takiego jak Entity.cpp, MovableEntity.cpp, Enemy.cpp itp. Czy może podejście takie jak Entity.cpp [zawierające Entity i MovableEntity] i Enemy.cpp [zawierające Enemy i WalkingEnemy] byłoby lepsze? (Lub w bardziej agnostyczny sposób, plik wroga i plik jednostki a plik dla każdej klasy?)
Czy to wpłynęłoby na coś innego niż czytelność i organizację?

Kaczka komunistyczna
źródło
1
Nitpicky, ale nie sądzę, że language-agnosticjest to odpowiedni tag, ponieważ zależy on w dużej mierze od używanego języka efektów ubocznych.
Tetrad,
Dobra uwaga, myślę, że mogę się wycofać.
Kaczka komunistyczna

Odpowiedzi:

12

Jest to całkowicie kwestia preferencji. Jednak osobiście uważam, że najlepiej jest popełnić błąd po stronie większej liczby plików. Java wymaga jednej klasy na plik , na przykład z taką samą nazwą jak nazwa klasy; robią to zgodnie z polityką, aby egzekwować tę dobrą praktykę (chociaż możesz mieć podklasy, które w zasadzie omijają to).

Ponadto systemy kontroli źródła są całkiem dobre w scalaniu zmian w pliku, ale jest to mniej kłopotliwe, jeśli pracujesz w całkowicie oddzielnych plikach. Możesz także łatwiej zobaczyć, kto zmienił klasę. Powiedzmy, że inny programista wprowadza zmiany do pliku AllEntities.h; nie masz pojęcia, który byt (lub byty) zmienił, dopóki nie otworzysz pliku i nie spojrzysz na wynik różnicowy.

Wspaniale jest grupować małe struktury i wyliczenia związane z klasą w pliku jednej klasy . Jeśli masz wyliczenie, które jest używane tylko przez jedną klasę, po co dzielić ją na własny plik? Po prostu je złóż. Ale jeśli jest używana przez inną klasę (tj. Inny członek klasy jest typu tego wyliczenia), wtedy nadszedł czas, aby nadać mu własny plik.

Ricket
źródło
Zgoda. Złożoność typów powinna zdecydowanie być czynnikiem. Jeśli twój język obsługuje klasy częściowe (lub jeśli implementacje składowe mogą być zorganizowane podobnie do C ++), zaleciłbym nawet rozbicie szczególnie złożonych typów na wiele plików. Na przykład, jeśli istnieje (duży) interfejs, który klasa musi zaimplementować, ale kod jest dość ogólny i nie jest szczególnie istotny dla reszty, możesz podzielić ten kod na osobny plik / klasę częściową. W przypadku typów wyliczeń myślę, że można uniknąć umieszczania wszystkich wyliczeń dla danej przestrzeni nazw w jednym pliku.
Mike Strobel,
1
Czy grupowanie wyliczeń nie oznacza, że ​​zmiana pojedynczej wartości spowodowałaby rekompilację każdego pliku, który używa wyliczenia w tej przestrzeni nazw?
Kaczka komunistyczna
Cóż, to naprawdę zależy od języka, ale tak, z pewnością może mieć taki efekt. Nie jest to dla mnie problemem, ponieważ rozwijam się głównie w C # (bez kompilacji plik po pliku), ale może być problematyczny w C ++ i innych językach. Jak zawsze, należy wziąć pod uwagę czynniki specyficzne dla języka i to byłby jeden z nich :).
Mike Strobel,
2

Wiele języków poza C / C ++ nakłada ograniczenia na pliki. Ricket wspomniał o Javie „jedna klasa na plik”; Python używa plików jako przestrzeni nazw; inne języki często kopiują ducha tych języków.

Jeśli używasz C lub C ++, więcej dołączonych plików zwykle oznacza dłuższy czas kompilacji na plik; z drugiej strony mniej oznacza więcej do ponownej kompilacji przy wprowadzaniu niewielkich zmian. Ponieważ wyliczeń nie można zadeklarować w C, należy zawsze umieszczać je w plikach nagłówkowych zawierających tylko inne wyliczenia, dla zachowania bezpieczeństwa zależności.

W przeciwnym razie „jeden plik na klasę” Javy jest rozsądny, ale przez długi czas Java obsługiwał klasy wewnętrzne - takie jak kontener i klasa wewnętrzna iteratora. Podobnie w każdym innym języku prawdopodobnie będziesz potrzebować jednego dominującego rekordu / struct / class / type / interface / blorb na nagłówek, ale możesz zdecydować o dołączeniu powiązanych pomocników lub kontenerów.

(Nie musisz używać modelu komponentowego, ale jeśli masz taką głęboką i specyficzną hierarchię klas, będziesz później nienawidzić siebie.)


źródło
Użyłem hierarchii jako przykładu; Czułem, że lepiej podkreśla to, co miałem na myśli. W rzeczywistym kodzie staram się tworzyć komponenty.
Kaczka komunistyczna