Właściwości powinny mieć skutki uboczne


19

Należy właściwości w C # mają skutki uboczne obok powiadamiania o zmianach w jego stanach?

Widziałem właściwości używane na kilka różnych sposobów. Od właściwości, które będzie załadować wartość po raz pierwszy oni są dostępne do właściwości, które mają ogromne skutki uboczne, takie jak powodując przekierowanie na inną stronę.



1
Wśród ustaleń @ Job, dlaczego powinienem unikać używania właściwości w języku C #? alias Opinia Jeffreya Richtera jest bardzo istotna dla tego pytania.
rwong

@rwong Istotne tak, ale całkowicie non sens --nonetheless należy czytać (tak, aby zdawać sobie sprawę z problemów Podkreśla). Przynajmniej w tej sprawie jestem w obozie Skeet.
Apoorv Khurasia

Choć dotyczy to konstruktorów, jest to również istotne: programmers.stackexchange.com/a/164255/1996
Jim G.

Odpowiedzi:


40

Zakładam, że mówisz tylko do odczytu właściwości, albo przynajmniej własności pobierające , ponieważ nieruchomość seter jest w prawie każdym przypadku, będzie mieć skutki uboczne. W przeciwnym razie nie jest to bardzo przydatne.

Ogólnie dobry projekt jest zgodny z zasadą najmniejszego zaskoczenia . Nie rób rzeczy, które dzwoniący nie oczekujemy, aby to zrobić, zwłaszcza jeśli te rzeczy mogą zmienić przyszłe wyniki.

Ogólnie oznacza to, że osoby pobierające nieruchomości nie powinny mieć skutków ubocznych.

Uważajmy jednak na to, co rozumiemy przez „efekt uboczny”.

Efektem ubocznym jest technicznie wszelkie zmiany stanu. To może być stan publicznie dostępny lub ... może być całkowicie prywatny.

Leniwe / odroczone programy ładujące są jednym z przykładów stanu, który jest prawie wyłącznie prywatny. Dopóki to nie jest odpowiedzialność osoby dzwoniącej, aby zwolnić ten zasób, to faktycznie zmniejszenie niespodziankę i złożoność w ogóle za pomocą odroczony inicjalizacji. Osoba dzwoniąca zwykle nie musi wyraźnie sygnalizować inicjalizacji struktury wewnętrznej . Leniwa inicjalizacja nie narusza powyższej zasady.

Innym przykładem jest zsynchronizowany nieruchomość. Aby metoda była bezpieczna dla wątków, często musi być chroniona przez sekcję krytyczną lub mutex. Wprowadzanie sekcji krytycznej lub uzyskiwania muteksu to działanie uboczne; jesteś modyfikowanie stanu, zwykle globalny stan. Jednak ten efekt uboczny jest niezbędny , aby zapobiec znacznie gorszemu zaskoczeniu - zaskoczeniu modyfikacją danych (lub, co gorsza, częściowo zmodyfikowaniem) innym wątkiem.

Chciałbym więc nieco poluzować to ograniczenie: Odczyty właściwości nie powinny mieć widocznych efektów ubocznych ani efektów ubocznych, które zmieniają ich semantykę .

Jeśli nie ma sposobu na rozmówcy, aby kiedykolwiek zostać dotknięte skutkami lub nawet świadomi działań ubocznych, to efekt uboczny nie robi żadnej szkody. Jeśli byłoby to niemożliwe, aby napisać test, aby zweryfikować istnienie konkretnego skutku ubocznego, to jest zlokalizowane na tyle, aby etykiety jako prywatny szczegółów realizacji, a tym samym bez uzasadnionej troski ze światem zewnętrznym.

Ale należy uważać; jako zasada, to powinien spróbować uniknąć skutków ubocznych, ponieważ często to, co można pomyśleć, aby być prywatnym detal realizacja może niespodziewanie przeciekać i stają się publiczne.


2
+1 - miły pełna odpowiedź tym bardziej skomplikowanych przypadkach, które z kolei jest „musi” w „powinna ... z wyjątkiem kiedy ....”
quickly_now

Innym przykładem akceptowalnego działania ubocznego na pobierająca: funkcja rejestrowania A.
Loren Pechtel

5

Odpowiem na pytanie z pytaniem: Co się dzieje, gdy zmodyfikować właściwość szerokości formie?

Zaraz po mojej głowie to:

  • Zmień wartość pola podkładu.
  • Wystrzel wydarzenie.
  • Zmienić wymiary formularza, zgłosić zmianę do menedżera okien i zażądać repaint.
  • Informuj formantów na formularzu zmiany tak, że każdy z nich, że potrzeba zmiany rozmiaru lub położenia, gdy formularz jest zmieniany może zrobić.
  • Przyczyna wszelkie kontrole, które zmieniły zdarzeń pożarowych i powiedzieć menedżera okien, które muszą być odświeżana.
  • Prawdopodobnie inne rzeczy, jak również.

(Zastrzeżenie: Jestem programistą Delphi, a nie deweloper .NET To nie może być w 100% dokładne dla C #, ale założę się, że to całkiem blisko, szczególnie biorąc pod uwagę, jak wiele z pierwotnego NET oparto na Delphi.).

Wszystkie te „skutki uboczne” stało po zmianie właściwość Width na formularzu. Czy któryś z nich wydają się nieodpowiednie lub niewłaściwe jakoś?


tak długo, jak nie idzie do nieskończonej pętli nazywająca siebie. Aby tego uniknąć, każdy „zmiana” zostaną odwzorowane na co najmniej trzy wydarzenia: jedno zwolniony przed zmianą, jeden zwolniony w trakcie zmiany, a jeden zwolniony po jej zakończeniu.
rwong

5

Spójrz na Zasad Microsoft projektowych , zwłaszcza jeden z nich:

CA1024: W razie potrzeby użyj właściwości

... metoda A jest dobrym kandydatem, aby stać się nieruchomość, jeśli jeden z tych warunków:

  • Przyjmuje żadnych argumentów i zwraca informacje o stanie obiektu.
  • Przyjmuje jeden argument, aby ustawić jakąś część stanu obiektu.

Właściwości powinny zachowywać się tak, jakby to pola; Jeśli metoda nie może, to nie powinien być zmieniany do nieruchomości. Metody są lepsze niż właściwości w następujących sytuacjach:

  • Sposób wykonuje czasochłonne. Metoda jest zauważalnie wolniejsza niż czas wymagany do ustawienia lub uzyskania wartości pola.
  • Sposób wykonuje konwersję. Dostęp do pola nie zwraca przekonwertowany wersji danych, że przechowuje.
  • Metoda GET ma zauważalnego efektu ubocznego. Pobieranie wartość pola nie wywołuje żadnych skutków ubocznych.
  • Kolejność wykonywania jest ważne. Ustawienie wartości pola nie opiera się na występowaniu innych operacji.
  • Wywołanie metody dwa razy z rzędu tworzy różne wyniki.
  • Metoda jest statyczna, ale zwraca obiekt, który może być zmieniany przez rozmówcę. Pobieranie wartość pola nie pozwala rozmówcy do zmiany danych, które są przechowywane przez pole.
  • Metoda zwraca tablicę ...

2

Wierzę właściwości nie powinny mieć skutki uboczne. Jest jednak jeden wyjątek od tej reguły: leniwy załadunku. Jeśli chcesz leniwie załadować coś do nieruchomości, to w porządku, ponieważ klient nie może powiedzieć, że leniwe ładowanie się dzieje, i ogólnie to nie obchodzi.

EDYCJA : Och, jeszcze jedno - wystrzelenie wydarzenia z napisem „PropertyXYZ zmienione!” (np. INotifyPropertyChanged) - jest w porządku dla seterów.


2

Oprócz wspomnianego wcześniej leniwego ładowania występuje również funkcja rejestrowania. Byłyby to rzadkie, ale nie wykluczone.


2

W programowaniu prawie nie ma absolutów, aby odpowiedzieć na twoje pytanie, musimy przyjrzeć się pewnym pożądanym właściwościom obiektów i sprawdzić, czy ma to zastosowanie w naszym przypadku

  1. Chcemy, aby klasy były łatwe do przetestowania.
  2. Chcemy klas do wsparcia współbieżności
  3. Chcemy, aby zajęcia były łatwe do uzasadnienia dla osób trzecich

Jeśli odpowiemy tak yo niektóre z tych pytań, to chyba dobry pomysł, aby myśleć o właściwościach bardzo starannie i ich skutków ubocznych. Zakładam, że kiedy mówisz skutki uboczne znaczy wtórnych skutków ubocznych, ponieważ aktualizacja wartości jest skutkiem ubocznym w sobie.

Im więcej skutków ubocznych w ogóle trudniejszej klasy będzie testem. Bardziej wtórne skutki uboczne, tym trudniej będzie współbieżności uchwyt, ale to trudne zagadnienie, które prawdopodobnie wymaga jakiś poważny projekt myśl tak.

Dużą haczyka jest chyba dla ludzi, którzy traktują swoją klasę jako „czarna skrzynka”, nie byłoby łatwo dostępne, że niektóre państwa nie zmieniło tylko dlatego, że czytałem, że niektóre własności lub innych zmian w obiekcie, ponieważ inny zmian (co może prowadzić do aktualizacji kaskadowych).

Więc w ogólne Nie chcemy Właściwości być tak łatwo powodu oi proste, jak to możliwe, że jest trochę domniemanych w decyzji projektowej inaczej byłoby to metoda. Dobry programista może łamać zasady zawsze jednak po prostu mieć pewność, że masz naprawdę bardzo dobry powód :)

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.