yigal_s: (general)
[personal profile] yigal_s
В С++ есть две "культуры" конструирования функций как объектов.

С одной стороны - функторы, тип которых отражает практически полностью их начинку. Т.е. если внутри этой функции будет сложение, то в навороченном объекте, функцию эту имплементирующем, а так же в его типе, будет какой-то подобъект "add", реализующий сложение, собственно сам объект представляет собой дерево более элементарных объектов, исполняющих математические действия, bind-ящих константы вместо каких-то отдельных аргументов итд., а его темплейтный тип имеет в качестве аргументов другие темплейтные типы итд. опять же деревом, и среди этих типов будет и add, и bind, и всё остальное прочее что мы по дороге в наш функтор запихали. И, что важно, функция вызова подобного функционального объекта не виртуальна. Подобные функции стали делать в STL, продолжили делать в boost и даже лямбда-функция в С++ в какой-то отдаленной мере отражает этот же подход, поскольку её тип уникален.

С другой стороны, построив с грехом пополам в С++ функтор как композицию объектов, или же создав лямбду, его или её можно присвоить инстансу класса std::function, который в своих темплейтных параметрах несет только сигнатуру необходимого функционального вызова, в отношении всей же остальной начинки выполняет типичный type erasure. И далее работать уже с std::function. Или же можно работать с функциональными объектами, которые имеют виртуальную функцию вызова (не как в STL или boost), тем самым осуществляя type erasure посредством обращения с классом функции через её базовый интерфейс.

Первый подход, очевидно, вызывает в С++ генерацию нового кода для каждой функции ИСПОЛЬЗУЮЩЕЙ наш функциональный объект, использование же класса "function" позволяет это избежать.

Мне интересно - какие есть принципиальные случаи, когда первый подход в принципе не работает? Один случай я уже знаю - это когда мы динамически генерим функтор по каким-то входным данным, скажем, пользователь может написать выражение y=sin(2*x), мы это выражение распарсиваем и строим функциональный объект, вычисляющий данное выражение. А вот если нет у нас юзеровского ввода, могут ли тем не менее быть ситуации, когда вариант с полной статической типизацией функтора в С++ не срабатывает? Ну, наверное, еще какая-нибудь задача, где нам надо сгенерить и перебрать какой-нибудь класс арифметических выражений.

Что-нибудь ещё менее вычурное из задач, где статическая типизация не подходит, имеется ли?

Date: 2014-10-08 04:38 pm (UTC)
From: [identity profile] panchul.livejournal.com
Я выучил C++ еще в 1992 году (С в 1986), также знаком с Smalltalk и List и в свое время прочел несколько книжек по методологии объектно-ориентированного дизайна.

Так вот, первые пару лет я наигрался с этими методологиями и у меня появилось подозрение, что они снижают и производительность программиста, и качество программ, так как смещают фокус программиста с решения проблемы на программирование ради программирования, а также рутинно вводят лишние сущности, сильно затрудняющие поддержку кода после исчезновения исходных авторов. После смены 2-3 поколений разработчиков объектно-ориентированный с извращениями код превращается в неподдерживаемый хаос, а новые правки приводят к новым багам.

Date: 2014-10-08 07:09 pm (UTC)
From: [identity profile] panchul.livejournal.com
*** Все эти "методологии" включают определенные накладные расходы и имеют определенную цену (что особо не рекламируется). Предполагается, что суммарный баланс расходов на решение инфраструктурных задач, создание всякой мишуры абстракций и проч проч и доходов, которые всё это принесёт, будет существенно положительный. ***

Все это накрывается медным тазом после появления в проекте первых fresh college graduates без индустриального опыта, от которых менеджмент требует быстренько поставить заплату, чтобы программа прошла regression и ее можно было бы отправить клиенту. Учитывая, что люди с первыми или не особенно нужными им работами в гробу видали попытку разобраться в design intentions исходных авторов, думая о скором нахождении другой работы, они создают хаос, который (в сложных методологиях) приводит очень серьезной ненадежности.

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