Илья Фофанов "Обработка ошибок в c#"

51
1 IOA Error Panel PLEASE PRESS ENTER TO RESUME Обработка ошибок в C# MSK.NET представляет ERROR

Upload: yulia-tsisyk

Post on 11-Feb-2017

210 views

Category:

Technology


2 download

TRANSCRIPT

Page 1: Илья Фофанов "Обработка ошибок в C#"

1

IOA Error Panel

PLEASE PRESS ENTER TO RESUME

Обработка ошибок в C#

MSK.NET представляет

ERROR

Page 2: Илья Фофанов "Обработка ошибок в C#"

2

Илья Фофанов

http://engineerspock.com

Page 3: Илья Фофанов "Обработка ошибок в C#"

3

Зачем надо уметь обрабатывать ошибки?

• Бич современности: падающие приложения, которые ничего не сообщают о возникшей проблеме

• Обработка ошибок – критически важная часть программ с высокими требованиями к устойчивости

Page 4: Илья Фофанов "Обработка ошибок в C#"

4

Проверяемые Непроверяемые

Page 5: Илья Фофанов "Обработка ошибок в C#"

Большие проблемы… с исключениями

5

Page 6: Илья Фофанов "Обработка ошибок в C#"

6

Виды ошибок

Page 7: Илья Фофанов "Обработка ошибок в C#"

7

Как бороться с исключениями

Page 8: Илья Фофанов "Обработка ошибок в C#"

8

public HttpResponseMessage CreateCustomer(string name, string billingInfo) {

Result<BillingInfo> billingInfoResult = null; try { billingInfoResult = BillingInfo.Create(billingInfo); } catch (Exception ex) { Log(ex); return CreateResponseMessage(ex); }  Result<CustomerName> customerNameResult = null; try { customerNameResult = CustomerName.Create(name); } catch (Exception ex) { Log(ex); return CreateResponseMessage(ex); }  try { _paymentGateway.ChargeCommission(billingInfoResult.Value); } catch (Exception ex) { Log(ex); return CreateResponseMessage(ex); }

var customer = new Customer(customerNameResult.Value); try { _repository.Save(customer); } catch (Exception ex) { Log(ex); _paymentGateway.RollbackLastTransaction(); } try { _emailSender.SendGreetings(customerNameResult.Value); } catch (Exception ex) { Log(ex); return CreateResponseMessage(ex); } return CreateResponseMessage(true);}

«Try-Catch» Hell

Page 9: Илья Фофанов "Обработка ошибок в C#"

9

 public HttpResponseMessage CreateCustomer(string name, string billingInfo){ Result<BillingInfo> billingInfoResult = BillingInfo.Create(billingInfo); Result<CustomerName> customerNameResult = CustomerName.Create(name);  return Result.Combine(billingInfoResult, customerNameResult) .OnSuccess(() => _paymentGateway.ChargeCommission(billingInfoResult.Value)) .OnSuccess(() => new Customer(customerNameResult.Value)) .OnSuccess(customer => _repository.Save(customer) .OnFailure(() => _paymentGateway.RollbackLastTransaction())) .OnSuccess(() => _emailSender.SendGreetings(customerNameResult.Value)) .OnBoth(Log) .OnBoth(CreateResponseMessage);}

«No Try-Catch» Paradise

Page 10: Илья Фофанов "Обработка ошибок в C#"

10

Семь бед - один ответ: исключения!

Page 11: Илья Фофанов "Обработка ошибок в C#"

11

Use exceptions. They are much cleaner then all the other options. The fear about uncaught exceptions is misplaced. Forgetting to catch an exception is much better than forgetting the if statement to check a result. The former fails visibly, and the latter fails silently. The fear of messy code near the try/catch blocks is also misplaced. Use the 'extract till you drop' rule, and make sure that any function with a try/catch block has _only_ the try/catch block in it; with the try block being a single function call.Finally, write tests for all your exception throws, and all your exception catches. Error processing is part of the legitimate behavior of your system and testing it is very important.

Robert Martin aka “Uncle Bob”

https://groups.google.com/forum/#!topic/clean-code-discussion/CQSA4czDvHc

Page 12: Илья Фофанов "Обработка ошибок в C#"

12

Проблемы исключений

Page 13: Илья Фофанов "Обработка ошибок в C#"

13

Пример проверяемого исключения

     public static void readFile(string filePath) throws IOException {        FileReader file = new FileReader(filePath);        BufferedReader fileInput = new BufferedReader(file);                 // Print first 3 lines of the file         for (int counter = 0; counter < 3; counter++)             System.out.println(fileInput.readLine());                 fileInput.close();    }

Page 14: Илья Фофанов "Обработка ошибок в C#"

14

Проблема масштабирования

Page 15: Илья Фофанов "Обработка ошибок в C#"

15

Проблема версионирования

Нельзя просто так взять

и добавить новый тип исключения

Page 16: Илья Фофанов "Обработка ошибок в C#"

16

Какое решение?

Выпилить проверяемые исключения!

Page 17: Илья Фофанов "Обработка ошибок в C#"

17

Трудно понять программу

Page 18: Илья Фофанов "Обработка ошибок в C#"

18

Their power comes at an extremely high cost; it becomes impossible to understand the flow of the program using only local analysis; the whole program must be understood. This is especially true when you mix exceptions with more exotic control flows like event-driven or asynchronous programming. Avoid, avoid, avoid; use exceptions only in the most exceptional circumstances, where the benefits outweigh the costs.

Eric Lippert

Page 19: Илья Фофанов "Обработка ошибок в C#"

19

“…people don't care. They're not going to handle any of these exceptions. There's a bottom level exception handler around their message loop. That handler is just going to bring up a dialog that says what went wrong and continue.”

“It is funny how people think that the important thing about exceptions is handling them. That is not the important thing about exceptions. In a well-written application there's a ratio of ten to one, in my opinion, of try finally to try catch.”

Anders Hejlsberg

Page 20: Илья Фофанов "Обработка ошибок в C#"

20

Как обезопасить себя при чтении файла?

try { File.ReadAllLines();}catch (?) { }

Page 21: Илья Фофанов "Обработка ошибок в C#"

21

Исключения из File.ReadAllLines()• ArgumentException• ArgumentNullException• PathTooLongException• NotSupportedException

• IOException• DirectoryNotFoundException• FileNotFoundException

• UnathorizedAccessException• SecurityException

Page 22: Илья Фофанов "Обработка ошибок в C#"

22

Знаем ли мы какие исключения перехватывать?

Page 23: Илья Фофанов "Обработка ошибок в C#"

23

Corrupted State Exceptions

Page 24: Илья Фофанов "Обработка ошибок в C#"

24

SEHException

Если CLR не знает, что делать с исключением из unmanaged кода, то CLR заворачивает его в тип SEHException.

Page 25: Илья Фофанов "Обработка ошибок в C#"

25

Corrupted State ExceptionCorrupted State Exception (CSE) – исключение связанное с поврежденным состоянием.

Примеры CSE в C#:• SEHException• AccessViolationException

CSE в unmanaged:• EXCEPTION_ILLEGAL_INSTRUCTION EXCEPTION_IN_PAGE_ERROR• EXCEPTION_INVALID_DISPOSITION

EXCEPTION_NONCONTINUABLE_EXCEPTION• EXCEPTION_ACCESS_VIOLATION EXCEPTION_STACK_OVERFLOW• EXCEPTION_PRIV_INSTRUCTION STATUS_UNWIND_CONSOLIDATE

Page 26: Илья Фофанов "Обработка ошибок в C#"

26

CSE. Надо ли ловить?

• В общем случае ловить CSE не надо. Компенсационную логику написать практически невозможно.

• Можно ловить только в случаях, когда вы точно знаете с какой проблемой столкнулись и уверены, что можно «подавить и продолжить»

Page 27: Илья Фофанов "Обработка ошибок в C#"

27

CSE. Как поймать?[HandleProcessCorruptedStateExceptions]public static void HandleCorruptedState(){ // handling}

<configuration> <runtime> <legacyCorruptedStateExceptionsPolicy enabled="true"/> </runtime></configuration>

1.

2.

Page 28: Илья Фофанов "Обработка ошибок в C#"

28

Обработка исключений

Page 29: Илья Фофанов "Обработка ошибок в C#"

29

Обработка только известных исключений

try { File.ReadAllLines();}catch (IOException ex) { } //а точно ничего не забыли?

Page 30: Илья Фофанов "Обработка ошибок в C#"

30

Политики фильтраций

try { File.ReadAllLines();}catch (Exception ex) { //делегируем обработку ExceptionManager .HandleException(ex, “Policy”);}

Page 31: Илья Фофанов "Обработка ошибок в C#"

31

Catch Them All!

try { File.ReadAllLines();}//вообще всё пофигу!catch (Exception ex) { }

Page 32: Илья Фофанов "Обработка ошибок в C#"

32

Подавление исключений

1. Приложение какого типа вы разрабатываете? 2. Полной корректности достичь очень трудно.3. Каков размер приложения?

Page 33: Илья Фофанов "Обработка ошибок в C#"

33

… most people don’t write robust error handling code in non-systems programs, throwing an exception usually gets you out of a pickle fast. Catching and then proceeding often works too. No harm, no foul. Statistically speaking, programs “work.”Joe Duffy

Page 34: Илья Фофанов "Обработка ошибок в C#"

34

Категории ошибок

Пользовательские восстанавливаемые

Системные восстанавливаемые

Пользовательские невосстанавливаемые

Системные невосстанавливаемые

Пользовательские Системные

Восс

тана

влив

аем

ые

Нево

сста

навл

ивае

мы

е

Page 35: Илья Фофанов "Обработка ошибок в C#"

35

Восстанавливаемые пользовательские ошибки

public void TransferMoney(Payment p) { if (p == null) throw new ArgumentNullException("p"); ValidatePayment(p);}

Page 36: Илья Фофанов "Обработка ошибок в C#"

36

Исключения и сигнатура метода

Эту семантическую часть надо вывести в сигнатуру метода!

• Исключения – побочные эффекты

• Исключения, выражающие нарушения пользовательской бизнес-логики скрывают важную семантическую часть

Page 37: Илья Фофанов "Обработка ошибок в C#"

37

Боремся с исключениями

Page 38: Илья Фофанов "Обработка ошибок в C#"

38

Способы борьбы с исключениями

• Шаблон Tester-Doer• Шаблон TryParse• Railway Oriented Programming

Page 39: Илья Фофанов "Обработка ошибок в C#"

39

Tester-Doer

ICollection<Student> students = GetStudents();if (!students.IsReadOnly)//tester{ students.Add(new Student("Joe")); //doer}

Page 40: Илья Фофанов "Обработка ошибок в C#"

40

TryParse

DateTime birthday;bool parsed = DateTime.TryParse("12/08/1988", out birthday);if (parsed) { SocialNumber socialNumber; parsed = SocialNumber.TryParse("1239584594", out socialNumber); if (parsed) { } else { }}else {}

Page 41: Илья Фофанов "Обработка ошибок в C#"

41

Недостатки Tester-Doer и TryParse

• Tester-Doer – форма антипаттерна «temporal coupling»• Tester-Doer не работает в условиях конкурентного доступа• TryParse неуклюж из-за out-параметра и возврата boolean

Page 42: Илья Фофанов "Обработка ошибок в C#"

42

Pipelining

[| 83uy; 80uy; 79uy; 67uy; 75uy |]|> Encoding.ASCII.GetString(textInBytes)|> Console.WriteLine(contents)

var sb = new StringBuilder();sb.Append("Hello") .Append(",") .Append("World") .AppendLine("!");

Pipelining in F# Method chaining in C#

Page 43: Илья Фофанов "Обработка ошибок в C#"

43

Коды ошибок

Page 44: Илья Фофанов "Обработка ошибок в C#"

44

Демо

Page 45: Илья Фофанов "Обработка ошибок в C#"

4 вида методовCommands:

Queries:

void EnrollStudent(Student student);//not expected to fail

Result EnrollStudent(Student student);//expected to fail

Student GetStudent(string name);//not expected to fail

Result<Student> GetStudent(string name); //expected to fail

45

Page 46: Илья Фофанов "Обработка ошибок в C#"

46

Итоги

Page 47: Илья Фофанов "Обработка ошибок в C#"

47

Что делать?

Отслеживайте control flow. Если вызов уходит в unmanaged будьте готовы к неприятностям.

Есть три основных подхода к обработке исключений. Выбирайте тот, который оптимальным образом удовлетворяет требования по устойчивости конкретного приложения.

Page 48: Илья Фофанов "Обработка ошибок в C#"

48

Категории ошибок – что делать?

Result Monad Catch\Handle or Suppress

Fail Fast or Suppress Fail Fast Only

Пользовательские Системные

Восс

тана

влив

аем

ые

Нево

сста

навл

ивае

мы

е

Page 49: Илья Фофанов "Обработка ошибок в C#"

Ссылкиhttp://pluralsight.com/courses/csharp-applying-functional-principles «Applying Functional Principles in C#» - видео курс

https://github.com/vkhorikov/CSharpFunctionalExtensionsКласс Result и полезные расширения – исходники

https://www.nuget.org/packages/CSharpFunctionalExtensions/Класс Result и полезные расширения – NuGet package

Владимир Хориков

https://www.visualstudio.com/en-us/products/visual-studio-dev-essentials-vs.aspx49

Page 50: Илья Фофанов "Обработка ошибок в C#"

Ссылкиhttps://ericlippert.com/2014/03/03/living-with-unchecked-exceptions/Статья Эрика Липперта в двух частях про исключения

https://vimeo.com/97344498Scott Wlaschin - Railway Oriented Programming — error handling in functional languages

http://www.artima.com/intv/handcuffs.htmlАндерс Хейлсберг об исключениях

http://joeduffyblog.com/2016/02/07/the-error-model/Очень крутая статья Joe Duffy об обработке ошибок

50

https://www.nuget.org/packages/EnterpriseLibrary.ExceptionHandling/Enterprise Exception Handling Block

http://sergeyteplyakov.blogspot.ru/2016/06/semantic-of-exception.htmlСтатья Теплякова об исключениях

https://github.com/App-vNext/PollyPolly

Page 51: Илья Фофанов "Обработка ошибок в C#"

Илья Фофанов

http://engineerspock.comhttps://www.udemy.com/user/eliasfofanov/https://habrahabr.ru/users/engineerspock/

51

Спасибо за внимание!