Jeśli będę nadal pisać więcej kodu, nadejdzie czas, kiedy będzie mi trudno go zorganizować.
To jest twój problem: popraw organizację, a styl powinien płynąć łatwiej.
Nie czekaj, aby uporządkować kod: utrzymuj swój kod uporządkowany na bieżąco. Chociaż język tego nie robi, kod powinien być nadal zorganizowany w moduły o niskim sprzężeniu i wysokiej spójności.
Moduły te następnie naturalnie zapewniają przestrzeń nazw. Skróć nazwę modułu (jeśli jest długi) i prefiks nazwy funkcji w module, aby uniknąć kolizji.
Na poziomie indywidualnych identyfikatorów są one z grubsza w porządku subiektywnym:
- wybierz konwencję i trzymaj się jej
- np.
function_like_this(struct TypeLikeThis variable)
jest powszechne
zdecydowanie unikać notacji węgierskiej (przepraszam JNL)
chyba że chcesz go używać zgodnie z pierwotnym przeznaczeniem, co oznacza notację aplikacji Simonyi zamiast strasznej wersji systemowej
Dlaczego? Mógłbym napisać esej na ten temat, ale zamiast tego zasugeruję, abyś przeczytał ten artykuł Joela Spolsky'ego, a następnie polował na więcej, jeśli jesteś zainteresowany. Na dole znajduje się link do oryginalnej pracy Simonyi.
unikaj typowania wskaźników, chyba że są to naprawdę nieprzejrzyste typy plików cookie - tylko mylą
struct Type *ok;
typedef struct Type *TypePtr;
TypePtr yuck;
Co rozumiem przez nieprzezroczysty typ pliku cookie ? Mam na myśli coś używanego wewnątrz modułu (lub biblioteki, czy cokolwiek innego), co musi zostać przekazane do kodu klienta, ale tego kodu klienta nie można użyć bezpośrednio. Po prostu przekazuje go z powrotem do biblioteki.
Na przykład biblioteka bazy danych może ujawniać interfejs podobny do tego
/* Lots of buffering, IPC and metadata magic held in here.
No, you don't get to look inside. */
struct DBContextT;
/* In fact, you only ever get a pointer, so let's give it a nice name */
typedef struct DBContexT *DBContext;
DBContext db_allocate_context(/*maybe some optional flags?*/);
void db_release_context(DBContext);
int db_connect(DBContext, const char *connect);
int db_disconnect(DBContext);
int db_execute(DBContext, const char *sql);
Teraz kontekst jest nieprzejrzysty dla kodu klienta, ponieważ nie można zajrzeć do środka. Po prostu przekaż go z powrotem do biblioteki. Coś podobnego FILE
jest również nieprzezroczyste, a deskryptor pliku liczb całkowitych jest również plikiem cookie , ale nie jest nieprzejrzysty.
Uwaga dotycząca projektu
Użyłem powyższego wyrażenia niskie sprzężenie i wysoka kohezja bez wyjaśnienia, i czuję się z tym trochę źle. Możesz go wyszukać i prawdopodobnie znaleźć dobre wyniki, ale postaram się krótko rozwiązać (ponownie, mógłbym napisać esej, ale spróbuję tego nie robić).
Naszkicowana powyżej biblioteka DB pokazuje niskie sprzężenie, ponieważ odsłania mały interfejs dla świata zewnętrznego. Ukrywanie szczegółów implementacji (częściowo przy pomocy nieprzezroczystej sztuczki cookie) zapobiega uzależnieniu kodu klienta od tych szczegółów.
Wyobraź sobie, że zamiast nieprzezroczystego pliku cookie deklarujemy strukturę kontekstu, aby jego zawartość była widoczna i zawiera deskryptor pliku gniazda dla połączenia TCP z bazą danych. Jeśli następnie zmienimy implementację na obsługę segmentu pamięci współdzielonej, gdy baza danych działa na tym samym komputerze, klient musi zostać ponownie skompilowany, a nie tylko ponownie połączony. Co gorsza, klient mógł zacząć korzystać z deskryptora pliku, na przykład wywołując setsockopt
zmianę domyślnego rozmiaru bufora, a teraz również potrzebuje zmiany kodu. Tam, gdzie jest to praktyczne, wszystkie te szczegóły powinny być ukryte wewnątrz naszego modułu, co zapewnia niskie sprzężenie między modułami.
Przykład pokazuje również wysoką spójność , ponieważ wszystkie metody w module dotyczą tego samego zadania (dostęp do bazy danych). Oznacza to, że tylko kod, który musi wiedzieć o szczegółach implementacji (tj. Zawartości naszego pliku cookie) faktycznie ma do nich dostęp, co upraszcza debugowanie.
Widać również, że posiadanie jednego problemu ułatwiło wybranie prefiksu do grupowania tych funkcji razem.
Powiedzenie, że ten przykład jest dobry, jest łatwe (zwłaszcza, że nie jest nawet kompletne), ale nie pomaga natychmiast. Sztuczka polega na tym, aby podczas pisania i rozszerzania kodu obserwować funkcje, które robią podobne rzeczy lub działają na tych samych typach (które mogą być kandydatami na własny moduł), a także funkcje, które wykonują wiele różnych rzeczy, które nie są naprawdę powiązane i mogą być kandydatami do podziału.