Wątek przeniesiony 2021-04-23 22:59 z Java przez furious programming.

Ocena bazy danych i wzorzec projektowy

0

Hej,

Piszę projekt na zaliczenie na studia, a także jako "pokaz" umiejętności dla potencjalnego pracodawcy. Jest to uproszczony sklep internetowy. Technologie to angular, spring boot, hibernate, postgresql. Pytania zapiszę poniżej dla lepszej czytelności:

  1. Czy baza danych jest sensownie zaprojektowana, czy warto pozmieniać jakieś rzeczy (może błędnie wykonany diagram).
    -Jeżeli chodzi o opis do produktu, to zakładam, że opis na stronie składa się z kilku sekcji, dlatego dodatkowa tabela.
    -Tabela product_details powinna zawierać wszystkie możliwe pola dla każdego typu produktu (np. telefon ma przekątną ekranu, ale karta graficzna już nie, więc byłoby to pole jako null). Nie wiem czy to dobre rozwiązanie, ale product_type, rozbija to na wiele klas w javie.

  2. Prosiłbym o podpowiedź jaki wzorzec projektowy tutaj zastosować. Jeszcze się w nich nie orientuję do końca, który pasowałby do tego modelu. Budowniczy, byłby przy tworzeniu nowego produktu (tak mi się wydaję).

2021-04-23_194952.png

3
  1. billing i shipping_address to praktycznie to samo - część wspólna, czyli adres, powinna być w osobnej tabeli i powinna być powiązana z userem i z zamówieniem (jeśli dopuszczamy "pamiętanie" różnych adresów dostawy a jeśli nie to wystarczy z userem)
  2. order_row - średnia nazwa tabeli z pozycjami zamówienia
  3. do opinii można dodać tylko jedno zdjęcie
  4. nie widzę informacji o kwocie, jaką zapłacił klient (wcale nie musi być taka sama jak wartość zamówienia)
  5. brakuje: uwagi do zamówienia, sposób dostawy, koszt dostawy,
  6. co jeśli będę chciał zamówić np. 3 sztuki danego towaru
  7. product_details jak dla mnie jest nieakceptowalne - takie rzeczy robi się pionowo a nie poziomo (tzn. że zamiast dodawać nowe kolumny do tabeli opisujące nowe cechy dodaje się nowe rekordy)
  8. można jeszcze dodać warianty produktu (np. rozmiar albo kolor z taką samą ceną albo za dodatkową opłatą)
0

Jutro poprawię i wrzucę poprawiony schemat. Nie rozumiem tylko z tym adresem. Jeżeli adres dostawy będzie inny niż rozliczenia, to wtedy mamy 2 rekordy w 2 tabelach. Jeżeli faktura nie będzie na inna osobę lub firmę, to wtedy bierzemy dane z dostawy na fakturę.

0

Ja się jeszcze dopytam, bo bazodanowiec ze mnie słaby, czy status nie powinien być w order?

0

@nalik: Chyba nie, operację na stringach trwają dłużej i zajmują więcej pamięci. Wolę mieć osobną tabelę z możliwymi statusami (żeby ktoś nie wprowadził błędnego z obsługi) i ewentualnie wykonywać szybki join.

@abrakadaber: Poprawiłem rzeczy o których wspomniałeś, dodałem także encję category o której zapomniałem. Teraz prezentuje się to tak:
2021-04-24_111804.png

1

W variant i product_details mieszasz różne rzeczy - tzn cechy produktu niezwiązane ze sprzedażą, z cechami produktu dotyczącymi sprzedaży.

Variant niepotrzebnie w ogóle jest osobną tabelą.

Ja w swoim silniku sklepu zrobiłem to trochę inaczej, stosując klasy produktów.

Co do klas:

  • Relacja na właściwości: nazwa właściwości, typ (tekst, liczba, data)
  • Relacja na klasę
  • Relacja łącząca klasę z właściwościami (wielu-do-wielu) - aby określić z jakich właściwości składa się klasa
  • Dodanie klucza obcego w relacji produktów do relacji klasy
  • Relacja łącząca produkt z właściwościami (wielu-do-wielu): oczywiście dokładnie tymi które wynikają z wybranej klasy. W tej relacji określa się wartości właściwości produktów wynikające z klasy.
    • zmiana klasy / określenie z pustej na niepustą: stworzenie powiązań w tej relacji dla danego produktu na podstawie tych właściwości które są związane z wybraną klasą
    • usunięcie klasy w produkcie (określenie na NULL): usunięcie powiązań z tej relacji

Masz tu też więcej problemów - np. produkt może należeć tylko do jednej kategorii, a powinno być tak, że powinien móc należeć do wielu kategorii ale tylko do jednej klasy (IMO).

Czyli kategorie to powinna być jedna relacja, produkty druga i trzecia relacja wielu-do-wielu łącząca dowolnie kategorie z produktami.

0

@abrakadaber: czemu dane w product details powinny być zrobione per rekord a nie kolumnowo? Co nam to daje? Osobiście bym to wrzucił w arraya propertiesów w polu.

Description i product details to dla mnie powinna być jedna szeroka tabela, nie widzę osobiście zysku z rozbicia.

2
MuadibAtrides napisał(a):

Description i product details to dla mnie powinna być jedna szeroka tabela, nie widzę osobiście zysku z rozbicia.

Jesteś pewien?

Co w sytuacji kiedy masz w sklepie setki tysięcy produktów, z setek różnych branż? Musiałbyś mieć tabelę z ponad tysiącem kolumn, żeby te wszystkie cechy uwzględnić. LOL

0

@TomRZ: Faktycznie to co zrobiłem z wariantem nie ma większego sensu. Zrobiłem na klasach produktów, daj znać czy to miałeś na myśli, przykład:

  1. Produkt należy do klasy produktów smartfon
  2. Klasa smartfon ma przypisane specyfikację np. przekątna itd.
  3. Relacja produkt - specyfikacja pozwala uzupełnić wartości tych specyfikacji, tylko dla tej danej klasy.

W tym wypadku jeżeli chcemy np. 3 warianty kolorystyczne to będą 3 osobne produkty, ze zmienioną 1 specyfikacją. Czy może lepiej zrobić dodatkowe pole "różnica w cenie" w tabeli specyfikacja_produkt i jeżeli dla danego produktu będzie powielać się dana specyfikacja to wtedy będziemy możliwość dodania, lub odjęcia ceny dla konkretnie wybranej. Dzięki temu nie duplikujemy produktów ze zmienionym tylko np. kolorem.

Chyba że kompletnie nie o to chodziło.

Ps: Historie produktów potem poprawie, bo teraz nie ma sensu. Kategorie również.

2021-04-24_221004.png

1
  • Relacja "produc_class_specification" jest niepotrzebna
  • Zamiast "specification_id" ma być "product_class_id" -> określasz do jakiej klasy nalezy produkt
  • To jakie będą powiązania w "product_specification" zależy od powiązań klasy w "product_class_specification" - oczywiście to już należy do logiki aplikacji, ponieważ do "product_specification" możesz wrzucić wszystko i dowolnie sobie określać cechy produktu w ogóle w oderwaniu od tego do jakiej klasy należy. Dlatego to logik aplikacji dba o to, żeby była spójność między tym jaka jest definicja klasy a jakie ma przydzielone cechy produkt należący do tej klasy. Powinien mieć tylko te które są dla klasy zdefiniowane - żeby był porządek.
  • W "specification" (czyli cesze) powinieneś dodać jaki to jest typ cechy - np. liczba, tekst, data
  • W "product_specification" powinieneś odpowiednio dodać kolumny dla typu wartości: np."value_int" -> jeżeli cecha jest liczbą calkowitą, "value_date" -> jeżeli datą, "value_varchar" - jeżeli to tekst. I tak dalej - ja u siebie mam jeszcze typ "enum" gdzie można wybrać z kilku zdefiniowanych cech, ale to dodatkowa komplikacja, na później ewentualnie.
0

Jak rozumiem w aplikacji będę posiadał interfejs klasa z podstawowymi metodami np. finalPrice(). Interfejs ten, będą rozszerzać dane klasy produktów np. telefon z dodatkowymi polami. Telefon rozszerzy telefon stacjonarny i domowy i każda z tych klas będzie miała swoje specyfikację.

Teraz pytanie jak rozwiązać problem powielania produktów np. smartfon xyz zielony albo niebieski, z tym że zielony kosztuje 20zł drożej. W polu specyfikacja dodać specyfikację dodatkowa cena np. 20zł i w aplikacji obliczać cenę od głównej? Jeżeli tak, to jak obliczać promocję np. na kolor niebieski tylko. W aplikacji pobiorę kolor zielony i niebieski, ale nie będę wiedział do którego przynależy promocja.

Czy faktycznie nie bawić się i tworzyć za każdym razem produkt, choćby miał on się powielić w 99%. Ułatwia to zarządzanie historią.

2021-04-24_225450.png

0
TomRZ napisał(a):
MuadibAtrides napisał(a):

Description i product details to dla mnie powinna być jedna szeroka tabela, nie widzę osobiście zysku z rozbicia.

Jesteś pewien?

Co w sytuacji kiedy masz w sklepie setki tysięcy produktów, z setek różnych branż? Musiałbyś mieć tabelę z ponad tysiącem kolumn, żeby te wszystkie cechy uwzględnić. LOL

@TomRZ popraw mnie jeśli się mylę, ale według diagramu rozumiem, że zakładamy, że każdy produkt może mieć N wariantów i każdy wariant ma swój opis i detale - bo tak wynika z poprowadzenia linii w 1 poscie. Chyba, że tutaj jest błąd i ten opis przez product id powinien być połączony z głównym produktem?

Czy źle rozumiem details i defacto yo generyczne atrybuty do produktu per wiersz?

2

@brus97: ja u siebie to tak zrobiłem że po prostu grupuję wybrane produkty, które różnią się jedynie cechą X, wg. różnic tej cechy.

Może to być kolor, długość, cokolwiek z cech które są zdefiniowane w specification.

Dla każdego produktu osobno tworzysz listę cech, nawet jeżeli się powtarzają, robienie jakichś algorytmów i rozwiązań żeby zaoszczędzić trochę miejsca generalnie się nie opłaca.

Tworzysz sobie np. relację "product_specifcation_group": id, specification_id, gdzie określasz cechę do grupowania, a potem relację gdzie będziesz miał product_specifcation_group_id oraz product_id - i w ten sposób możesz zgrupować np. 8 prouktów a potem system w sklepie powinien pozwalać na szybkie przechodzenie między wariantami wg. specification_id

Co do reszty to nie patrzyłem już na diagram bo późno, może w poniedziałek.

@MuadibAtrides:
Tak, i Ty byś chciał to zrealizować dodając za każdym razem nową kolumnę do relacji na produkty, kiedy trzeba dodać jakąś nową cechę?

Np. zaczęliśmy sprzedawać pralki i trzeba określić np. prędkość wirowania, więc dodajesz na to nową kolumnę do relacji na produkty?

Nie tędy droga, to byłaby jakaś masakra.

1

Witam serdecznie, poprawiona baza danych mi się podoba dodałbym jednak kluczowe elementy dla sklepu to znaczy wartość podatku. (jest to konieczne) i zastanowiłbym się nad dodaniem
cen sprzedaży oraz zakupu. Ponieważ mają ceny sprzedaży oraz zakupu później w łatwy sposób z CSV wygenerujesz zysk per każde zamówienie. Do tego doliczasz inne koszta i możesz dosyć łatwo rozliczyć się. (Szczególnie ważne w modelu dropshippingu) gdzie nie posiadasz produktów własnych i faktur na masowe zamówienia a setki bądź tysiące pojedynczych.

0

@TomRZ: ja w NoSQL siedzę i tam to co Ty tutaj proponujesz zrobić na relacji przez nowe wiersze robi się po prostu structem / tablicą w encji. Ja bym dążył do jak najmniejszej liczby tabel i jeśli ma to sens złączał w 1 szersze tabele tam gdzie można.

1

@MuadibAtrides: autor pyta o bazę relacyjną a nie NoSQL, nie wiem czy tutaj kogoś interesuje jak Ty byś to zrobił w bazie nierelacyjnej - mnie to nie obchodzi.

0

Hej, sorka za przestój, plusiki rozdałem, tutaj ostateczna wersja bazy danych (dodane rzeczy od Emila). Resztę będę poprawiał w trakcie tworzenia stronki.

@TomRZ Z grupowaniem jeszcze przemyślę potem :d

Jeszcze ostateczne pytanie, lepiej zostawić tabelę status i payment, czy zrobić ich jako enum po stronie aplikacji i wrzucić pola do order.

2021-05-07_222418.png

0

@TomRZ, wytłumaczyłbyś raz jeszcze, bo czegoś nie zrozumiałem. Każdy produkt ma zestaw specyfikacji, które określa logika aplikacji, na podstawie klasy produktu. W takim razie po co nam kategoria, skoro to samo robi klasa?

Ja to rozumiem tak:

  1. Mam produkt, smartfon.
  2. Logika aplikacji na podstawie kategorii pozwala utworzyć smartfon z danymi polami specyfikacji.

Innym razem mam monitor led. Jego kategoria to monitory, monitory led. Robię te same kroki co ze smartfonem. W takim razie co określa klasa produktu?

2

Produkt ma określoną klasę - tylko jedną, natomiast może należeć do wielu kategorii.

Możesz mieć np. damską suszarkę do włosów i wtedy:

  • ma klasę "suszarki"
  • należy np. do kategorii:
  1. AGD
  2. AGD->DO ŁAZIENKI
  3. AGD->DO ŁAZIENKI->SUSZARKI
  4. PRODUKTY WG. PŁCI
  5. PRODUKTY WG. PŁCI -> DAMSKIE

każda z tych 5-ciu kategorii to osobna kategoria - jeżeli robimy je rekurencyjnie w strukturze drzewa.

1 użytkowników online, w tym zalogowanych: 0, gości: 1