Współpraca Entity |
Współpraca Entity |
4.06.2018, 14:39:05
Post
#1
|
|
Grupa: Zarejestrowani Postów: 898 Pomógł: 48 Dołączył: 2.11.2005 Skąd: Poznań Ostrzeżenie: (0%) |
Mam takie pytanie teoretyczne, które od czasu do czasu pojawia się w moich projektach. Najlepiej chyba będzie opisać na przykładzie.
Piszę aplikację sportową (konkretnie dla pływaków) we frameworku Symfony i w niej mam między innymi dwa obiekty Entity: - User - Interval Użytkownik ma pewne cechy definiowalne - np. prędkość bazową (dajmy na to 2:00/100m), modyfikatory prędkości (np. gdy ma płetwy to płynie 10s/100m szybciej niż bez etc). Interwał to cegiełka z której buduję treningi do wykonania. Czyli każdy interwał posiada między innymi: - dystans do pokonania - prędkość wyrażoną jako prdkość bazowa +/- x sekund. - listę modyfikatorów do zastosowania - czyli np. dany interwał użytkownik ma płynąć w płetwach I teraz dochodzimy do tego co mnie interesuje. Mam konkretny interwał w którym jest płyń z prędkością bazową - 5s oraz użyj płetw. Mam konkretnego użytkownika, dla którego prędkość bazowa to 2:00, a modyfikator płetw daje - 10s. Czyli finalnie ten konkretny użytkownik ma popłynąć ten konkretny interwał w tempie 2:00 (prędkość bazowa użytkownika) - 5s (ustawienie interwału) - 10s (bonus za płetwy) - razem daje 1:45/100m. Pytanie brzmi - jaki obiekt powinien obliczyć tą konkretną wartość, żeby było prawidłowo i zgodnie ze sztuką. Interwał raczej nie powinien wiedzieć o użytkowniku i vice versa. Robienie tych samych obliczeń w 50 miejscach (np. w kontrolerach) jest bez sensu i trudne w utrzymaniu. Osobiście w tym celu stosuję usługę, którą sobie nazwałem WorkoutService i mam tam takie funkcje jak np getIntevalPace. Zastanawiam się czy to jest dobre rozwiązanie, czy może jakoś inaczej powinienem to ogarniać. |
|
|
6.06.2018, 06:09:46
Post
#2
|
|
Grupa: Zarejestrowani Postów: 6 476 Pomógł: 1306 Dołączył: 6.08.2006 Skąd: Kraków Ostrzeżenie: (0%) |
1. Szczerze mówiąc nie jestem dokładnie pewien czy w pełni poprawnie rozumiem problem (tak patrząc całościowo) - to na start. Nie wiem też czy przykłady jakie podałeś wyczerpują różnorodność detali czy właściwie na tym kończą się ich wariacje. Fajnie jakbyś może pokazał nawet jakąś okrojoną wersję kodu źródłowego (szczególnie $workoutService'u) - nieraz mówi więcej niż jego opis.
2. Bardzo ważne jest to jak bardzo chcesz, czy właściwie jak bardzo potrzebujesz "rozdmuchać" obsługę tego problemu. Chodzi o to by jednak potencjalnie prostego problemu nie zacząć rozwiązywać w niepotrzebnie rozbudowany, skomplikowany i obszerny sposób (takie ang. overengineering). 3. Wstępnie wygląda to tak, że obiekty pod $interval, $vcsettings czy $workout to wyłącznie wory do przenoszenia złożonych danych (DTO), a obliczenia z nimi związane zamiast być blisko danych w postaci metod (jak to jest przewidziane w OOP) są wyniesione gdzieś zupełnie indziej w kodzie. 4. Na początek spróbuj może troszkę odwrócić relację pomiędzy obiektami. Zamiast $workoutService->getDuration($workout, $vcsettings) spróbuj do tego podejść jako $workout->computeDuration($vcsettings??, $workoutService??). Być może te $vcsettings powinny być przekazane już w konstruktorze, a ten drugi argument w ogóle stanie się już niepotrzebny? 5. Ten fragment kodu (związany z samą logiką aplikacji) w miarę możliwości nie powinien mieć nawet świadomości Symfony, Doctrine'a (encji) czy innych frameworków. Dlaczego? Bo takie webowe FW nie chcą rozwiązywać konkretnych problemów, specyficznych dla Twojej aplikacji. Mają dać Ci szybką, solidną i wygodną "otoczkę" niezwiązaną bezpośrednio z celem działania samej apki (tutaj: wyliczania terningów), a związaną z całym tym "syfem" potrzebnym do tego by to gdzieś/jakoś/komuś uruchomić. Pozwól im skupić się na tym co faktycznie potrafią robić, samemu skupiając się mocno na swoim problemie - którego rozwiązanie już leży po Twojej stronie. Ten post edytował Crozin 6.06.2018, 06:15:19 |
|
|
Wersja Lo-Fi | Aktualny czas: 25.04.2024 - 08:16 |