MaximGB писал(а):
Здравствуйте. Я читаю форум уже продолжительное время, однако до этого момента сказать было нечего, а читать - интересно ;), так что это моё первое сообщение здесь.
Добро пожаловать : )
MaximGB писал(а):
Я считаю исключения скорее полезными чем нет. Если разрабатываемый вами протокол зависит от другого протокола, например, получает объект, реализующий протокол, в качестве параметра метода, то вы не можете быть уверены в его безошибочной реализации. Или, наоборот, если ваш компонент, реализующий какой-либо протокол, используется с нарушениями контракта - вызывается метод с фактическими параметрами, которые ваш компонент не может обработать, то разумно выбросить исключение из реализации вызываемого метода.
Согласитесь, Максим, что механизм исключений не является необходимым для реализации подобных отношений между объектами. Достаточно в самом базовом объекте предусмотреть поле error c числовым значением ошибки. Теперь далее:
MaximGB писал(а):
при возникновении исключения которое не может быть корректно обработано - при раскрутке стека - низкоуровневое исключение всегда оборачивается в исключение более высокого уровня так чтобы можно было получить доступ ко всей цепочке. В последнем пункте под высокоуровневым я имею в виду исключение выбрасываемое в методе выше по стеку.
В целом ваш подход мне представляется
очень правильным, и я благодарен вам за то, что вы его описали, иначе нечто подобное пришлось бы писать мне. Однако, обратите внимание: при таком правильном, структурном подходе к проектированию и реализации системы исключительных ситуаций получается, что исключение в любом случае
обрабатывается, даже если оно будет проигнорировано. В том смысле, что для всякого исключения есть программный код, который его поймает и обернёт исключением другого типа. Насколько я понимаю, главный аргумент за использование исключений состоит в том, что если нет сильного желания, то можно не возиться с кодами ошибок - мол, оно само допрыгнет до обработчика. В вашем же варианте возня с кодами (if obj.error <> OK...) заменена на аналогичную возню с прыгающими блохами (except on E:Exception do raise MyException.Create(E)...). Фактически вы вручную минимизировали дистанцию прыжка - по границам объектов. Есть ли тогда смысл?
Если есть желаение получить именно
цепочку ошибок, то достаточно иметь простую библиотечку, где это всё можно регистрировать при обработке if obj.error <> OK. Примитивный вариант такой библиотеки - текстовый журнал событий (либо лог-файл), но можно сделать и объектно-ориентированную реализацию для упрощения анализа и обработки ошибок изнутри самой программы - и "получить доступ ко всей цепочке". Нужен ли такой механизм в языке программирования (не как библиотека, а как часть языка, зашитая в компилятор)? У меня очень большие сомнения на этот счёт.
Итак, можно подвести промежуточный итог. Исключения - это:
1. goto через стек вызовов процедур;
2. средство обработки ошибок;
3. средство отделения полезного кода от кода обработки особых случаев (последний переносится в блоки except либо finally, по сути не отличающиеся от IF/ELSIF/ELSE);
4. средство оптимизации за счёт исключения лишних проверок из полезного кода.
На мой взгляд, (2) и (3) достижимо библиотечными средствами и соглашениями наподобие вашей системы правил пользования исключениями, а (1) и (4) скорее способствует разгильдяйству при программировании, чем помогает решать реальные проблемы. Где-то здесь пролегает тонкая грань между признанием того, что "программисты ошибаются", и признанием собственного бессилия. Я ожидаю исключение при вызове метода чужого объекта в том случае, если я исхожу из того, что автор объекта - дурак, править его код невозможно, добиваться, чтобы он сам его исправил, тоже бессмысленно, а написать свой такой же объект я не могу. Остаётся только поймать исключение и сказать: "Это он дурак, а не я!" Как вы понимаете, на уровне языка программирования это не решается, это проблема из другой плоскости. Так же, как многозадачность в современных ОС: одна программа может сломаться, но другие не должны пострадать. Ввод в язык механизма исключений ничего не решает, а только лишь добавляет новые организационные проблемы.
Вот что действительно важно - это понимать и уметь организовывать обработку ошибок. Этот механизм тоже нужно проектировать, как канализацию в многоквартирном доме. Просто мало кто считает это самостоятельной проблемой. Не в том смысле, что "мараться не хочется", а в том смысле, что наибольший интерес вызывает основная задача -планировка и интерьер. А ведь при обработке ошибок наверняка тоже есть свои паттерны проектирования. Есть коды ошибок, возвращаемые процедурой или устанавливаемые в глобальной переменной модуля, есть журналы и лог-файлы, есть объекты с текстом (Exception) и т.п. Есть механизмы заменяемые, когда с ростом проекта один механизм можно заменить на другой, а есть статичные, которые трудно поддаются корректировке. Хотелось бы как-то эту тему копнуть поглубже.