W naszych przeważnie dużych aplikacjach zwykle mamy tylko kilka lokalizacji dla „stałych”:
- Jedna klasa dla graficznego interfejsu użytkownika i elementów wewnętrznych (tytuły stron tabulatora, tytuły pól grupy, współczynniki obliczeniowe, wyliczenia)
- Jedna klasa dla tabel i kolumn bazy danych (ta część jest generowana kodem) oraz czytelne nazwy dla nich (przypisane ręcznie)
- Jedna klasa dla komunikatów aplikacji (logowanie, skrzynki komunikatów itp.)
Stałe są zwykle podzielone na różne struktury w tych klasach. W naszych aplikacjach C ++ stałe są definiowane tylko w pliku .h, a wartości są przypisywane w pliku .cpp.
Jedną z zalet jest to, że wszystkie ciągi znaków itp. Znajdują się w jednym centralnym miejscu i wszyscy wiedzą, gdzie je znaleźć, gdy trzeba coś zmienić.
Szczególnie podoba się to menedżerom projektów, gdy ludzie przychodzą i odchodzą. W ten sposób każdy może zmienić takie trywialne rzeczy bez konieczności zagłębiania się w strukturę aplikacji.
Ponadto możesz łatwo zmienić tytuł podobnych pól grup / stron kart itp. Jednocześnie. Innym aspektem jest to, że możesz po prostu wydrukować tę klasę i przekazać ją nieprogramiście, który może sprawdzić, czy napisy są intuicyjne i czy wiadomości dla użytkownika są zbyt szczegółowe lub zbyt mylące itp.
Widzę jednak pewne wady:
- Każda klasa jest ściśle powiązana z klasami stałych
- Dodanie / usunięcie / zmiana nazwy / przeniesienie stałej wymaga ponownej kompilacji co najmniej 90% aplikacji (uwaga: zmiana wartości nie, przynajmniej dla C ++). W jednym z naszych projektów C ++ z 1500 klasami oznacza to około 7 minut czasu kompilacji (przy użyciu prekompilowanych nagłówków; bez nich to około 50 minut) plus około 10 minut łączenia z niektórymi bibliotekami statycznymi.
- Zbudowanie wersji zoptymalizowanej pod kątem prędkości za pomocą kompilatora Visual Studio zajmuje do 3 godzin. Nie wiem, czy źródłem jest ogromna liczba relacji klasowych, ale równie dobrze może być.
- Zostajesz wprowadzony do tymczasowo zakodowanych ciągów znaków bezpośrednio w kodzie, ponieważ chcesz przetestować coś bardzo szybko i nie chcesz czekać 15 minut tylko na ten test (i prawdopodobnie każdy kolejny). Wszyscy wiedzą, co dzieje się z myślami „Naprawię to później”.
- Ponowne użycie klasy w innym projekcie nie zawsze jest takie łatwe (głównie ze względu na inne ciasne połączenia, ale obsługa stałych nie ułatwia).
Gdzie będziesz przechowywać takie stałe? Jakie argumenty przedstawiłbyś, aby przekonać swojego kierownika projektu, że istnieją lepsze koncepcje, które są również zgodne z wymienionymi wyżej zaletami?
Udziel odpowiedzi niezależnej lub specyficznej dla C ++.
PS: Wiem, że to pytanie jest subiektywne, ale szczerze mówiąc, nie znam lepszego miejsca niż ta strona do tego rodzaju pytań.
Zaktualizuj ten projekt
Mam wiadomości na temat czasu kompilacji:
śledząc posty Caleba i gbjbaanba, podzieliłem plik stałych na kilka innych plików, gdy miałem czas. W końcu podzieliłem swój projekt na kilka bibliotek, co było teraz znacznie łatwiejsze. Kompilacja tego w trybie wydania pokazała, że automatycznie wygenerowany plik zawierający definicje bazy danych (tabela, nazwy kolumn i więcej - ponad 8000 symboli) i gromadzący pewne skróty spowodował ogromne czasy kompilacji w trybie wydania.
Dezaktywacja optymalizatora MSVC dla biblioteki, która zawiera stałe DB, pozwoliła nam teraz skrócić całkowity czas kompilacji twojego projektu (kilku aplikacji) w trybie wydania z maksymalnie 8 godzin do mniej niż jednej godziny!
Musimy jeszcze dowiedzieć się, dlaczego MSVC tak trudno jest zoptymalizować te pliki, ale na razie ta zmiana zmniejsza presję, ponieważ nie musimy już polegać tylko na nocnych kompilacjach.
Ten fakt - i inne korzyści, takie jak mniej ścisłe sprzężenie, lepsza możliwość ponownego użycia itp. - również pokazał, że spędzanie czasu na dzieleniu „stałych” wcale nie było takie złe ;-)
Aktualizacja 2
Ponieważ na to pytanie wciąż zwraca się uwagę:
Oto, co robiłem przez ostatnie kilka lat:
Umieść każdą stałą, zmienną itp. Dokładnie w odpowiednim dla niej zakresie: Jeśli używasz stałej tylko w jednej metodzie, możesz ją zdefiniować w tej metodzie. Jeśli zainteresowana jest jedna klasa, pozostaw ją jako prywatny szczegół implementacyjny tej klasy. To samo dotyczy przestrzeni nazw, modułu, projektu i zakresu firmy. Używam tego samego wzoru dla funkcji pomocniczych i tym podobnych. (Może to nie dotyczyć 100%, jeśli opracujesz ramy publiczne).
Dzięki temu zwiększona możliwość ponownego użycia, testowalność i łatwość konserwacji do tego stopnia, że nie tylko spędzasz mniej czasu na kompilacji (przynajmniej w C ++), ale także mniej czasu na naprawianie błędów, co pozostawia więcej czasu na faktyczne opracowanie nowych funkcji. Jednocześnie rozwijanie tych funkcji będzie szybsze, ponieważ łatwiej będzie ponownie wykorzystać więcej kodu. Przewyższa to jakąkolwiek przewagę, jaką może mieć plik stałych centralnych.
Jeśli chcesz dowiedzieć się więcej, zapoznaj się zwłaszcza z zasadą segregacji interfejsu i zasadą pojedynczej odpowiedzialności .
Jeśli się zgadzasz, głosuj za odpowiedzią Caleba, ponieważ ta aktualizacja jest zasadniczo bardziej ogólnym podejściem do tego, co powiedział.