Od roku pracuję jako Android Developerka i zauważyłam niezrozumiałą tendencję do używania wszystkich popularnych bibliotek czy wzorców projektowych.
Tutaj problemem jest akurat to, że rynek programistów Androida jest bardzo kreowany modą, pomijając frontend (chociaż nie wiem czy ostatnio nie zaczął wyprzedzać w tym wszystkim i frontendowej gonitwy). Wydaje mi się, że wynika to z kilku rzeczy. Po pierwsze Google przez długi, długi, długi czas w dokumentacji i przykładach miał przedstawione bardzo mierne rozwiązania. Jeżeli ktoś się uczył tylko i wyłącznie na podstawie ich kodu, to kończył z kodem spaghetti, którego nie dało się utrzymać. Dodatkowym problemem w tym wszystkim jest to, że Google pomimo robienia wielu fajnych rzeczy, robie też rzeczy obrzydliwe. Jeszcze gorzej dla nas, bo są wbudowane bezpośrednio w Androida. Świeża osoba myśli sobie, że skorzysta z tych rzeczy, żeby za jakiś czas ugrząźć w złych abstrakcjach albo niewystarczającym API. Sfrustrowany developer szukał wtedy jakiegokolwiek rozwiązania i sprawdzał miliony rzeczy albo pisał własne, które niestety miały zastosowanie w kilku konkretnych przypadkach albo nie dostarczały wystarczająco wiele i koło się napędzało.
Drugi problem jest taki, że w Google jesteś nagradzany głównie za innowacyjność. Jeżeli biblioteka jest pełna bajerów, fajerwerków itd. to będzie miałą wyższy priorytet niż np. udogodnienia do testowania rzeczy związanych z frameworkiem. Kończy się to wieloma nowymi rozwiązaniami, które Google promuje i które ludzie sprawdzają i adaptują w projektach. To jest akurat naturalne, że chcemy się bawić nowymi zabawkami zamiast zostawać przy starych. Niestety tych zabawek robi się za dużo i nierzadko robi się je źle.
Po trzecie Android jakotaki jest relatywnie młody i nie ma wielu doświadczonych programistów. Im mniej doświadczenia, tym łatwiej o pokusę.
- W jakim celu 25letni Androidowi Seniorzy/Team Leaderzy wymagają MVVM z databindingiem(ten od Googla), Daggera i jakiś dziwnych ORMów.
Zakładam, że chodzi o bibliotekę MVVM. Ogólnie należy korzystać jakiegoś MV-X (czy to P, C, VM, cokolwiek), ale o tym w innym pytanie. Czemu akurat chcą MVVM? To pytanie raczej do nich. Sam w pracy korzystam z MVVM, mimo że biblioteka jest moim zdaniem zbędna i nie wnosi niczego. Dlaczego? Bo jeżeli jest duża rotacja w projektach, to dużo łatwiej jest wejść w projektu, który korzysta ze znanych przeciętnemu klepaczowi rozwiązań. To akurat jest wymówka z mojej strony. Gdybym miał czas, to wywaliłbym MVVM z projektu, ale niestety germańscy klienci + germańscy architekci + germański menadżment = brak czasu na cokolwiek poza absolutnym minimum.
Czemu DataBinding? Nie mam pojęcia, bo nie jestem masochistą i uważam, że jest zła. Możesz przejrzeć ten temat, żeby poznać moje zdanie bardziej, jeśli Cię interesuje - Korzyści z DataBinding. Ostatecznie, to mnie nie obchodzi z czego ludzie korzystają, bo to ich sprawa. Są ludzie, którym ta biblioteka przyspiesza i usprawnia pracę. Na zdrowie. U mnie wywołuje odruch wymiotny.
O Daggerze i ORMach w kolejnych pytaniach.
- Czy ten Dagger to naprawde główna biblioteka ? Czy tak ciężko wstrzyknać te obiekty przez konstruktor ? Nawet na studiach nie jest poruszane wstrzykiwane zależności, bo to tylko wypadkowa myślenia człowieka który poradził sobie z maturą. Tak, zgadzam się, że można wymyślić przykład matrioszki w której użycie Daggera będzie łatwiejsze, ale bez przesady, ile razy trafimy na takie coś w realnym projekcie ? Nawet przyjemnie będzie to napisać w Javie.
Zależy. Poniżej Androida 28 nie ma możliwość wstrzykiwać przez konstruktor, bo nie ma się do niego dostępu na poziomie frameworka. AppComponentFactory zostało dodane dopiero w API 28, więc poczekamy jeszcze 3, 4 lata zanim będzie można rzeczywiście używać.
Natomiast sam Dagger, o ile dobrze skonfigurowany, robi dokładnie to, co napisałaś. Przekazuje obiekty przez konstruktor. Możesz nawet podejrzeć wygenerowany kod, żeby zobaczyć, jak to jest robione. Wyjątkiem są klasy Androidowe, do których wsrzykuje się przez odwołanie się do kontenera (inaczej się na tę chwilę nie da). Z tego powodu WSZYSTKO, co związane z Androidem, powinno mieć jak najmniej zależności.
Teraz pytanie, po co Dagger, skoro samemu można napisać cały ten kod? Przede wszystkim, żeby ułatwić testowanie end-to-end, integracyjne i przyspieszyć konfigurowanie aplkacji. Tu wychodzi lekki problem, bo żeby zobaczyć korzyści wynikające z korzystania z tej bibloteki, aplikacja tych zależności musi trochę mieć. Pi razy drzwi tych zależności musi być w górnym przedziale dziesiątek, żeby odczuć zalety. Bo niestety Dagger jest bilbioteką skomplikowaną i wymaga trochę konfiguracji. Dodatkowo można go skonfigurować niewydajnie dosyć łatwo - nie że będzie jakoś specjalnie zamulał, ale można często dużo rzeczy usprawnić w typowych konfiguracjach, jakie zazwyczaj widzę. Czy są alternatywy? Są. Czy są lepsze? Moim zdaniem nie, ale nie będę się na wstępie o tym rozpisywał.
- Dlaczego nie możemy informować innych miejsc w aplikacji o jakiejś zmianie używając natywnego BroadcastReceivera tylko robimy to przez RxJave?
Pierwsza ważna rzecz to sposób przesyłania danych za pomocą Receivera jest ograniczony. Tracisz bardzo dużo ze statycznego typowania. Kod zaczyna wtedy przypomniać trochę JavaScript, a jednak fajnie jest zrzucić na kompilator tak dużo, jak to tylko możliwe. Dodatkowo, Twoje klasy muszą implementować Parcelable, więc zaczynają zależeć od frameworka. Jeżeli chcemy tego uniknąć, to musimy tworzć nowe klasy i robić dla nich mapowania. Trochę lipa.
Problem numer dwa to testowanie takiego kodu. Receivery same w sobie należą do frameworka. Gdyby Twoja klasa biznesowa zależała od takiego Receivera to masz problem. Masz kilka wyjść i żadne nie jest fajne.
- Piszesz testy integracyjne i odpalasz je na telefonie. Takie testy pisze się ciężko (niektórych praktycznie się nie da) i odpala się powoli, co skutkuje małą iteracją.
- Mockujesz na potęgę i nie testujesz tak naprawdę niczego.
- Korzystasz z np. Robolectric, co skutkuje ponownie mockowaniem na potęgę oraz wyrywaniem sobie włosów z głowy co jakiś czas, bo Robolectric nagle przestał działać.
Problem numer trzy to liche (a dokładnie żadne) API dla BroadcastReceivera. Nie możesz robić fajnych rzeczy, na które pozwala RxJava. Natomiast Receivery i Rx nie są w stosunku do siebie ortogonalne. Receivery można opakować w Rx i mieć dostęp do genialnego API.
To samo z ORM'ami, natywną bazę danych możemy zmieścić w 1 klasie i mamy pełniejszą kontrolę nad tym co się dzieje.
ORM'ami gardzę. Zwłaszcza na Androidzie, gdzie nie wpasowują się w model wątkowy platformy (Baza danych w Androidzie). Natomiast jakaś abstrakcja mądra abstrakcja jest przydatna. Unika się wtedy błędów w runtimie dzięki wsparciu IDE albo kompilatora.
- Teraz tak bardziej projektowo. MVP? MVVM ? HWDP ? Na co to komu ? Wystarczy odrobina rozsądku żeby ładnie odseparować modele, widoki czy co tam chcecie. Czasami przy prostych projektach widzę taką abstrakcję, że nie umiem zmienić wyświetlającego się tekstu na ekranie.
No i oczywiście nigdy idealnie nie zrobicie wszystkiego zgodnie z jednym wzorcem projektowym + każdy interpetuje go inaczej, już nie raz nie dwa widziałam na tym forum awanturę doświadczonych osobników inaczej rozumiejących MVC.
Temat rzeka (jak każdy tutaj ;)). Co do skrótowców - zgadzam się jak najbardziej. Idiotyzm do kwadratu, wynikający głównie z problemu wspomnianego w pierwszym pytani, czyli gonieniem za modą. Natomiast na co to komu? Bo są pewne rozwiązania, które ułatwiają rozwijanie aplikacji. Czyli tak jak napisałaś - odseparować model od widoku. Aczkolwiek należy pamiętać, że Model (ten przez wielkie M) to nie jest Pies.java
, Drukarka.java
, LampkaNocna.java
. Tylko wszystkie klasy, które wprowadzają interakcję między tymi przykładowymi klasami. Są też architektury, gdzie klasy typu Skarpeta.java
są Modelem, ale nie będę robił dygresji na ten temat. Kolejny temat podlinkuję - Architektura MVP z Interactorem i Repository.
- Nie można po staremu zrobić katalogów z aktywnościami, fragmentami, serwisami, modelami itp ? Każdy będzie wiedział o co chodzi.
Można, ale ciężko taką aplikację rozwijać, testować i utrzymywać. Tzn. taką w oparciu tylko o te komponenty.
- Clean architecture ? - tego w ogóle nie znam więc nie krytykuję, ale może ktoś ma coś do powiedzenia.
Clean architecture jest fajne, bo uczy, że należy Androida (i każdy inny framework) traktować jak wroga. Jako coś, co psuje nasz aplikację i chce ją sobą zarazić. Bo framework powinien być pluginem do naszej aplikacji, który wyświetla obliczone przez nią wyniki i ewentualnie dostarcza dane od użytkownika.
- Pozbycie się fragmentów - w jakim celu ?
Ponieważ Fragmenty razem z FragmentManagerem są jednym z grzechów głównych Googla. Zachowują się w sposób nieprzywidywalny, są piekielnie trudne do debugowania i robią za dużo jednocześnie. Jest o tyle dobrze, że natywne Fragmenty już nie są wspierane i kiedyś w odległej przyszłości (oby przed śmiercią cieplną Wszechświata) Google je usunie z SDK. Żeby zrozumieć problemy związane z nimi wystarczy popatrzeć na ten obrazek. Z tym się nie da logicznie dyskutować. Zwłaszcza w przypadku bugów. A dodaj do tego, że cykl życia Fragmentu zależy od cyklu życia Activity.
FragmentManager z kolei, to najbardziej chory wymysł, jaki mógł powstać. Zamiast śledzić jaka była historia np. jakichś kluczy, po których można się poruszać w aplikacji i dać do nich dostęp, żeby móc tym łatwo manipulować, to nie. Google musiał zlecić tę klasę do zaprojektowania upośledzonemu koniowi i zapisywać transakcję między jednym fragmentem a drugim. Powodzenia w manipulowaniu tym. Na szczęście można z Fragmentów korzystać bez FragmentManagera i napisać jakiś własny stos. W projekcie tak mam. Fragmentów nie wyrzuciłem przez te same problemy, co z MVVM.
To sobie ponarzekałem. Natomiast jeżeli ktoś ma aplikację na dwa ekrany, wie, że tak zostanie na amen, i nie pisze jej dla nauki / rozrywki, to oczywiście nie ma sensu robić niewadomo jakich abstrakcji i korzystać z multum bibliotek. Za każdym razem jak widzę, że ktoś dodaje RxJavę tylko dlatego, że nie umie poradzić sobie z asynchornicznymi zapytaniami, to umieram w środku. Nie trzeba takiej kobyły do tego.
Może pytanie do Ciebie skoro niektóre rzeczy wydają Ci się zbędne i wnoszą niepotrzebny chaos - jak duża była największa aplikacja, którą napisałaś i co robiła? Pytanie bonusowe - czy była pokryta testami?