Czy dobrą praktyką jest zawijanie pokrewnego zestawu właściwości do własnej struktury / klasy?

10

Pisanie obiektu użytkownika w Swift, choć moje pytanie dotyczy dowolnego silnie napisanego języka. Użytkownik może mieć kilka linków (FacebookProfile, InstagramProfile itp.). Kilka pytań wokół tego.

  1. Czy dobrą praktyką jest zawijanie łączy we własnym obiekcie?
    struct Użytkownik {
       var firstName: string
       var lastName: string
       var email: string
       var links: Linki
    }
    Struktur Linki {
       var facebook: string
       var instagram: string
       var twitter: string 
    }

A może powinny być luźne? Wiem, że technicznie oba sposoby są w porządku, ale zastanawiam się, czy istnieje ogólnie zalecane podejście - szczególnie w zakresie czytelności.

struct User { 
   var firstName: string
   var lastName: string
   var email: string
   var facebookLink: string
   var twitterLink: string
   var instagramLink: string
}
  1. Czy w takim scenariuszu linki powinny być zbiorem / listą? Uznałem, że nie powinna to być lista, ponieważ dostępna jest stała liczba opcji linków, a nie rosnąca liczba. Czy moje myślenie jest prawidłowe?

  2. Czy dobrą praktyką jest umieszczanie moich metod sieciowych w obiekcie użytkownika, takich jak getUsers, getUser, updateUser?

Wiem, że mogą być subiektywne, ale staram się zrozumieć, jaka jest najlepsza praktyka w podobnych sytuacjach. Byłby wdzięczny za wszelkie wskazówki.

Prabhu
źródło

Odpowiedzi:

30

Albo będziesz potrzebować

  • zero rzeczy,
  • jedną z rzeczy lub
  • dowolna liczba rzeczy.

Jestem zszokowany, że twój projekt przewiduje, że liczba potrzebnych linków zawsze będzie wynosić trzy i że wiesz, jakie są ich nazwy na zawsze.

To, co głoszę, nazywa się zasadą zero jeden nieskończoności . Na początku może nie być to oczywiste, ale to mówi mi, że twój projekt nie toleruje przyszłości.

Czułbym się inaczej, gdyby było coś w tych linkach, co było dla nich wyjątkowe. Niektóre specjalne rzeczy, które robię inaczej, uzyskując dostęp do linku na Facebooku, których nie robię dla linku Twitter. To sprawi, że będą różne. Ale nie jest to wskazane w tym kodzie.

Właśnie dlatego ciąg e-maila nie przeszkadza mi. Wiem, że jest używany w inny sposób niż linki.

Więc dopóki nie zobaczę powodu, aby używać tych linków inaczej, jestem po stronie kolekcji linków.

candied_orange
źródło
4
FacebookProfile, InstagramProfile, ...Myślę, że OP już odpowiedział na pytanie. Jego język mówi nam, że Użytkownicy mogą nie mieć żadnego profilu lub kilku profili związanych z sieciami społecznościowymi. Ale programista w nim / nim zamienił ten element w zwykłe linki. Dlaczego nie kolekcja Profiles? Zgodziłem się z CandiedOrange. Za dużo zakładasz na przyszłość. Mogą pojawić się nowe sieci społecznościowe. Rzeczywiste mogą zniknąć. Użytkownicy mogą przechodzić z jednej sieci do drugiej.
Laiv
To zgadywanie. Powiedz, że chcesz używać tych profili do logowania do sieci społecznościowych. Mając komponent Profile, mamy od czego zacząć. Gdzie obudować informacje dotyczące uwierzytelnienia i bieżącej sesji za pomocą tych profili. Można to uznać za YAGNI lub nadmierną inżynierię, ale nie warto o tym myśleć, sprawdzić, czy można żądać tych funkcji lub czy mogą one stanowić wartość dla naszej aplikacji. Jeśli nie, po prostu je wyrzuć.
Laiv
1
@Prabhu zależy od tego, dlaczego je ograniczasz. Domyślam się, że tylko tyle pasuje do GUI. Co jest w porządku Ale nie ograniczaj struktury danych z powodu GUI. GUI zmieniają się pod wpływem kaprysu. Struktury danych są kosztowne. Naprawdę opłaca się je dobrze za pierwszym razem.
candied_orange
2
O to chodzi. Po prostu zastosuj te struktury, które sprawią, że przyszłe zmiany będą mniej bolesne. Nie więcej nie mniej. My, Candied i ja mówimy to, ponieważ (wierzę) często spotykamy się z podobnymi sytuacjami i przewidujemy możliwe cechy, które mogą ulec zmianie lub ewolucji. Ostatecznie jesteś bliżej projektu i jego przyszłej perspektywy.
Laiv
1
@Prabhu: Zauważ, że zadałeś pytanie o dobrą praktykę , a nie to, czy jest to najbardziej zwięzłe podejście do twojego konkretnego scenariusza. Zwykle jestem po stronie unikania nadmiernej inżynierii, ale koszt przyszłej konserwacji (dodawanie / usuwanie linków, aktualizacja definicji klas jednostek, ...) znacznie przewyższa koszt implementacji zbioru linków. Jeśli nazywa kolumn link1, link2, link3, potrzeba zbierania byłaby bardziej oczywista. Jednak fakt, że nadałeś kolumnom bardziej znaczącą nazwę, nie zmienia faktu, że jest to zbiór powtarzalnych danych.
Flater
6

Jesteś na skraju wpadnięcia w pułapkę „Widzę techniczną możliwość”.

To, że widzisz wspólną cechę wśród przedmiotów, nie oznacza, że ​​warto na nich zastosować agregację. Agregacja powinna coś znaczyć. Nie na poziomie technicznym, ale w domenie problemowej.

Wszystkie linki są w porządku, ale czy w kontekście klasy użytkownika to coś znaczy? Nie. Jest to tak samo pozbawione znaczenia, jak byłoby podgrupowanie za pomocą klas o nazwach „ciągi” i „liczby”.

Problem z tego rodzaju rzeczą polega na tym, że rozmazuje twój model. Zmusza czytnik kodów do odcięcia znaczącego od pozbawionego znaczenia, zanim będzie w pełni rozumieć domenę.

Nikt nigdy nie mówi o linkach użytkownika. Byłoby inaczej, gdybyś nazwał swoją agregację SocialNetworkIds. Ponieważ w rzeczywistości coś to znaczyłoby, byłaby to prawdziwa właściwość Użytkownika, a nie arbitralny zbiór techniczny.

Martin Maat
źródło
Właśnie moje wątpliwości skłoniły mnie do zadania tego pytania. Jedyną relacją między różnymi linkami jest to, że byłyby one prawdopodobnie wyświetlane razem w interfejsie użytkownika. W takim przypadku sugerujesz, aby NIE umieszczać ich w osobnym obiekcie, ale raczej trzymać je bezpośrednio pod obiektem użytkownika?
Prabhu
1
Nie sądzę, aby w tym przypadku byłoby to pomocne. Nie masz jeszcze problemu uzasadniającego dodanie warstwy złożoności. Gdybyś miał dużo więcej właściwości, może przydałby się wysiłek grupowania (z trafnymi nazwami dla grup). Trudno jednak powiedzieć, co jest właściwe bez kontekstu. Najważniejsze jest to, że powinno to ułatwić. Zrozumieć i / lub przejść do następnego etapu procesu programowania.
Martin Maat
I ogólnie jak unikanie nadmiernej inżynierii, ale ja dziwię: byś powiedział to samo, jeśli PO nazwał swoje pola link1, link2, link3? Struktura struktury danych jest niezależna od nazwy pól, więc mój przykład jest funkcjonalnie równoważny. To kwestia zabezpieczenia na przyszłość. YAGNI miałoby ogólnie zastosowanie, ale w ogóle media społecznościowe okazały się podatne na popularność i zmiany wirusowe. Pożądane wydaje się unikanie przebudowy każdego nowego popularnego serwisu społecznościowego. W przeciwnym razie ryzykujesz wpadnięcie w „co to jeszcze jedno pole?” pułapka, która może stworzyć ogromny dług.
Flater
1

Ogólnie rzecz biorąc, uważam, że rozsądne byłoby posiadanie odnośników, structjeśli prawdopodobnie zastosujesz podobne operacje do każdego z nich, a zwłaszcza jeśli zawsze będziesz wykonywać te same operacje na wszystkich z nich. Jeśli są one w twoim wniosku niezwiązane z celami, to bym je rozdzielił. Na przykład, jeśli byliby stroną domową użytkownika, witryną ubezpieczyciela i linkiem do ich ulubionej witryny z wiadomościami, prawdopodobnie nie zgrupowałbym ich razem, ponieważ wydają się niezwiązani. Ale w przypadku 3 serwisów społecznościowych wygląda na to, że będą one traktowane podobnie w aplikacji i jako takie powinny być prawdopodobnie zgrupowane razem. Użyłbym bardziej opisowej nazwy niż Linkschociaż. (Jaki typ linków? W jakim celu w Twojej aplikacji?)

Zgadzam się z twoim myśleniem na # 2. Jak wspomniano powyżej, jeśli liczba miałaby rosnąć lub stać się zmienną, lista lub inna kolekcja byłaby dobrym wyborem, ale nie dla opisanego scenariusza.

Nie umieszczałbym metod sieciowych w obiektach przechowujących dane pobrane przez sieć. Skąd pochodzą dane i jak je uzyskać, zwykle nie mają znaczenia dla głównego celu klasy. Co jeśli w przyszłości chcesz uzyskać dane z dysku? Lub chcesz, aby użytkownik go wprowadził? Idź wystarczająco daleko tą drogą, a prosta Userklasa musi mieć kod do obsługi każdej możliwej metody wprowadzania i wyszukiwania danych. Po prostu Userzatrzymaj klasę i zachowaj dane, gdy są one w pamięci. Wszystko inne może być obsługiwane przez bardziej odpowiednie klasy.

użytkownik1118321
źródło