MVC a katalog app w Railsach

Architektura MVC dzieli aplikację na trzy części Model, View, Controller. Ale o tym wszyscy dobrze wiedzą. W Railsach katalogiem przechowującym tą strukturę jest katalog app. Jednak od jakiegoś czasu niektórzy twórcy zaśmiecają ten katalog w swoich aplikacjach. Jakiś czas temu napotkałem jakąś przykłądową aplikację prezentującą funkcje pewnego gema, która w app miała folder uploader. Przecież to jest nic innego jak logika biznesowa więc powinno być w ostateczności w app/model/uploader. Nie chcę wchodzić w kompetencje głównych developerów Railsów ale w Rails 3.1 katalog assets to przecież też nic innego jak widok więc mógłby być w app/view/assets. Podobnie jest z mailerem - tutaj wogóle tego nie rozumiem. Logika mailera jest w app/mailer/* a widoki mailera prawidłowo w app/view/* . Jakie jest wasze zdanie na ten temat ?

IMHO nie, bo przecież ani uploader, ani mailer nie są modelami, tym bardziej assety nie są widokami… A kto powiedział, że w app powinna być wyłącznie struktura MVC? Tym bardziej, że RoR nie jest MVC w ścisłym tego słowa znaczeniu.

@wafcio:
Z punktu widzenia mvc być może by tak wynikało, ale z pragmatycznego punktu widzenia pakowanie całej logiki biznesowej do katalogu models nie ma żadnych plusów nad podzieleniem. Dzięki temu wiesz, że jak szukasz mailera czy uploadera, to idziesz do odpowiedniego katalogu i masz tam powiedzmy 10, a nie 40 plików.

model != ActiveRecord, w railsach panuje jakieś takie przeświadczenie, że model to klasa, która ma coś wspólnego z bazą danych i dziedziczy po ActiveRecord :wink:

@tiwi: Wiem że MVC to tylko termin i jak to zwykle bywa nie jest on ściśle przestrzegany w RoR ale chyba katalogu app nie powinno się zawalać mnóstwem katalogów bo wyjdzie (wg struktury plików) coś co przypomina frameworki PHP (a fuj)
@drogus: Równie dobrze mogłoby być app/model/mailer, a jeśli dobrze zorganizuje się ułożenie modeli to wszystko jest przejrzyste.

Co do uploadera to się zgodzę, ale mailera bym już pod model nie podciągał. A pakowanie tego wewnątrz app/models jest też o tyle niebezpieczne, że może być mylące, gdy mamy jakieś moduły/namespace itp. Wydaje mi się, że wtedy może być jeszcze większe zamieszanie.

polecam doczytać o MVC- w żadnej aplikacji opartej o http nie jesteś w stanie zrobić “true MVC” bez opierania się o rozwiązania typu ajax.

to raczej dziesiątki frameworków phpowych są kopiami railsów, nie na odwrót :wink:
Druga sprawa, że w imię koszerności chcesz pozbawić się wygody. Gdzie wrzucisz helpery? Ja mam kilka dodatkowych folderów w paru aplikacjach (takich jak: workers, observers, uploaders czy validators) i wydaje mi się że mam porządek w folderach :wink:

do kosza :stuck_out_tongue:

polecam doczytać o MVC- w żadnej aplikacji opartej o http nie jesteś w stanie zrobić “true MVC” bez opierania się o rozwiązania typu ajax.[/quote]
To już jest inna sprawa, railsy to bardziej Model2

A mailer to już nie jest logika aplikacji? :slight_smile:

Już wiem do czego zmierzasz :wink: Chodziło mi o tutaj o próbę szufladkowania klasycznego MVC, gdzie taki mailer nie musi mieć nic wspólnego z danymi, czyli modelem. To że w railsach logikę wrzucamy do modeli, to inna sprawa :slight_smile: Podsumowując, moim zdaniem nie ma sensu na siłę rozdzielać struktury aplikacji wyłącznie na MVC, bo pewne klasy (lub inne elementy, np. assety) po prostu się nie mieszczą w tych ramach i warto je wydzielić osobno :slight_smile:

Model = logika biznesowa (czy źle to rozumiem)

Co do mailera to jest tu pewna niekonsekwencja, bo mamy katalog app/mailer w którym znajdują się pliki mailera i w moim odczuciu jest to w pewnym sensie logika biznesowa a widoki mailera są w app/views. Z jednej strony chcą się dopasować do struktury a z drugiej strony widze, że główni dewelperzy nie lubią tworzyć podkatalogów w katalogów modeli (w czystej aplikacji Railsowej). Jeśli mailer nie jest logiką biznesową i poniekąd ławiej można go znaleźć w app/mailer to widoki mailera powinny być tak samo łatwe do odnalezienia i logiczne powiązane z mailerem (pomijam fakt że można samemu ustawić odpowiednie ścieżki)

[quote=wafcio]Model = logika biznesowa (czy źle to rozumiem)

Co do mailera to jest tu pewna niekonsekwencja, bo mamy katalog app/mailer w którym znajdują się pliki mailera i w moim odczuciu jest to w pewnym sensie logika biznesowa a widoki mailera są w app/views. Z jednej strony chcą się dopasować do struktury a z drugiej strony widze, że główni dewelperzy nie lubią tworzyć podkatalogów w katalogów modeli (w czystej aplikacji Railsowej). Jeśli mailer nie jest logiką biznesową i poniekąd ławiej można go znaleźć w app/mailer to widoki mailera powinny być tak samo łatwe do odnalezienia i logiczne powiązane z mailerem (pomijam fakt że można samemu ustawić odpowiednie ścieżki)[/quote]
Myślę że trochę za bardzo do serca bierzesz sobię to jak twórcy frameworka podzielili folder app. Według mnie to jest tylko wskazówka, dobra rzecz na początek. Ale framework jest po to żeby ci pomagał, dawał “fundament” pod rozbudowę, a nie ograniczał. Dlatego jeżeli ktoś uważa, że mu będzie wygodniej dać jakiś nowy katalog typu uploaders czy mailers to czemu nie. Kwestia decyzji teamu. Na przykład ostatnio zacząłem z partnerem w projekcie mały eksperyment - głównie za sprawą “Objects on rails” (http://avdi.org/devblog/2011/11/15/early-access-beta-of-objects-on-rails-now-available-2/) - w katalogu models mamy tylko tzw encje - modele które są bezpośrednio powiązane z bazą danych. A logika biznesowa jest w katalogu domain gdzie klasy nie mają w ogóle szytwnego połączenia z Railsami. Co z tego wyjdzie - nie wiem, to dopiero początek. Ale warto poeksperymentować.

Czy w Railsach w ogóle da się skonfigurować katalogi w stylu “package-by-feature”, zamiast “package-by-layer”?? Zastanawiam się czy takie podejście nie jest bardziej uporządkowane i logiczne niż nawrzucanie wszystkiego co w aplikacji w 3 dostępne katalogi (model/view/contr.).

IMHO to by niesłychanie skomplikowało kod rails, gdyby udostępnić możliwość takiej konfiguracji, nie jestem pewien czy warto.

Są jednak półśrodki http://piotrsarnacki.com/2010/12/21/mountable-apps-tutorial/

IMHO to by niesłychanie skomplikowało kod rails, gdyby udostępnić możliwość takiej konfiguracji, nie jestem pewien czy warto.[/quote]
Jeszcze pytanie jak to widzisz, moim zdaniem by się dało :wink: Możesz podać przykład?

Podejście komponentowe. Jak tak bardzo chcesz, to masz to w cellsach. Jasne że można, ale istnieje próg po przekroczeniu którego koszt modularności jest wyższy niż korzyści z niej wynikające.

Modularność tak, ale chyba jednak nie podejście komponentowe w wydaniu Cells. Miałem bardziej na myśli ogólniejszą strukturę w stylu (powiedzmy dla jakiegoś sklepu):
app

  • shopping
  • payments
  • user administration
    Cellsy od razu idą w szczególy -> ShoppingCart, które znowu rozszerzają jakieś klasy bazowe (jakąś analogię do ActiveRecordu widzę).
    Mam po prostu wrażenie, że często w przypadku gdy jakiś model/kontroler się rozrasta to jedyne co przychodzi do głowy człowiekowi (jeżeli już chce zrobić jakiś porządek) to przerzucenie nadmiarowych rzeczy do helperów/utili itp. No bo jak to tworzyć klasę ogarniającą kawałek logiki i trzymać ją między modelami kiedy sama modelem nie jest? Tą sytuację można spotkać nie tylko w railsowym projekcie.
    Czy w przypadku Cellsów nie byłoby podobnie? Tak samo trzyma się wszystkie komponenty w jednym worku w app/cells.
    Kiedy mam package-by-feature to wiem, że wszystko związane z daną funkcjonalnością mam w jednym konkretnym miejscu. I nie mam problemu z dzieleniem klas na mniejsze - cała funkcjonalność i tak podchodzi pod dany feature.

@pplcanfly
Jeżeli o tym mówisz, to nic prostszego, dodaj coś takiego do config/application.rb i będzie działać:

[code] paths = config.paths
paths.add “app/shopping/models”, :eager_load => true
paths.add “app/shopping/controllers”, :eager_load => true
paths.add “app/shopping/views”

initializer :more_view_paths, :after => :add_view_paths do
  views = paths["app/shopping/views"].existent
  ActiveSupport.on_load(:action_controller) { append_view_path(views) }
  ActiveSupport.on_load(:action_mailer)     { append_view_path(views) }
end[/code]

Dla ułatwienia więcej przykładów w konfiguracji samych railsów:

Przy okazji, jakiś czas temu naprawiając jedną rzecz w engine’ach dodałem kod, który przy migracjach bierze pod uwagę też migracje z podkatalogów, np. /db/migrate/shopping/

Nie wykorzystaliśmy tego wreszcie, bo utrudnia to chociażby przeglądanie migracji chronologicznie używając zwykłego ‘ls’, ale jeżeli Ci to nie przeszkadza, to nic nie stoi na przeszkodzie, żeby też migracje sobie pogrupować.

Inna sprawa jest taka, czy przy takim dzieleniu nie lepsze byłoby użycie właśnie engine’ów (takich zwykłych, nie mountable), które w dużym uproszczeniu robią to co te linijki powyżej - ładują kod leżący w katalogach z engine’em tak jakby leżał on bezpośrednio w aplikacji. Ale to już kwestia gustu.