Właściwości w ramach ARC: zawsze czy tylko publicznie?

9

Po przeczytaniu pokornie artykułu Roberta McNally'ego „Przykazania kodu: najlepsze praktyki kodowania Objective-C” nieco mniej niż dwa lata temu, zaadaptowałem praktykę używania właściwości dla prawie każdego członka danych z moich klas Objective-C ( trzecie przykazanie z maja 2012 r.). McNally wymienia następujące powody (moje podkreślenie):

  1. Właściwości wymuszają ograniczenia dostępu (takie jak tylko do odczytu)
  2. Właściwości egzekwują zasady zarządzania pamięcią (mocne, słabe)
  3. Właściwości zapewniają możliwość transparentnego wdrożenia niestandardowych programów ustawiających i pobierających.
  4. Właściwości z ustawieniami niestandardowymi lub obiektami pobierającymi mogą służyć do egzekwowania strategii bezpieczeństwa wątków.
  5. Posiadanie jednego sposobu dostępu do zmiennych instancji zwiększa czytelność kodu.

Większość moich nieruchomości umieszczam w kategoriach prywatnych, więc numery 1 i 4 zwykle nie są problemami, z którymi się spotykam. Argumenty 3 i 5 są bardziej „miękkie”, a przy odpowiednich narzędziach i innych konsekwencjach mogą stać się bezproblemowe. Wreszcie, dla mnie najbardziej wpływowy z tych argumentów był numer 2, zarządzanie pamięcią. Odtąd to robię.

@property (nonatomic, strong) id object; // Properties became my friends.

W ostatnich kilku projektach przestawiłem się na ARC, co wzbudziło we mnie wątpliwości, czy tworzenie właściwości praktycznie wszystkiego jest nadal dobrym pomysłem, czy może trochę zbędnym. ARC dba o zarządzanie pamięcią obiektów Objective-C, co dla większości strongczłonków działa dobrze, jeśli tylko zadeklarujesz ivars. Typy C, którymi musiałeś ręcznie zarządzać, przed i po ARC, a weakwłaściwości są przeważnie publiczne.

Oczywiście nadal używam właściwości do wszystkiego, co wymaga dostępu spoza klasy, ale w większości są to tylko garść właściwości, podczas gdy większość członków danych jest wymienionych jako ivars pod nagłówkiem implementacji

@implementation GTWeekViewController
{
    UILongPressGestureRecognizer *_pressRecognizer;
    GTPagingGestureRecognizer *_pagingRecognizer;
    UITapGestureRecognizer *_tapRecognizer;
}

Jako eksperyment robiłem to nieco bardziej rygorystycznie, a odejście od właściwości dla wszystkiego ma pewne pozytywne pozytywne skutki uboczne.

  1. Wymagania dotyczące kodu członka danych ( @property/ @synthesize) zmniejszyły się do deklaracji ivar.
  2. Większość moich self.somethingreferencji wyczyściłem tylko _something.
  3. Łatwo jest odróżnić, którzy członkowie danych są prywatni (ivars), a którzy publiczni (właściwości).
  4. Wreszcie, „wydaje się”, że to właśnie był cel, do którego Apple zamierzał mieć właściwości, ale to subiektywna spekulacja.

Na pytanie : powoli przesuwam się w stronę ciemnej strony, używając coraz mniej właściwości na rzecz implementacji ivars. Czy możesz podać mi trochę uzasadnienia, dlaczego powinienem trzymać się właściwości do wszystkiego, lub potwierdzić mój obecny ciąg myśli, dlaczego powinienem używać więcej ivarów i mniej właściwości tylko tam, gdzie jest to potrzebne? Najbardziej przekonująca odpowiedź dla każdej ze stron otrzyma mój znak.

EDYCJA: McNally waży na Twitterze, mówiąc : „Myślę, że moim głównym powodem pozostania przy właściwościach jest: jeden sposób na zrobienie wszystkiego, co robi wszystko (w tym KVC / KVO.)”

epolog
źródło

Odpowiedzi:

5

Czy możesz podać mi trochę uzasadnienia, dlaczego powinienem trzymać się właściwości do wszystkiego, lub potwierdzić mój obecny ciąg myśli, dlaczego powinienem używać więcej ivarów i mniej właściwości tylko tam, gdzie jest to potrzebne?

W tej chwili uważam, że można powiedzieć, że to głównie kwestia stylu. Jak mówisz, korzyści wynikające z zarządzania pamięcią są mniej ważne w przypadku ARC. Z drugiej strony „korzyści” powrotu do bezpośredniego dostępu do ivar również nie są zbyt przekonujące:

  1. Deklaracja @property jest dość podobna do deklaracji ivar. Unikanie dyrektywy @synthesize nie wydaje się dużą wygraną - nie mówimy o wielu kodach.

  2. foo.somethingSkładnia jest zapewne dużo lepiej niż _something. Składnia dostępu do właściwości jest oczywiście zaprojektowana tak, aby wyglądała i działała jak składnia kropkowa C w celu uzyskiwania dostępu do elementów struktury. selfPomocne jest wyraźne określenie, do którego obiektu masz dostęp (czy to, czy coś innego). (Niektórzy ludzie - nie ja! - opowiadają się self->somethingza dostępem do ivar z tego powodu.) Wiodąca konwencja podkreślania dla ivars jest w porządku, ale nie jest konsekwentnie używana przez cały kod Objective-C.

  3. Właściwości wydają się lepszym wyborem do uzyskiwania dostępu do danych przechowywanych w innych obiektach tej samej klasy (co jest dozwolone w ramach dostępu „prywatnego”) oraz do dostępu przez podklasy (np. „Chronione” w C ++). Tak więc idea „właściwości == public” jest nieco rozmyta.

  4. Mam wrażenie, że właściwości miały uprościć zarządzanie pamięcią i zapewnić inne korzyści. Jak mówisz, ze zmniejszoną korzyścią z zarządzania pamięcią, właściwości wydają się mniej atrakcyjne.

Wybrana przez ciebie ścieżka - powrót do bezpośredniego dostępu ivar dla wewnętrznych danych - wydaje się być bardzo rozsądnym wyborem i nie ma oczywistego powodu, aby zmienić kurs. Ale trzymanie się właściwości jest również całkiem rozsądne - wady nie są znaczące, a istnieją pewne miłe korzyści, takie jak zgodność z KVO i bardziej spójny styl dostępu do członka.

Właściwości nie były ostatnim krokiem w ewolucji Objective-C i nie oczekuję, że ARC też będzie. Nie mam żadnych konkretnych informacji, ale wydaje mi się, że w pewnym momencie można dodać dodatkowe funkcje, które czynią właściwości bardziej atrakcyjnymi lub mniej. Będziemy musieli poczekać i zobaczyć, co się stanie.

Caleb
źródło
1
Cześć @Caleb, dzięki za poświęcenie czasu i napisanie solidnego posta. Nie myślałem o aspekcie KVO. Naprawdę jestem bardzo ciekawy, gdzie Apple bierze to wszystko. ARC as wydaje się być jednym z szeregu kroków. Poczekam, aby zobaczyć, czy ktoś nie chce rozważyć tego tematu, w przeciwnym razie rozważ zaznaczone pytanie.
epolog
1
@epologee Cieszę się, że mogę pomóc. Kolejną rzeczą, którą należy dodać do kolumny plus dla ivars, jest to, że można je łatwo zobaczyć w debuggerze. Dotyczy to również właściwości, jeśli jawnie zadeklarowałeś ivar, którego używa ta właściwość. Zsyntetyzowane ivars nie pojawiają się w debuggerze. (Nie zdziwiłbym się, gdy zobaczę tę zmianę wkrótce.)
Caleb
-1

Zastanawiałem się również nad tym pytaniem. Moim skromnym zdaniem tylko użycie właściwości akcesoriów powoduje, że kod jest znacznie bardziej czytelny. Możesz natychmiast zobaczyć, do jakich zmiennych mają być dostępne publicznie. A osobiście wpisywanie @property (...) przed zmienną jest czasochłonne.

Alex Boudreau
źródło
Cześć Alex, myślę, że lepiej odpowiedzieć na najnowsze pytania tutaj na SE. Nie zgadzam się zbytnio z czasochłonnym argumentem. Nie piszę kodu, który oszczędza mi czas na pisaniu, lubię pisać kod, który oszczędza mojemu przyszłemu ja lub komuś innemu czas na jego zrozumienie. To powiedziawszy, głos -1 nie był mój. Byłoby miło, gdyby ta osoba wyjaśniła głosowanie.
epolog