Jak lepiej projektować aplikacje webowe?

0

Witam,

Od roku pracuje z Python i Django. Na początku byłem podekscytowany możliwościami tego frameworka, ponieważ wysokopoziomowa natura Pythona pozwolała mi w Django bardzo szybko tworzyć kod do małych projektów.

Teraz, gdy tego kodu mam coraz więcej do utrzymania to jest coraz gorzej, ponieważ z powodu modeli ORM ciężko jest pracować nad logiką biznesową, a tym bardziej tworzyć testy jednostkowe.

Do tej pory próbowałem upychać logikę do modeli, ale wtedy uzyskiwałem Fat Models :/ Później robiłem odwrotnie, modele robiłem możliwie lekkie, a logikę przenosiłem do funkcji pomocniczych.

Koniec końców, w dobie OOP mam wrażenie, że mój kod to same struktury i procedury :[

Pytania:

  1. Jak to możliwe, że w świecie Javy i C# tak bardzo użyteczne są wzorce projektowe skoro ORM psuje hermetyzacje, abstrakcje, dziedziczenie i polimorfizm.

  2. W internecie widzę czasem teksty o DDD, które mówią o warstwie modelu dziedziny. Czy ta technika jest przerostem treści nad formą? Jak używanie tej techniki ma się do języków takich jak Python, Ruby, PHP?

  3. Jakimi książkami powinienem się zainteresować, żeby dowiedzieć się jak lepiej projektować?

0
pydj napisał(a):
  1. Jak to możliwe, że w świecie Javy i C# tak bardzo użyteczne są wzorce projektowe skoro ORM psuje hermetyzacje, abstrakcje, dziedziczenie i polimorfizm.

ORM niczego nie psuje. Musisz go bardzo źle używać, skoro tak twierdzisz.

ORM to koncepcja łączenia aplikacji z bazą danych, inna niż Active Record czy Table Data Gateway czy też Row Data Gateway, ale na pewno najbardziej obiektowa z nich wszystkich.

  1. W internecie widzę czasem teksty o DDD, które mówią o warstwie modelu dziedziny. Czy ta technika jest przerostem treści nad formą?

Nie, z wyjątkiem bardzo małych programów. Generalnie im większy system, tym większy sens ma podejście DDD.

Jak używanie tej techniki ma się do języków takich jak Python, Ruby, PHP?

PHP samo jest swoim modelem dziedziny. ;)

  1. Jakimi książkami powinienem się zainteresować, żeby dowiedzieć się jak lepiej projektować?

Poza GoF, to np.:
http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215
http://www.amazon.com/gp/product/0321127420/

0

ORM niczego nie psuje. Musisz go bardzo źle używać, skoro tak twierdzisz.

Co mam robić w przypadku, gdy model posiada kolumnę kind zawierającą informację o tym z jakim rodzajem obiektu mamy styczność? Od tego pola zależy jak różne akcje będą obsługiwać wybraną instancję modelu.

Efekt końcowy, zamiast polimorfizmu i różnych typów muszę bazować na 1 modelu i sekwencji ifów.

0

Ale niby kto Ci broni używać dziedziczenia i polimorfizmu? Przecież nie trzeba wszystkich pól obiektu mapować na kolumny tabeli, dziedziczenie też jest wspierane przez ORMy...

Opisz dokładniej problem i zobrazuj go jakimś kodem, bo nic z tego nie rozumiem.

0
class Report(models.Model):
    KIND_WORKTIME = 10
    KIND_DISTANCE = 20
    KIND_FUEL = 30
    KIND_CHOICES = (
        (KIND_WORKTIME, 'Czas pracy'),
        (KIND_DISTANCE, 'Dystans'),
        (KIND_FUEL, 'Paliwo')
    )
    created_at = models.DateTimeField(auto_now_add=True)
    cars = models.ManyToManyField(Car)
    kind = models.IntegerField(choices=KIND_CHOICES)
    from_date = models.DateField()
    to_date = models.DateField()
    range_count = models.IntegerField()
    fuel = models.FloatField(null=True)
    distance = models.IntegerField(null=True)
    time = models.IntegerField(null=True)

W powyższym kodzie mamy pewien przykład. Obecnie w aplikacji ma być kilka rodzajów raportu. Póki co mam generować osobny raport dla raportu z paliwem, osobny raport dla raportu z dystansem, osobny raport dla raportu z czasem. Przechowuje pola fuel, distance, time, bo to są pola wartości jakie mogą zostać wykorzystane dla różnych rodzajów raportu. Później klient może sobie zażyczyć raport z distance + time albo inaczej.

Na sam koniec klient ma mieć wszystkie wygenerowane raporty dostępne na liście w jednym widoku.

Zarówno selekty do bazy danych, jak i sposób renderowania jest zależny od pola kind.

0
pydj napisał(a):
class Report(models.Model):
    KIND_WORKTIME = 10
    KIND_DISTANCE = 20
    KIND_FUEL = 30
    KIND_CHOICES = (
        (KIND_WORKTIME, 'Czas pracy'),
        (KIND_DISTANCE, 'Dystans'),
        (KIND_FUEL, 'Paliwo')
    )
    created_at = models.DateTimeField(auto_now_add=True)
    cars = models.ManyToManyField(Car)
    kind = models.IntegerField(choices=KIND_CHOICES)
    from_date = models.DateField()
    to_date = models.DateField()
    range_count = models.IntegerField()
    fuel = models.FloatField(null=True)
    distance = models.IntegerField(null=True)
    time = models.IntegerField(null=True)

W powyższym kodzie mamy pewien przykład. Obecnie w aplikacji ma być kilka rodzajów raportu. Póki co mam generować osobny raport dla raportu z paliwem, osobny raport dla raportu z dystansem, osobny raport dla raportu z czasem. Przechowuje pola fuel, distance, time, bo to są pola wartości jakie mogą zostać wykorzystane dla różnych rodzajów raportu. Później klient może sobie zażyczyć raport z distance + time albo inaczej.

Na sam koniec klient ma mieć wszystkie wygenerowane raporty dostępne na liście w jednym widoku.

Zarówno selekty do bazy danych, jak i sposób renderowania jest zależny od pola kind.

imho powinineś rozbić to na ReportFuel, ReportDistance itd. Osobne modele powinny przechowywać swoją wartość, sposób renderowania oraz relację do Report.

0

@pydj patrząc na ten twój kod to nie sposób sie nie zgodzić że Koniec końców, w dobie OOP mam wrażenie, że mój kod to same struktury i procedury, ale to nie wina technologii, ORMów czy języka, tylko twoja. Po prostu nie rozumiesz na czym polega programowanie obiektowe i sensowne projektowanie.

Przechowuje pola fuel, distance, time, bo to są pola wartości jakie mogą zostać wykorzystane dla różnych rodzajów raportu. Później klient może sobie zażyczyć raport z distance + time albo inaczej.

Brak mi słów. No bo przecież stworzenie hierarchii klas wśród raportów to zbyt skomplikowana sprawa i trzeba zrobić God Object który zawiera wszystkie możliwe informacje. A łączenie raportów? A jaki problem zrobić kompozytowy raport. Hierarchia klas niech określa potencjalne fragmenty raportu a raport niech będzie zbiorem fragmentów. I voila.

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