![]() |
Здравствуйте, гость ( Вход | Регистрация )
![]() |
Litkevich Yuriy |
![]()
Сообщение
#1
|
![]() разработчик РЭА ![]() ![]() ![]() ![]() ![]() ![]() ![]() Группа: Сомодератор Сообщений: 9669 Регистрация: 9.1.2008 Из: Тюмень Пользователь №: 64 Спасибо сказали: 807 раз(а) Репутация: ![]() ![]() ![]() |
Тут наткнулся на статью Link
Читаю, вроде пока с автором согласен. ![]() |
|
|
![]() |
Kagami |
![]()
Сообщение
#2
|
Старейший участник ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 601 Регистрация: 2.2.2009 Пользователь №: 523 Спасибо сказали: 101 раз(а) Репутация: ![]() ![]() ![]() |
Я помню эту статью еще с хабра. С частью тезисов не согласен
![]() Сообщение отредактировал Kagami - 28.3.2010, 15:43 |
|
|
Litkevich Yuriy |
![]()
Сообщение
#3
|
![]() разработчик РЭА ![]() ![]() ![]() ![]() ![]() ![]() ![]() Группа: Сомодератор Сообщений: 9669 Регистрация: 9.1.2008 Из: Тюмень Пользователь №: 64 Спасибо сказали: 807 раз(а) Репутация: ![]() ![]() ![]() |
Цитата(Kagami @ 28.3.2010, 19:34) Link Плюс отказ от рекурсии. это я тоже не понял, но пока до объяснений не дочитал.А насчёт параллельных масивов с ним согласен. И насчёт переменных объявляемых в паскалевском стиле полностью согласен (хотя сам до не давнего времени так и делал) |
|
|
kwisp |
![]()
Сообщение
#4
|
![]() астарожна ынтжинэр ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 1404 Регистрация: 26.11.2008 Из: ТаганрогРодинаЧехова Пользователь №: 435 Спасибо сказали: 113 раз(а) Репутация: ![]() ![]() ![]() |
Цитата(Kagami @ 28.3.2010, 16:34) Link В основном претензии к призыву отказаться от сеттеров/геттеров. я вот сейчас прочёл тоже согласен с тобой. а как автор советует поступать если при изменении свойства нужно выполнить какие нибудь действия, это получается и поведение и изменение свойства? получается никак. либо его притензии к сеттерам и геттерам проявляются только в чистом виде, когда ничего делать по изменению свойства не нужно. я поддерживаю концепцию того чтобы в открытой секции класса хранились только константные данные. Изменяемые данне должны быть надёжно защищены. + пропадает возможность сделать сеттеры и геттеры виртуальными при наследовании. |
|
|
Litkevich Yuriy |
![]()
Сообщение
#5
|
![]() разработчик РЭА ![]() ![]() ![]() ![]() ![]() ![]() ![]() Группа: Сомодератор Сообщений: 9669 Регистрация: 9.1.2008 Из: Тюмень Пользователь №: 64 Спасибо сказали: 807 раз(а) Репутация: ![]() ![]() ![]() |
Цитата(kwisp @ 28.3.2010, 20:15) Link я вот сейчас прочёл тоже согласен с тобой. тут есть нюанс. В целом я согласен с автором, те кому приходилось писать на Делфи, перейдя на любой другой инструмент (Билдер не всчёт так как пытается пародировать Делфи) могли испытать чувство не Объектно-Ориентированности.Дело в том, что в Делфи, есть понятие свойств, поддерживаемых компилятором. В Qt, например, тоже есть. И когда в Делфи вы пишите: value = object.sameProperty; то вы получаете значение свойства объекта, но не напрямую, а через "геттер", а когда вы пишете object.sameProperty = value; то вы устанавливаете значение свойства объекта, но не напрямую, а через "сеттер". Т.е. у вас есть возможность определить и "геттер" и "сеттер". Но форма записи в коде очень интуитивна, и на мой взгляд, по настоящему Объектно-Ориентирована. Нюанс в том, что автор абстрагируется в размышлении от конкретного языка программирования. Но редко указывает на каком языке дан пример. Цитата Свойство — это интерфейс для красивого и безопасного доступа к данным объекта
|
|
|
Iron Bug |
![]()
Сообщение
#6
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Модератор Сообщений: 1611 Регистрация: 6.2.2009 Из: Yekaterinburg Пользователь №: 533 Спасибо сказали: 219 раз(а) Репутация: ![]() ![]() ![]() |
автор статьи работает в веб и сильно зациклен на жабаскрипте. отсюда и его странные представляния о коде
![]() но в большинстве языков того, что автор описывает, просто не существует. так что советы неактуальны. что касается "общих" вопросов, применимых ко всем языкам, то моё мнение такое: про возвращаемое значение: имхо - функция ВСЕГДА должна возвращать int с кодом ошибки и точка. результаты - в параметрах. про геттеры и сеттеры - для крупных проектов со сложными объектами это единственный нормальный и безопасный способ обращения к данным. при этом обеспечивается полная инкапсуляция и наследование. |
|
|
Litkevich Yuriy |
![]()
Сообщение
#7
|
![]() разработчик РЭА ![]() ![]() ![]() ![]() ![]() ![]() ![]() Группа: Сомодератор Сообщений: 9669 Регистрация: 9.1.2008 Из: Тюмень Пользователь №: 64 Спасибо сказали: 807 раз(а) Репутация: ![]() ![]() ![]() |
Цитата(Iron Bug @ 29.3.2010, 0:08) Link про возвращаемое значение: а я вот категорически с этим не согласен. имхо - функция ВСЕГДА должна возвращать int с кодом ошибки и точка. результаты - в параметрах. Сам термин "функция" обязывает к математическому поведению. Как и приведено у автора статьи Цитата(Iron Bug @ 29.3.2010, 0:08) Link про геттеры и сеттеры - для крупных проектов со сложными объектами это единственный нормальный и безопасный способ обращения к данным. ну это опять же жёстко завязано на Си++. А в языках где есть свойства, в них нет нужды
|
|
|
AD |
![]()
Сообщение
#8
|
Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 2003 Регистрация: 4.2.2008 Из: S-Petersburg Пользователь №: 84 Спасибо сказали: 70 раз(а) Репутация: ![]() ![]() ![]() |
Я не согласен с функциями внутри функций. Если нужен какой-то логический блок, то лучше пользоваться пространствами имен.
|
|
|
Litkevich Yuriy |
![]()
Сообщение
#9
|
![]() разработчик РЭА ![]() ![]() ![]() ![]() ![]() ![]() ![]() Группа: Сомодератор Сообщений: 9669 Регистрация: 9.1.2008 Из: Тюмень Пользователь №: 64 Спасибо сказали: 807 раз(а) Репутация: ![]() ![]() ![]() |
Цитата(AD @ 29.3.2010, 2:52) Link то лучше пользоваться пространствами имен а пространства имён разве можно определить внутри функции?Прочитал про рекурсию, ну положим итерационным методом лучше, но кода для сравнения обоих методов я не увидел - это минус товарищу. |
|
|
AD |
![]()
Сообщение
#10
|
Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 2003 Регистрация: 4.2.2008 Из: S-Petersburg Пользователь №: 84 Спасибо сказали: 70 раз(а) Репутация: ![]() ![]() ![]() |
Цитата(Litkevich Yuriy @ 29.3.2010, 0:38) Link а пространства имён разве можно определить внутри функции? Читай внимательно, я сказал следующее, что вместо функций в функциях лучше использовать пространства имен, внутри которых и определять нужные функции. |
|
|
Iron Bug |
![]()
Сообщение
#11
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Модератор Сообщений: 1611 Регистрация: 6.2.2009 Из: Yekaterinburg Пользователь №: 533 Спасибо сказали: 219 раз(а) Репутация: ![]() ![]() ![]() |
Цитата(Litkevich Yuriy @ 28.3.2010, 23:59) Link Цитата(Iron Bug @ 29.3.2010, 0:08) Link про возвращаемое значение: а я вот категорически с этим не согласен. имхо - функция ВСЕГДА должна возвращать int с кодом ошибки и точка. результаты - в параметрах. Сам термин "функция" обязывает к математическому поведению. Как и приведено у автора статьи все проекты, которые я видела, имели именно такие функции, возвращающие int. и я думаю, что это весьма оправданно. просто когда переходишь к реальному программированию, выясняется, что иногда вообще нет смысла возвращать значение, потому что его нет как такового, а вот зато код результата выполнения нужен абсолютно во всех случаях для проверки. я не разделяю вызовы на "функции" и "процедуры" - это устаревшее условное разделение, ничем не обоснованное на практике. |
|
|
ufna |
![]()
Сообщение
#12
|
![]() Активный участник ![]() ![]() ![]() Группа: Участник Сообщений: 362 Регистрация: 24.5.2008 Из: Курган/СПб Пользователь №: 182 Спасибо сказали: 29 раз(а) Репутация: ![]() ![]() ![]() |
и положительные эмоции, и не очень
![]() как уже было сказано - цели и практика конкретного приложения могут быть разными. Иногда "красиво" идет в ущерб быстродействию, как минимум. |
|
|
Tonal |
![]()
Сообщение
#13
|
![]() Активный участник ![]() ![]() ![]() Группа: Участник Сообщений: 452 Регистрация: 6.12.2007 Из: Новосибирск Пользователь №: 34 Спасибо сказали: 69 раз(а) Репутация: ![]() ![]() ![]() |
Цитата(Iron Bug @ 29.3.2010, 0:08) Link про возвращаемое значение: имхо - функция ВСЕГДА должна возвращать int с кодом ошибки и точка. результаты - в параметрах. Если постоянно работаешь с чистым С, и основные апи на нём или на "С с классами" то это вполне оправданно - для единообразия. ![]() В других случаях вполне разумно использовать и остальные возможности С++, например такие как возвращение экземпляра структуры/класса из функции и исключения. ![]() А вот смесь этих подходов очень чревата ошибками. Я как-то видел большой проект, где функции и возвращали код ошибки, и бросали исключения - очень неприятное спагетти получалось... Кстати, возвращать таки лучше не int, а перечисление. ![]() Цитата(Iron Bug @ 29.3.2010, 0:08) Link про геттеры и сеттеры - для крупных проектов со сложными объектами это единственный нормальный и безопасный способ обращения к данным. при этом обеспечивается полная инкапсуляция и наследование. Зависит от назначения класса/структуры. В том же std::pair геттеры и сеттеры, как и наследование бессмысленны. ![]() А наследование, в С++, обеспечивается наличием средствами языка, а не геттерами/сеттерами. ![]() Ну и про рекурсию - это маразм. ![]() Итеративные алгоритмы - это просто подмножество рекурсивных. Другое дело, что встроенную в императивный язык рекурсию можно вручную нарисовать с помощью явных стеков на массиве и циклов. Но такая эмуляция будет гораздо менее понятной и более подверженной ошибкам чем явная. ![]() С другой стороны рекурсивные алгоритмы всё-таки пока требуются не так часто. Рекурсией конечно не следует злоупотреблять, как и любой возможностью. И нужно чётко представлять во что выльется тот или иной код для выбранного языка и компилятора. П. С. Функциональные языки, типа Haskell и LISP полностью строятся на рекурсии и циклы в них - это довольно простые функции выраженные в терминах рекурсии. ![]() Ага, таки решил прочитать опус. ![]() Про рекурсию у него примерно то и написано что у меня. ![]() Про вложенные функции с ним не согласен. Просто лексическая вложенность функций ничем не лучше чем объединение их в классе или пространстве имён или модулей и пакетов. А вот для организации частичных применений/замыканий это очень удобно. Замечательно что в новом стандарте для этого есть механизм лямбд! ![]() С длинной массива тоже не всегда так однозначно. Например алгоритму бинарного поиска нужно именно отдельное количество элементов. ![]() Да, свойства я тоже не люблю - из кода не видно что происходит - тривиальное действие присвоения или что-то "великое и ужасное". ![]() Ну и вообще, красота кода сильно зависит от языка и парадигмы, в которой код написан - красивый код на Pascal будет уродским на Python и оба они будут корявыми для С++ и наоборот. Код в стиле MFC|xWidget покоробит в проекте использующем в основном на Boost/Loki. ![]() |
|
|
Iron Bug |
![]()
Сообщение
#14
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Модератор Сообщений: 1611 Регистрация: 6.2.2009 Из: Yekaterinburg Пользователь №: 533 Спасибо сказали: 219 раз(а) Репутация: ![]() ![]() ![]() |
Цитата(Tonal @ 30.3.2010, 11:14) Link Да, свойства я тоже не люблю - из кода не видно что происходит - тривиальное действие присвоения или что-то "великое и ужасное". ![]() вот ради этого "великого и ужасного" и нужны сеттеры и геттеры. потому что когда у тебя закрытая библиотека и незнакомый с тонкостями твоего кода юзер хочет, скажем, написать свой класс на основе твоего базового - то вот тогда без них он пожнёт все возможные грабли. надо всегда делать библиотеки такими, чтобы вызовы были безопасны для структуры внутренних данных объекта. а прямые обращения часто этому противоречат и могут быть небезопасны при многопоточности, к примеру. а про возвращение результата функции, это элементарно: что должна вернуть функция, если ей задали параметры вне её области определения? ноль? минус один? а где гарантия, что это значение не совпадёт с нормальным возможным значением? а если кидать исключения, то, к примеру, есть у пользователя десять библиотек. в каждой - свои классы исключений, которые каждая функция кидает и надо отлавливать и разгребать это дерьмище. это просто капец, надо заметить! в сложных обработчиках исключения полезны для раскрутки стека. а вот в примитивных функциях - проще возвращать код возврата и значение в параметре. думаете, мелкософт свои стандартные библиотеки зря переписали с "безопасными" вариантами вызовов, где возвращается именно результат выполенения, а указатели или ссылки для параметров передаются в параметрах? хотя они и не пример правильного программирования, но просто так, без причины, они бы этого делать не стали. когда программируешь много и имеешь дело с разношёрстными библиотеками, нет ничего хуже, чем дикое многообразие результатов и необходимость вникать в особенности реализации каждой конкретной мелкой функции. Сообщение отредактировал Iron Bug - 30.3.2010, 20:02 |
|
|
Tonal |
![]()
Сообщение
#15
|
![]() Активный участник ![]() ![]() ![]() Группа: Участник Сообщений: 452 Регистрация: 6.12.2007 Из: Новосибирск Пользователь №: 34 Спасибо сказали: 69 раз(а) Репутация: ![]() ![]() ![]() |
Цитата(Iron Bug @ 30.3.2010, 23:56) Link Цитата(Tonal @ 30.3.2010, 11:14) Link Да, свойства я тоже не люблю - из кода не видно что происходит - тривиальное действие присвоения или что-то "великое и ужасное". ![]() вот ради этого "великого и ужасного" и нужны сеттеры и геттеры. потому что когда у тебя закрытая библиотека и незнакомый с тонкостями твоего кода юзер хочет, скажем, написать свой класс на основе твоего базового - то вот тогда без них он пожнёт все возможные грабли. надо всегда делать библиотеки такими, чтобы вызовы были безопасны для структуры внутренних данных объекта. а прямые обращения часто этому противоречат и могут быть небезопасны при многопоточности, к примеру. При наследовании интерфейса ты с такими граблями не столкнёшься - нет состояния у родителя. А при наследовании реализации всё сильно зависит от назначения и дизайна. Довольно часто полное закрытие внутреннего состояния от потомка приводит к необходимости его дублирования и дополнительной синхронизации. Ну и быстродействие может сильно пострадать, особенно при многопоточке. ![]() Цитата(Iron Bug @ 30.3.2010, 23:56) Link а про возвращение результата функции, это элементарно: что должна вернуть функция, если ей задали параметры вне её области определения? ноль? минус один? а где гарантия, что это значение не совпадёт с нормальным возможным значением? Ну дак давай пойдём до конца: какую сигнатуру должен иметь оператор + или new? И что они должны делать при возникновении ошибок? Что и как должен возвращать конструктор? ![]() Ну и с областью определений - есть функции внешнего интерфейса системы - там функция обязательно должна проверить корректность параметров и сообщить пользователю если что не так. А есть внутренние - передача в них неверного значения это ошибка кодирования, которую должен отловить компилятор и/или система тестирования. Для сигнализации о них вполне уместны разного рода ассерты. Т. е. такие ошибки лучше закрывать более тщательным типизированием. Ещё раз, то что хорошо для чистого С или в стиле "С с классами" как в MFC, не обязательно хорошо/удобно/наглядно/быстро/компактно в С++. ![]() Цитата(Iron Bug @ 30.3.2010, 23:56) Link а если кидать исключения, то, к примеру, есть у пользователя десять библиотек. в каждой - свои классы исключений, которые каждая функция кидает и надо отлавливать и разгребать это дерьмище. Ежели ты работаешь с зоопарком библиотек, то кто тебе сможет гарантировать одинаковые стратегии обработки ошибок в них? Даже если у некоторых стратегия схожа, то нюансы могут отличатся очень сильно. Например значение кодов возврата и их структура. Стандарты на сигнатуру - кто-то возвращает код ошибки как результат, а кто-то в параметре. У кого-то код ошибки получается вовсе вызовом отдельной функции (привет Win32 & Posix) А кто-то кидает исключение в случае ошибки а в код возврата отдаёт признак наличия предупреждений... Так что тут всяко придётся каждую отдельным местом оборачивать и обрабатывать. Цитата(Iron Bug @ 30.3.2010, 23:56) Link Думаете, мелкософт свои стандартные библиотеки зря переписали с "безопасными" вариантами вызовов, где возвращается именно результат выполенения, а указатели или ссылки для параметров передаются в параметрах? Это про С или про С++? Ну и думаю, таки зря. ![]() Сообщение отредактировал Tonal - 31.3.2010, 7:50 |
|
|
BRE |
![]()
Сообщение
#16
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 1112 Регистрация: 6.3.2009 Из: Ростов-на-Дону Пользователь №: 591 Спасибо сказали: 264 раз(а) Репутация: ![]() ![]() ![]() |
Цитата(Iron Bug @ 30.3.2010, 20:56) Link есть у пользователя десять библиотек. в каждой - свои классы исключений, которые каждая функция кидает и надо отлавливать и разгребать это дерьмище. это просто капец, надо заметить! К сказанному Tonal хочу добавить свои мысли по поводу зоопарка библиотек. Для интеграции каждой библиотеки наверное лучше написать свои врапперы, которые будут иметь однотипный интерфейс, как по вызову их функционала, так и по сообщению результата своей работы. Тогда возможно смена низкоуровневых библиотек без изменения кода основной системы. И даже не обязательно прятать весь функционал библиотеки, достаточно описать и предоставить только используемый. |
|
|
Iron Bug |
![]()
Сообщение
#17
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Модератор Сообщений: 1611 Регистрация: 6.2.2009 Из: Yekaterinburg Пользователь №: 533 Спасибо сказали: 219 раз(а) Репутация: ![]() ![]() ![]() |
Цитата(Tonal @ 31.3.2010, 9:44) Link Ну и быстродействие может сильно пострадать, особенно при многопоточке. ![]() практика показывает, что не страдает. там, где идёт прямое обращение, компилятор сам оптимизирует вызовы в inline . так что по скорости это никак не отличается. Цитата(Tonal @ 31.3.2010, 9:44) Link Ну дак давай пойдём до конца: какую сигнатуру должен иметь оператор + или new? И что они должны делать при возникновении ошибок? Что и как должен возвращать конструктор? ![]() это уже демагогия. речь шла о функциях. как известно, операторы - особые функции. впрочем, за последние N лет мне ни разу не потребовалось переписывать оператор +, к примеру. просто перегрузка оператора - это довольно экзотическое требование, которое больше относится к удобству программирования, чем к эффективности. а оператор new имеет строгое формальное описание. мы тут не спорим о синтаксисе С++. Цитата(Tonal @ 31.3.2010, 9:44) Link Ну и с областью определений - есть функции внешнего интерфейса системы - там функция обязательно должна проверить корректность параметров и сообщить пользователю если что не так. А есть внутренние - передача в них неверного значения это ошибка кодирования, которую должен отловить компилятор и/или система тестирования. Для сигнализации о них вполне уместны разного рода ассерты. Т. е. такие ошибки лучше закрывать более тщательным типизированием. что значит "сообщить пользователю" когда, к примеру, ты управляешь системой реального времени? ругнуться в свой лог? пользы от этого - ноль. там уже накроется всё оборудование, железяки покорёжит, пока ты пишешь своё "сообщение пользователю". в реальном времени нет возможности пространного ввода-вывода и ассертов. всё решается проще - возврат 0 или 1. через регистры. очень быстро и просто. а типизирование при рантайме не помогает. пришло тебе ошибочное число от аппаратуры и надо его обрабатывать. а как ты заранее предугадаешь, что может прийти? так что далеко не везде есть возможность развёрнутых сообщений об ошибках и отлова десятков исключений с перебором, чего же там всё-таки попалось. это очень замедляет и усложняет работу софта. Цитата(Tonal @ 31.3.2010, 9:44) Link Ежели ты работаешь с зоопарком библиотек, то кто тебе сможет гарантировать одинаковые стратегии обработки ошибок в них? ... Стандарты на сигнатуру - кто-то возвращает код ошибки как результат, а кто-то в параметре. ну, практически все функции возвращают 0 при удачном завершении. а остальное - в параметрах. по крайней мере, хардварные программеры придерживаются такой идеологии и разнообразия мнений как-то особо не наблюдается. Сообщение отредактировал Iron Bug - 31.3.2010, 14:31 |
|
|
Tonal |
![]()
Сообщение
#18
|
![]() Активный участник ![]() ![]() ![]() Группа: Участник Сообщений: 452 Регистрация: 6.12.2007 Из: Новосибирск Пользователь №: 34 Спасибо сказали: 69 раз(а) Репутация: ![]() ![]() ![]() |
Цитата(Iron Bug @ 31.3.2010, 18:30) Link Цитата(Tonal @ 31.3.2010, 9:44) Link Ну и быстродействие может сильно пострадать, особенно при многопоточке. ![]() практика показывает, что не страдает. там, где идёт прямое обращение, компилятор сам оптимизирует вызовы в inline . так что по скорости это никак не отличается. Практика - показывает что может всяко получится. ![]() Например, пусть класс реализует визуальный элемент - эллипс. При изменении размера по любой из полуосей его нужно перерисовать. Наследник - круг, при изменении любой полуоси должен изменять синхронно другую. Если доступ к полуосям эллипса только через геттеры и сеттеры, которые обеспечивают перерисовку элемента при изменении, то круг неизбежно будет дёргаться. ![]() Что приведёт к уродскому интерфейсу. Другой пример - многопоточный логгер. Пишет в файл, который создаётся в конструкторе и закрывается в деструкторе. Все операции защищает мутексом. Мы хотим сделать наследника, которрый обеспечивает ротирование логов. Если мы дадим доступ к мутексу клиентам (прямой или через геттер), то и есть прямая возможность нарушить инвариант класса и получить дедлоки... А если доступ у мутексу получить нельзя, мы не сможем атомарно переоткрыть файл для организации ротирования. Причём в обоих этих случаях о каких-либо инлайнах можно забыть - всё на уровне логики. ![]() Цитата(Iron Bug @ 31.3.2010, 18:30) Link Цитата(Tonal @ 31.3.2010, 9:44) Link Ну дак давай пойдём до конца: какую сигнатуру должен иметь оператор + или new? И что они должны делать при возникновении ошибок? Что и как должен возвращать конструктор? ![]() это уже демагогия. речь шла о функциях. как известно, операторы - особые функции. впрочем, за последние N лет мне ни разу не потребовалось переписывать оператор +, к примеру. просто перегрузка оператора - это довольно экзотическое требование, которое больше относится к удобству программирования, чем к эффективности. а оператор new имеет строгое формальное описание. мы тут не спорим о синтаксисе С++. Link - набор полемических приёмов вводящих заблуждение. Я никого в заблуждение не вводил, а предложил довести твоё утверждение до логического конца (явного противоречия) для того, чтобы выявить границы его применимости. ![]() Сигнатура операторов может изменятся в довольно широких пределах - см. например operator(). А насчёт экзотики - это опять же именно твоё личное мнение, обусловленное тем, что ты видимо мало работала в областях связанных с массовыми расчётами. У меня есть знакомая библиотека расчётов для векторной графики написанная на С++ в 94-96гг по мотивам реализаций на Fortran и Pascal. Где-то в 2003 была попытка перевода её на Delphi - провалилась. Удобство использования совмещения (перегрузки) операторов оказалась критичным. А если смотреть с точки зрения чистого С на объекты - это всего лишь чуть более удобный способ записи структуры, функций работающий с ней и таблиц указателей на такие функции. Так какая же сигнатура должна быть у конструкторов, функции std::strlen, std::string::size(), std::find, std::sort, и остальных? ![]() Цитата(Iron Bug @ 31.3.2010, 18:30) Link что значит "сообщить пользователю" когда, к примеру, ты управляешь системой реального времени? ругнуться в свой лог? пользы от этого - ноль. там уже накроется всё оборудование, железяки покорёжит, пока ты пишешь своё "сообщение пользователю". в реальном времени нет возможности пространного ввода-вывода и ассертов. всё решается проще - возврат 0 или 1. через регистры. очень быстро и просто. а типизирование при рантайме не помогает. пришло тебе ошибочное число от аппаратуры и надо его обрабатывать. а как ты заранее предугадаешь, что может прийти? так что далеко не везде есть возможность развёрнутых сообщений об ошибках и отлова десятков исключений с перебором, чего же там всё-таки попалось. это очень замедляет и усложняет работу софта. Пользователь здесь - это тот код, который вызвал функцию. Сообщить ему - это значит стандартным для твоей системы образом просигнализировать об этом. Т. е. возвратить код ошибки, или установить код операции, или вызвать исключение, или показать сообщение. ![]() В любом случае, у системы/библиотеки/модуля должен быть стандартный способ такой сигнализации. 0 и 1 через регистры это очень хорошо и быстро, а что делать, если у тебя система работает с серверами баз данных, SOAP и DCOM. И с одним из них пропала связь или возникла какая другая критическая ошибка? Критическая здесь - это когда код на данном уровне не может принять решение по её обработке самостоятельно. Какую 1 или 0 ты будешь через регистры передавать? Т. е. тебе придётся эти ошибки ка-то классифицировать и передавать о них информацию, чтобы на верхнем уровне она была доступна и её было достаточно для принятия решений. Кроме того, в случае с кодами возврата и результатом операций, у тебя нет возможность гарантировать что клиентский код не забудет их проверить и при проверке правильно проинтерпретирует. А при возбуждении исключения, ты во первых явно передаёшь нужные данные в объекте, во вторых, если исключение не обработают оно уедет на следующий уровень - т. е. нечаянно проигнорировать критическое событие не получится. Ну и "ошибочное число от аппаратуры" придти не может. Это программа может быть написана так, что она ломается, когда приходят какие-то значения. Например браузер и ОС не должны "упать" если в ответ на запрос www.microsoft.com придёт мусор из свапфайла. ![]() Это как раз внешние границы системы, только тут клиентами выступают не человек или код, а железки. И их данные нужно проверять на допустимость обязательно. А вот во внутренних функциях - все даные уже обязаны быть проверены - в ином случае это ошибка кодирования. Именно тут рулит типизация и ассерты. Цитата(Iron Bug @ 31.3.2010, 18:30) Link Цитата(Tonal @ 31.3.2010, 9:44) Link Ежели ты работаешь с зоопарком библиотек, то кто тебе сможет гарантировать одинаковые стратегии обработки ошибок в них? ... Стандарты на сигнатуру - кто-то возвращает код ошибки как результат, а кто-то в параметре. ну, практически все функции возвращают 0 при удачном завершении. а остальное - в параметрах. по крайней мере, хардварные программеры придерживаются такой идеологии и разнообразия мнений как-то особо не наблюдается. Хардварь - не единственная область применения С++, не говоря уже о других языках. |
|
|
AD |
![]()
Сообщение
#19
|
Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 2003 Регистрация: 4.2.2008 Из: S-Petersburg Пользователь №: 84 Спасибо сказали: 70 раз(а) Репутация: ![]() ![]() ![]() |
Могу сказать, что крайне интересная тема получилась! Обоим участвующим в дискуссии большое спасибо. Крайне интересно.
|
|
|
![]() ![]() |
![]() |
|
Текстовая версия | Сейчас: 18.8.2025, 22:20 |