2009-02-07 19 views
19

Rozważmy ten scenariusz: Mam aplikację 3-warstwową, gdy użytkownik kliknie przycisk przycisk obsługi zdarzenia wywołuje metodę w warstwie biz, które robią cokolwiek z danymi mój moduł obsługi zdarzenia przycisku, a następnie przekazać dane do warstwy dostępu do danych, która wysyła je do bazy danych zaplecza. Pytanie, gdzie umieścić próbę złapać? W warstwie danych, w warstwie biz, w warstwie prezentacji, a może położyć ją na wszystkich? Jaka jest najlepsza strategia reprezentowania obsługi wyjątków, jak w tym scenariuszu?Gdzie umieścić próbę złapać

Odpowiedz

5

zdecydowanie umieścić próbę najbliżej użytkownika - ponieważ w tej lokalizacji można przetłumaczyć ją na coś znaczącego dla użytkownika.

Głębsza próba połowów może być potrzebna tylko wtedy, gdy zamierzasz coś z nimi zrobić - na przykład obsłużyć wyjątek, a może zalogować się i ponownie rzucić wyjątek.

39

Śledzimy

Nie złapać wyjątki, jeśli nie wiem, co z nim zrobić.

Nigdy nie zajmujemy się żadnymi wyjątkami, których nie możemy obsłużyć lub domyślnie To jest bąblowane i zajmujemy się nim na poziomie aplikacji.

Powiedz, jeśli możesz ustawić wartość domyślną dla obiektu biznesowego, a następnie możesz obsłużyć go w warstwie biznesowej.

+1

Tak, złap wyjątek, gdy jesteś w stanie sobie z tym poradzić. Jeśli nie wiesz, co z tym zrobić, nie łapaj go. (A czasami "złap go i zignoruj ​​to" może być słuszną rzeczą z tym zrobić, więc zrób to.) – jalf

+0

@Ramesh: Ładna odpowiedź +1 –

0

To zależy od tego, gdzie naprawdę chcesz coś z tym zrobić. Ogólnie łapię go w warstwie biznesowej, a następnie loguję i ewentualnie wywołuję jakąś funkcję ui, aby wyświetlić komunikat dla użytkownika.

Zastanawiam się, co zrobić z błędami reguły biznesowej. Powinien być oddzielony od warstwy danych lub warstwy interfejsu użytkownika.

0

Ogólna odpowiedź brzmi: złap, gdy tylko będziesz w stanie poradzić sobie z tym, co jest rzucane. Oznacza to, że decyzja jest dość prosta. Na przykład przechwytuj wyjątki, które pojawiają się podczas tworzenia potrzebnego obiektu.

+0

Zgadzam się z pierwszą częścią odpowiedzi, ale nie z przykładem, jeśli tworzenie obiektu nie powiedzie się, nie wiesz automatycznie, jak sobie z tym poradzić. –

+0

Tak, oczywiście. Jeśli nie możesz sobie z tym poradzić, pozwól mu się rozmnażać. –

2

Prawdopodobnie najlepiej używać spróbuj złapać we wszystkich warstwach, ale tylko cicho złapać wyjątki w warstwie UI. W warstwach dostępu biz i danych powinieneś prawdopodobnie wychwycić wyjątek i zapisać informacje przed ponownym wyrzuceniem, np.

try 
{ 
    //do something 
} 
catch(Exception ex) 
{ 
    LogFile.WriteLine(ex.ToString()); 
    throw; 
} 

Uwaga: nie pisać:

throw ex; 

jak to będzie usunąć wszystkie użyteczne informacje stos z wyjątkiem.

+0

@mrdresser: Dlaczego powinieneś logować wyjątek w każdej warstwie i nie logować go raz dla wszystkich przypadków, w których obsługujemy wyjątek/jeśli nie jest on nigdy obsługiwany w warstwie interfejsu użytkownika? ślad stosu zawsze dałby całą informację – Ramesh

+0

i jestem z Ramesh na tym. Łapanie tylko ze względu na pozyskiwanie jest kuszące ... ale jest to po prostu dużo pracowitej pracy, której nie potrzebujesz i której można bezpiecznie uniknąć. –

+0

Plus, jeśli logujesz go w każdej warstwie, możesz mieć wiele wpisów dziennika dla tego samego wyjątku. –

0

Zawsze próbuj/złap na najwyższym poziomie lub poziomie contoller.

0

Interfejs użytkownika służy tylko do prezentacji. Nie łapiesz tam wyjątków, ponieważ zastanawianie się, co z tym zrobić, oznacza logikę. To należy do warstw biznesowych lub kontrolerów. W najgorszym przypadku przechwytujesz wyjątek i mapujesz go na odpowiedni, przyjazny dla użytkownika komunikat o błędzie, który jest następnie wysyłany do prezentacji w celu wyświetlenia.

1

Umieść try-catch, w którym masz pewność, że nie połkniesz wyjątku. Wiele bloków try-catch na różnych warstwach może być OK, jeśli możesz zapewnić spójność.

Na przykład można umieścić try-catch w warstwie dostępu do danych, aby zapewnić prawidłowe czyszczenie połączeń.Ale ponieważ nie możesz zrobić o wiele więcej, prawdopodobnie powinieneś powtórzyć wyjątek.

Przechodząc do warstwy biznesowej, możesz umieścić try-catch w wielu operacjach na bazach danych, które chcesz przeprowadzić atomowo. W takim przypadku możesz przywrócić wszystko lub ułożyć stan w spójny sposób, gdzieś zarejestruj wyjątek. Połknięcie lub ponowne rzucanie powinno być rozstrzygane indywidualnie dla każdego przypadku.

Twoja warstwa prezentacji powinna zawsze wychwytywać wszystkie wyjątki, czy to jakąś aplikację internetową, skrypt działający w przeglądarce czy jakaś bogata aplikacja kliencka. Możesz nie być w stanie całkowicie zrozumieć wyjątku, ale przynajmniej możesz upewnić się, że twoja aplikacja nie umiera w obliczu użytkownika.

Oczywiście, to tylko porada. YMMV. :)

+0

Powiedziałbym, że jeśli chodzi o oczyszczanie połączeń w DAL, powinieneś używać bloków Try-Finally (lub bloków), a nie Try-Catch. Nie ma potrzeby określania bloku Catch, jeśli zamierzasz ponownie wyrzucić wyjątek bez jego obsługi. –

+0

O tak. Moje przeprosiny, mam na myśli spróbować w końcu, ale nie zauważyłem. :( –

0

Kiedy mam wielowarstwową architekturę taką jak ta (która jest dużo), będę często próbował/złapać na więcej niż jednej warstwie. Na przykład próba/catch w warstwie trwałości, która przechwytuje wyjątek SQLException, robi to, czego potrzebuje warstwa trwałości (na przykład powiadamia administratora), a następnie generuje nowy wyjątek, który ma sens w przypadku kodu wywołującego warstwę trwałości . Przykładem może być wyjątek PersistenceException. Następna warstwa nie dba o to, kto powinien zostać powiadomiony o ponownym uruchomieniu bazy danych, ale dba o to, by nie mógł zapisać stanu użytkownika, aby mógł uchwycić wyjątek PersistenceException i poinformować użytkownika, że ​​jego nowy numer telefonu nie był ". t przechowywane w bazie danych.

3

Mantra obsługi wyjątków to: "Rzuć wcześniej, złap się późno". Chcesz wychwycić wyjątki w ostatniej możliwej chwili, ale chcesz je natychmiast rzucić (nie wykonuj więcej przetwarzania po stwierdzeniu, że coś jest nie tak, a następnie wyrzuć wyjątek). Jeśli nie możesz "obsłużyć" wyjątku, nie łapaj go.

W większości przypadków, spróbuj ... W końcu bloki powinny być o wiele bardziej powszechne w twoim kodzie niż Spróbuj ... Złap.

-1

Używa się tylko próbnych połowów do zarządzania nieobsługiwanym kodem. Przykładem jest to, że mam obiekt COM, z którym się komunikuję i nie chcę, aby pozostawał otwarty i tworzył wyciek pamięci. Drugą dopuszczalną alternatywą jest złapanie błędów w zdarzeniach w bazie danych przed zezwoleniem na kontynuowanie wyjątku.

Nigdy nie chcesz używać funkcji sprawdzania catch w sytuacjach, w których nie masz pewności, że kod będzie działał i chcesz utworzyć plan tworzenia kopii zapasowych.

Więc gdzie to was opuści, gdy wysadzą się aplikacje, użyj niestandardowych stron z błędami, aby wskazać, że w aplikacjach internetowych wystąpił problem, a grube klienty przetwarzają kod na wątki robocze, aby nie wysadzić głównego wątku, nie udaje im się. Powodzenia!

Powiązane problemy