Załóżmy, że mam 4 rodzaje usług, które oferuję (raczej nie zmieniają się często):
- Testowanie
- Projekt
- Programowanie
- Inny
Załóżmy, że mam 60-80 faktycznych usług, z których każda należy do jednej z powyższych kategorii. Na przykład „usługa” może być „Programem testowym z wykorzystaniem techniki A” i jest typu „Testowanie”.
Chcę zakodować je w bazie danych. Wymyśliłem kilka opcji:
Opcja 0:
Użyj VARCHAR
bezpośrednio, aby zakodować typ usługi bezpośrednio jako ciąg
Opcja 1:
Użyj bazy danych enum
. Ale wyliczenie jest złe
Opcja 2:
użyj dwóch tabel:
service_line_item (id, service_type_id INT, description VARCHAR);
service_type (id, service_type VARCHAR);
Mogę nawet cieszyć się integralnością referencyjną:
ALTER service_line_item
ADD FOREIGN KEY (service_type_id) REFERENCES service_type (id);
Brzmi dobrze, tak?
Ale wciąż muszę kodować rzeczy i radzić sobie z liczbami całkowitymi, tj. Podczas zapełniania tabeli. Albo muszę tworzyć skomplikowane konstrukcje programistyczne lub konstrukcje DB podczas zapełniania tabeli lub zajmowania się nią. Mianowicie, ŁĄCZĄ się przy bezpośredniej obsłudze bazy danych lub tworzeniu nowych obiektowych obiektów po stronie programowania i upewnianiu się, że operuję nimi poprawnie.
Opcja 3:
Nie używaj enum
, nie używaj dwóch tabel, ale po prostu użyj kolumny liczb całkowitych
service_line_item (
id,
service_type INT, -- use 0, 1, 2, 3 (for service types)
description VARCHAR
);
To jest jak „fałszywy wyliczenie”, które wymaga większego narzutu po stronie kodu, na przykład wiedząc o tym {2 == 'Programming'}
i odpowiednio sobie z tym radząc.
Pytanie:
Obecnie zaimplementowałem go przy użyciu Opcji 2 , kierując się koncepcjami
- nie używaj enum (opcja 1)
- unikaj używania bazy danych jako arkusza kalkulacyjnego (opcja 0)
Ale nie mogę nie poczuć, że wydaje mi się to marnotrawstwem w zakresie programowania i ogólnych kosztów poznawczych - muszę być świadomy dwóch tabel i radzić sobie z dwiema tabelami w porównaniu do jednej.
Patrzę na „mniej marnotrawny sposób” Option 3
. IT jest lżejsze i do działania wymaga zasadniczo tych samych konstrukcji kodu (z niewielkimi modyfikacjami, ale złożoność i struktura są w zasadzie takie same, ale z jedną tabelą)
Sądzę, że idealnie nie zawsze jest to marnotrawstwo i istnieją dobre przypadki dla obu opcji, ale czy istnieją dobre wytyczne, kiedy należy użyć opcji 2, a kiedy opcji 3?
Gdy są tylko dwa typy (binarne)
Aby dodać nieco więcej do tego pytania ... w tym samym miejscu, mam opcję binarną usługi „Standard” lub „Wyjątek”, która może dotyczyć elementu zamówienia. Zakodowałem to przy użyciu Opcji 3 .
Zdecydowałem się nie tworzyć nowej tabeli, aby przechowywać wartości {„Standard”, „Wyjątek”}. Więc moja kolumna zawiera po prostu {0, 1} i nazwa mojej kolumny jest wywoływana exception
, a mój kod wykonuje tłumaczenie {0, 1} => {STANDARD, EXCEPTION}
( z którego kodowałem jako stałe w języku programowania)
Jak dotąd nie podoba mi się ten sposób ... (nie podoba się opcja 2 ani opcja 3). Uważam, że opcja 2 jest lepsza od 3, ale z większym obciążeniem i nadal nie mogę uniknąć kodowania rzeczy jako liczb całkowitych bez względu na to, której opcji użyję z 2 i 3.
ORM
Aby dodać kontekst, po przeczytaniu odpowiedzi - zacząłem ponownie używać ORM (ostatnio), w moim przypadku Doctrine 2. Po zdefiniowaniu schematu DB za pomocą Adnotacji, chciałem zapełnić bazę danych. Ponieważ cały mój zestaw danych jest stosunkowo niewielki, chciałem spróbować użyć konstrukcji programistycznych, aby zobaczyć, jak to działa.
Najpierw zapełniłem service_type
s, a potem service_line_item
s, ponieważ istniała lista z rzeczywistego arkusza kalkulacyjnego. Tak więc rzeczy takie jak „standardowy / wyjątek” i „Testowanie” są ciągami w arkuszu kalkulacyjnym i muszą być zakodowane w odpowiednich typach przed zapisaniem ich w DB.
Znalazłem odpowiedź SO: Czego używasz zamiast ENUM w doctrine2? , co sugerowało, że nie należy używać konstrukcji enum DB, ale użyć INT
pola i zakodować typy przy użyciu konstrukcji „const” języka programowania.
Ale jak wskazano w powyższym pytaniu SO, mogę uniknąć bezpośredniego użycia liczb całkowitych i użyć konstrukcji językowych - stałych - po ich zdefiniowaniu ...
Ale nadal ... bez względu na to, jak to zmienisz, jeśli zaczynam string
jako typ, muszę najpierw przekonwertować go na odpowiedni typ, nawet jeśli używam ORM.
Więc jeśli powiedzmy $str = 'Testing';
, nadal muszę mieć blok, który robi coś takiego:
switch($str):
{
case 'Testing': $type = MyEntity::TESTING; break;
case 'Other': $type = MyEntity::OTHER; break;
}
Dobrą rzeczą jest to, że nie masz do czynienia z liczbami całkowitymi / liczbami magicznymi [zamiast tego, mając do czynienia z zakodowanymi stałymi wielkościami], ale złą rzeczą jest to, że nie możesz automatycznie wciągać i wyprowadzać rzeczy z bazy danych bez tego kroku konwersji, do mojego wiedza, umiejętności.
I to właśnie miałem na myśli, mówiąc: „wciąż muszę kodować i radzić sobie z liczbami całkowitymi”. (Oczywiście, teraz, po komentarzu Ocramiusa, nie będę musiał zajmować się bezpośrednio liczbami całkowitymi, ale zajmować się nazwanymi stałymi i pewną konwersją do / z stałych, w razie potrzeby).