Zawsze byłem przekonany, że właściwości (tj. Ich operacje ustawiania / pobierania) powinny być szybkie / natychmiastowe i bezawaryjne. Nigdy nie powinieneś próbować / łapać się za uzyskanie lub ustawienie nieruchomości.
Ale patrzę na niektóre sposoby zastosowania zabezpieczeń opartych na rolach do właściwości niektórych obiektów. Na przykład właściwość Employee.Salary. Niektóre rozwiązania, na które natknąłem się, które wypróbowały inne (jednym z nich jest tutaj przykład AOP ), polegające na zgłoszeniu wyjątku, jeśli akcesorium nie ma odpowiednich uprawnień - ale jest to sprzeczne z osobistą regułą, którą miałem od dłuższego czasu.
Więc pytam: czy się mylę? Czy coś się zmieniło? Czy przyjęto, że nieruchomości powinny mieć możliwość zgłaszania wyjątków?
źródło
Odpowiedzi:
gdy ustawisz wartość właściwości, rzucanie wyjątku na niepoprawną wartość jest w porządku
uzyskanie wartości właściwości nie powinno (prawie) nigdy wyrzucać wyjątku
dla dostępu opartego na rolach użyj różnych / głupszych interfejsów lub fasad; nie pozwól ludziom zobaczyć rzeczy, których nie mogą mieć!
źródło
Uważam, że jest to w większości zła forma, ale nawet Microsoft zaleca czasem stosowanie wyjątków. Dobrym przykładem jest abstrakcyjna właściwość Stream.Length . Zgodnie z wytycznymi bardziej będę zainteresowany unikaniem skutków ubocznych u osób pobierających i ograniczaniem skutków ubocznych u osób ustawiających.
źródło
Zdecydowanie twierdzę, że projekt ma wadę, jeśli odczuwasz potrzebę rzucenia wyjątków od ustawiacza nieruchomości lub gettera.
Właściwość jest abstrakcją, która reprezentuje coś, co jest tylko wartością . Powinieneś być w stanie ustawić wartość bez obawy, że może to spowodować wyjątek. *
Jeśli ustawienie właściwości powoduje efekt uboczny, należy ją zaimplementować jako metodę. A jeśli nie wywołuje to żadnych skutków ubocznych, nie należy rzucać żadnych wyjątków.
Jednym z przykładów wspomnianych już w innej odpowiedzi jest
Stream.Position
właściwość. To powoduje skutki uboczne i może rzucać wyjątki. Ale to narzędzie do ustawiania właściwości jest po prostu opakowaniemStream.Seek
, które można zamiast tego wywołać.Osobiście uważam, że to stanowisko nie powinno być własnością do zapisu.
Innym przykładem, w którym możesz ulec pokusie rzucenia wyjątku z ustawiacza właściwości, jest sprawdzanie poprawności danych:
Ale istnieje lepsze rozwiązanie tego problemu. Wprowadź typ reprezentujący prawidłowy adres e-mail:
Do
Email
klasy zapewnia, że nie może posiadać wartość, która nie jest prawidłowy adres e-mail i klas, które trzeba przechowywać e-maile są zwolnione z obowiązku ich zatwierdzania.Prowadzi to również do większej spójności (wskaźnik dobrego projektu oprogramowania) - wiedza o tym, czym jest adres e-mail i jak jest weryfikowany, istnieje tylko w
Email
klasie, która ma tylko takie obawy.* ObjectDisposedException to jedyny prawidłowy wyjątek (bez zamierzonej gry słów), o którym mogę teraz myśleć.
źródło
Wiem, że twoje pytanie jest specyficzne dla .NET , ale ponieważ C # udostępnia trochę historii z Javą, pomyślałem, że możesz być zainteresowany. Jestem nie w żaden sposób sugerując, że skoro coś jest zrobione w Javie, należy to zrobić w języku C #. Wiem, że oba są bardzo różne, zwłaszcza w tym, że C # ma znacznie ulepszoną obsługę właściwości na poziomie języka. Podaję tylko kontekst i perspektywę.
Ze specyfikacji JavaBeans :
Proszę, weź to wszystko z odrobiną soli. Specyfikacja JavaBeans jest stara, a właściwości C # są (IMO) ogromną poprawą w stosunku do właściwości opartych na „konwencji nazewnictwa”, które ma Java. Próbuję tylko dać trochę kontekstu, to wszystko!
źródło
Punktem właściwości jest zasada jednolitego dostępu , tzn. Że wartość powinna być dostępna za pośrednictwem tego samego interfejsu, niezależnie od tego, czy jest implementowana przez pamięć, czy obliczenia. Jeśli twoja właściwość zgłasza wyjątek, który reprezentuje warunek błędu, na który programista nie ma wpływu, rodzaj, który powinien zostać przechwycony i obsłużony, zmuszasz swojego klienta do zrozumienia, że wartość jest uzyskiwana przez obliczenia.
Z drugiej strony nie widzę żadnego problemu z używaniem asercji lub wyjątków podobnych do asercji, które mają na celu zasygnalizowanie programatorowi niewłaściwego użycia API, a nie bycia złapanym i obsługiwanym. W takich przypadkach poprawna odpowiedź z perspektywy użytkownika interfejsu API nie obsługuje wyjątku (tym samym domyślnie dba o to, czy wartość jest uzyskiwana poprzez obliczenia, czy przechowywanie). Ma to na celu naprawienie jego / jej kodu, aby obiekt nie kończył się niepoprawnym stanem lub zmusił go do poprawienia kodu, aby asercja nie została uruchomiona.
źródło
AFAIK, niniejsze wskazówki pochodzą przede wszystkim z procesu myślowego, w którym właściwości mogą ostatecznie zostać wykorzystane czasie projektowania . (Np. Właściwość Text w TextBox) Jeśli właściwość rzuca wyjątek, gdy projektant próbuje uzyskać do niej dostęp, VS nie będzie miał dobrego dnia. Podczas próby użycia projektanta pojawi się mnóstwo błędów, a dla projektantów interfejsu użytkownika nie będą renderowane. Dotyczy to również czasu debugowania, chociaż w scenariuszu wyjątku zobaczysz tylko „wyjątek xxx” i nie będzie on blokował VS IIRC.
W przypadku POCO tak naprawdę nie wyrządzi to żadnej szkody, ale wciąż unikam robienia tego sam. Myślę, że ludzie będą chcieli częściej uzyskiwać dostęp do nieruchomości, więc zwykle powinny być tanie. Właściwości nie powinny wykonywać pracy metod, powinny po prostu uzyskać / ustawić pewne informacje i powinny być z tym zrobione jako ogólna zasada.
źródło
Chociaż wiele będzie zależeć od kontekstu generalnie unikałbym umieszczania jakiejkolwiek łamliwej logiki (w tym wyjątków) we właściwościach. Przykładowo, istnieje wiele rzeczy, które możesz zrobić (lub niektóre biblioteki, których używasz), które wykorzystują refleksję do iteracji właściwości, powodując błędy, których nie spodziewałeś się w czasie projektowania.
Mówię ogólnie, ponieważ mogą zdarzyć się chwile, kiedy absolutnie, zdecydowanie chcesz coś zablokować, nie martwiąc się zbytnio o konsekwencje. Bezpieczeństwo to chyba klasyczna sprawa.
źródło