Review codu. Pomysły jak to skrócić?

0

W jaki sposób można by ulepszyć/skrócić inicjację obiektów implementujących wzorzec budowniczego?

W aplikacji korzystam z biblioteki do prawie automatycznego tworzenia NavigationView ( prawie, za to trzeba zdefiniować trylion parametrów) https://github.com/mikepenz/MaterialDrawer
Przykładowa inicjacja pojedyńczego navigation view potrzebuje inicjacji obiektu Drawer do którego dodajemy następne obiekty ( header, rozwijane listy, pojedyńcze elementy, czy co tam chcemy i ile chcemy).

Wersja standardowa. Parametry bylejakie przykładowe.

        // 2 pozycje w navigation view
        SecondaryDrawerItem item1 = new SecondaryDrawerItem()
                .withIdentifier(1)
                .withName(R.string.drawer_item_send_intention)
                .withIcon(R.drawable.ic_add_a_photo)
                .withTextColor(Color.WHITE)
                .withTag(WHICH_FRAGMENT.EVENTS);
        SecondaryDrawerItem item2 = new SecondaryDrawerItem()
                .withIdentifier(2)
                .withName(R.string.drawer_item_send_intention)
                .withIcon(R.drawable.ic_add_a_photo)
                .withTextColor(Color.WHITE)
                .withTag(WHICH_FRAGMENT.EVENTS);

        // expandable list view do którego dodajemy item1 i item2
        ExpandableDrawerItem expandableList = new ExpandableDrawerItem()
                .withIdentifier(3)
                .withIcon(R.drawable.ic_add_a_photo)
                .withName(R.string.intentions)
                .withSelectedTextColor(getResources().getColor(R.color.pink_500))
                .withTextColor(getResources().getColor(R.color.pink_500))
                .withSelectedColor(getResources().getColor(R.color.teal_100))
                .withSubItems(item1 , item2);

        Drawer result = new DrawerBuilder()
                .withActivity(this)
                .withToolbar(toolbar)
                .withTranslucentStatusBar(true)
                .withActionBarDrawerToggle(true)
                .withActionBarDrawerToggleAnimated(true)
                .withAccountHeader(accountHeader)
                .withSliderBackgroundDrawableRes(R.drawable.nav_view_background)
                .addDrawerItems(
                        new DividerDrawerItem(),
                        expandableList ,
                        new DividerDrawerItem()
                )
                .build();

To jest tylko przykład, parametrów jest/może być więcej.
Jest to duże ułatwienie, ponieważ nie trzeba bawić się w żadnego rodzaju pliki xml/ adaptery, ale za to definiowanie tego może być ścianą kodu ( wyobraźcie sobie 10 takich pozycji w NavigationView).
Biblioteka implementuje wzorzec builder i w zasadzie jest on między innymi po to, żeby można było pozbyć się konstruktorów z 9213321 parametrami. Mimo wszystko dosyć mi się nie podoba to ilościowo.

Jakie macie odczucia co do zrobienia klasy rozszerzającej powyższe obiekty i przeniesienia do konstruktora parametrów które zawsze są definiowane?
Czyli, dla przykładu dla SecondaryDrawerItem :

public class CustomSecDrawerItem extends SecondaryDrawerItem {

    private CustomSecDrawerItem(int identifier, int nameId, int iconId,
                                int textColorId, Const.WHICH_FRAGMENT type) {
        this.withIdentifier(identifier)
                .withName(nameId)
                .withIcon(iconId)
                .withTextColor(textColorId)
                .withTag(type);
    }

    public static CustomSecDrawerItem newInstance(int identifier, int nameId, int iconId,
                                                  int textColorId, Const.WHICH_FRAGMENT type) {
        return new CustomSecDrawerItem(identifier, nameId, iconId, textColorId, type);
    }
}

Gdzie inicjacja SecondaryDrawerItem w kodzie wyglądałaby tak:

        CustomSecDrawerItem item1= CustomSecDrawerItem.newInstance(1, R.string.drawer_item_send_event,
                R.drawable.ic_add_a_photo, Color.WHITE, WHICH_FRAGMENT.EVENTS);

Prawdopodobnie zaimplementowałbym to też dla innych obiektów z pierwszego kodu.
Trochę to zataczanie koła i sam nie wiem. O wiele mniej czytelne. Chciałbym żeby to po prostu było krótsze, a ze względu na ilość oraz zmienność parametrów pomiędzy poszczególnymi obiektami ciężko mi jakoś to wykroić.
Może zapisać sobie te parametry w listach w folderach resources i później podczytać i tworzyć fabryką?

0
  1. Czy ktoś Cię zmusza do korzystania z buildera?
  2. Jak chcesz produkować obiekty w inny sposób, to zrób sobie fabrykę, która Ci je stworzy w taki sposób w jaki chcesz i będzie przyjmowała takie parametry jakie sobie życzysz. W implementacji fabryki możesz nawet użyć buildera jeśli uznasz to za zasadne.
0

To jest kod, którego nikt nie będzie nigdy czytał ani nad nim główkował. Więc niech sobie będzie długi choćby na 1000 wierszy. Może bym wywalił to do odzielnego pliku, żeby nie kłuło w oczy. Można podzielić na jakieś większe całości w postaci funkcji, np. createXXXDrawer.

Dzisiaj odchodzi się od plików konfiguracyjnych i zastępuje je konfiguracją w kodzie. Więc takie potworki będą miały swoje miejsce i rację bytu. Ja bym z nimi nie walczył.

0

Konstruktor jest według mnie gorszym rozwiązaniem, bo przestaje być widać, co jest czym. Parametr R.string.drawer_item_send_intention to jeszcze pół biedy, ale sekwencje w rodzaju true, true, false, true są nieszczególnie czytelne ;)

Peter Norvig napisał kiedyś, że większość wzorców projektowych to nic innego jak sposoby na zrekompensowanie braków w języku. Tak jest z wzorcem budowniczy, który (w każdym razie w tego typu scenariuszu użycia - zdecydowanie najczęściej spotykanym) jest w Javie taką protezą zastępującą parametry nazywane, których ona nie wspiera.

Gdybyś użył Kotlina, kod mógłby się stać nieco zwięźlejszy, np.:

val expandableList = ExpandableDrawerItem(
    identifier = 3,
    icon = R.drawable.ic_add_a_photo,
    name = R.string.intentions
    // etc.
0

W teorii całkiem dużo można zrobić pisząc tak:

 SecondaryDrawerItem template= new SecondaryDrawerItem()
                .withName(R.string.drawer_item_send_intention)
                .withIcon(R.drawable.ic_add_a_photo)
                .withTextColor(Color.WHITE)
                .withTag(WHICH_FRAGMENT.EVENTS);


        SecondaryDrawerItem item1 = template.withIdentifier(1);
        SecondaryDrawerItem item2 = template.withIdentifier(2);

Ale ponieważ wiekszość tooli w javie generuje mutowalne buildery/obiekty (!!!) więc to może łatwo doprowadzić do katastrofy.
Jeśli jednak masz w kodzie / zespole zaprowadzony niemutowalny totalitaryzm to wtedy ten koncept całkiem ładnie pomaga.

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