Re[39]: Императивная парадигма
От: samius Япония http://sams-tricks.blogspot.com
Дата: 23.07.11 18:01
Оценка:
Здравствуйте, Undying, Вы писали:

U>Здравствуйте, samius, Вы писали:


S>>А чем же тебя не устроила Graphics.DrawText? Тем что несвободна? Кстати, я так и не понял, свободные функции в твоем определении как-то связаны с детерминированностью и сайд эффектами? Пример-то какой-то уж сайд-эффектный больно.


U>Graphics.DrawText это свободная функция и очень полезная функция.

Теперь я даже перестал догадываться, что ты подразумеваешь под свободной функцией. Опять не то что другие?

U>Но она является низкоуровневой по сравнению со свободной функцией отрисовки текста textBox'а, т.к. к примеру ничего не знает о том, что часть текста может быть выделенной и ее надо выводить по другому.

Сколько же будет параметров у свободной функции отрисовки текста textBox'а, если не передавать весь textBox?

U>Соответственно над Graphics.DrawText будет много обвязочного кода, а над свободной функцией вывода текста в textBox'е обвязки практически не будет, т.к. и вызовы Graphics.DrawText и обвязка над ними внутрь этой самой функции и уйдут.
Re[37]: Императивная парадигма
От: samius Япония http://sams-tricks.blogspot.com
Дата: 23.07.11 18:07
Оценка: :)
Здравствуйте, Undying, Вы писали:

U>Здравствуйте, samius, Вы писали:


S>>Дай-ка определение свободной функции. А то у тебя Array.Resize вышел вроде как свободным, и оказался уровнем выше линка.


U>Свободные функции могут иметь самый разный уровень. Но уровень верхних свободных функций определяется уровнем преобразования. Естественно если бизнес-задача требует только низкоуровневых преобразований (как добавление элемента в список, к примеру), то и свободные функции будут там низкоуровневыми. Если же задача будет посложнее, то и верхний уровень свободных функций будет выше.

Что такое автобус?
— Автобусы бывают Львовские и Икарусы...
Вот ты мне примерно так ответил.

U>>>На маленьком примере это будет невидно, привести большой пример не позволяет формат форумного общения.

S>>Может дашь ссылку на какой-то ресурс, где об этом сказано?

U>Не знаю. Толчок в этом направлении мне дал Darkgray. Дальше сам.

А когда он давал тебе толчек, какими словами он о функциях толкал, не помнишь? Если все-таки о чистых, то твой пример о textBox-е мимо.
Re[38]: Императивная парадигма
От: Undying Россия  
Дата: 23.07.11 18:17
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Неа — всё это может влиять на рендеринг, два примера: автосайз текстбокса, шаблон "рыбий глаз" — размер текста увеличивается при выделении. Кроме того, фон рамки зависит от кучи флагов состояния — начиная с системных параметров и заканчивая фокусом (тот же accepts enter = false перенесёт альтернативный фокус (тот, что срабатывает по нажатию на enter) на кнопку по умолчанию).


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

S>Суммируя: даже набор нужных параметров для отрисовки зависит от текущего состояния текстбокса. Ну сделаем мы тонну static-методов и будем передавать не сам контрол, а отдельные его поля — как это повлияет на их "чистоту"?


Мы захотели написать comboBox и там тоже нужен рыбий глаз. Как ты будешь реализовать его в comboBox'е, если при реализации textBox'а ты свободные функции не использовал? Сдублируешь код?

S>Самый правильный (имхо) подход здесь — разнесение построения декларативного visual tree и собственно рендеринга. Как это выстреливает можно посмотреть на примере WPF.

S>Во-первых, вы можем манипулировать самим visual tree — начиная с анимаций по условию и заканчивая полной сменой шаблона.
S>Во-вторых, мы можем использовать информацию о состоянии контрола не только для рендеринга, но и для hit testing и accessibility (aka win automation).
S>В третьих, мы теперь можем относительно легко перенести стек рендеринга на удалённую машину — см RemoteFX.

То что ты говоришь, совершенно ортогонально свободным функциям.

S>Другими словами: "чистоту" кода можно повысить, инкапсулируя внутреннее состояние внутри слоя. Тут я всеми руками-ногами за. А вот избавиться от состояния совсем — не получится. Поэтому проще переиспользовать кирпичики-классы, чем изобретать 1025й способ эмулировать this.


А кто предлагает избавляться от состояния? Для инкапсуляция состояния придуманы объекты, для инкапсуляции преобразований придуманы свободные функции. Одно другому никак не мешает.
Re[40]: Императивная парадигма
От: Undying Россия  
Дата: 23.07.11 18:21
Оценка:
Здравствуйте, samius, Вы писали:

U>>Graphics.DrawText это свободная функция и очень полезная функция.

S>Теперь я даже перестал догадываться, что ты подразумеваешь под свободной функцией. Опять не то что другие?

Извиняюсь, туплю что-то на ночь глядя. Graphics.DrawText действительно не является свободной функцией, хотя и остается очень полезной.

U>>Но она является низкоуровневой по сравнению со свободной функцией отрисовки текста textBox'а, т.к. к примеру ничего не знает о том, что часть текста может быть выделенной и ее надо выводить по другому.

S>Сколько же будет параметров у свободной функции отрисовки текста textBox'а, если не передавать весь textBox?

Зависит от того в каком виде мы их будем передавать. Если в виде примитивных типов, то много, если в каком-то сгруппированном, то намного меньше.
Re[38]: Императивная парадигма
От: Undying Россия  
Дата: 23.07.11 18:23
Оценка:
Здравствуйте, samius, Вы писали:

S>Что такое автобус?

S>- Автобусы бывают Львовские и Икарусы...
S>Вот ты мне примерно так ответил.

S>А когда он давал тебе толчек, какими словами он о функциях толкал, не помнишь? Если все-таки о чистых, то твой пример о textBox-е мимо.


Все-таки твоя способность не замечать суть за формализмами продолжает меня удивлять.
Re[39]: Императивная парадигма
От: samius Япония http://sams-tricks.blogspot.com
Дата: 23.07.11 18:24
Оценка: :)
Здравствуйте, Undying, Вы писали:

U>Здравствуйте, samius, Вы писали:


S>>А когда он давал тебе толчек, какими словами он о функциях толкал, не помнишь? Если все-таки о чистых, то твой пример о textBox-е мимо.


U>Все-таки твоя способность не замечать суть за формализмами продолжает меня удивлять.


О какой сути может быть речь, если я не понимаю, что ты подразумеваешь под свободными? Ведь под чистыми и детерминированными ты тоже что-то свое подразумевал!
Re[41]: Императивная парадигма
От: samius Япония http://sams-tricks.blogspot.com
Дата: 23.07.11 18:25
Оценка: :)
Здравствуйте, Undying, Вы писали:

U>Здравствуйте, samius, Вы писали:


U>>>Graphics.DrawText это свободная функция и очень полезная функция.

S>>Теперь я даже перестал догадываться, что ты подразумеваешь под свободной функцией. Опять не то что другие?

U>Извиняюсь, туплю что-то на ночь глядя. Graphics.DrawText действительно не является свободной функцией, хотя и остается очень полезной.


Значит ты все-таки о тривиальном ExtractMethod, но своими словами.
Re[42]: Императивная парадигма
От: samius Япония http://sams-tricks.blogspot.com
Дата: 23.07.11 21:39
Оценка:
Здравствуйте, samius, Вы писали:

S>Здравствуйте, Undying, Вы писали:


U>>Здравствуйте, samius, Вы писали:


U>>>>Graphics.DrawText это свободная функция и очень полезная функция.

S>>>Теперь я даже перестал догадываться, что ты подразумеваешь под свободной функцией. Опять не то что другие?

U>>Извиняюсь, туплю что-то на ночь глядя. Graphics.DrawText действительно не является свободной функцией, хотя и остается очень полезной.


S>Значит ты все-таки о тривиальном ExtractMethod, но своими словами.


Вижу мои потуги понять тебя вызывают у тебя улыбки

Попробую показать, как это выглядит с моей стороны:

Сначала ты рассуждаешь о чистоте и императивности, потом говоришь о пользе чистой процедуры.

Изменять входные параметры чистая функция имеет право, соответственно чистая процедура (т.е. функция без возвращаемого значения) вполне возможна.

потом что это фигня, и важнее "внешность" аргументов

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

Что методы строки в дотнете нечисты

Впрочем есть подозрение, что большинство функций класса string на самом деле работают с внешним массивом char'ов, а не со строкой и соответственно чистыми не являются и близко.

что определение на вики бессмысленно

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

потом пошла тема про детерминированность

Детерминированная функция это такая функция, результат работы которой определяется только ее аргументами и ничем более.

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

Если массив принимается как аргумент, то он не является внешним и функция детерминирована. Если массив принимается через замыкание (через обращение к полю класса или статическому полю не суть важно), то он является внешним и функция недетерминирована.

Наконец-то удачный термин подобрал, то чему я давал определение должно называться "свободными функциями".

Т.е. я просто в твое определение чистоты а затем детерминированности подставляю "свободу" и получаю что-товроде
Свободная функция это такая функция, результат работы которой определяется только ее аргументами и ничем более.
Иду в интернет и неоднократно вижу упоминание под свободной функцией функции, не принадлежащие классам.
Я в затруднении.
Потом ты написал

При использовании свободных функций для получения этой информации достаточно просмотреть одну строчку кода, в случае использования функций класса — десятки, а то и сотни строчек кода.

Из чего можно сделать вывод, что ты противопоставляешь функции класса и свободные. Я подумал, что речь идет о трактовке, известной в интернете, а не об детерминированности под другим термином.
Потом

Свободные бизнес-функции много выше уровнем, нежели linq.

Отсюда следует что функции linq для тебя не являются свободными. Что с ними не так? Они вроде как не функции класса (хоть и лежат в Enumerable классе, но в C# нет возможности делать функции без класса ). Но что-то же ты называешь свободными.

Потом пошел пример с текстбоксом, где выяснилось что

Graphics.DrawText это свободная функция и очень полезная функция.

По каким критериям она свободна, если это метод класса, да еще и нифига не детерминированный (даже не говоря о недетерминированности GDI, достаточно помянуть что комплекты шрифтов разные на разных машинах).

Свободные функции могут иметь самый разный уровень. Но уровень верхних свободных функций определяется уровнем преобразования.

О! Преобразования? Так все-таки наверное речь о чистоте?

Естественно если бизнес-задача требует только низкоуровневых преобразований (как добавление элемента в список, к примеру)

Опять загадка. Преобразованием можно назвать добавление элемента к функциональному списку (Cons). И оформить это можно только в качестве свободной функции. А кому придет в голову делать это методом узла списка? Но как быть с Graphics.DrawText? он-то к функциональщине отношения никакого не имеет, да и метод класса!
Может ты подразумеваешь добавление к императивному списку, тогда делать добавление свободной функцией не с руки, т.к. нужно передавать кучу данных самого списка, причем передавать их для изменения (ref-ами). Что можно заюзать от добавления к списку в другом коде? Если список односвязный/двухсвязный — ничего. Если динамический массив — там куда проще написать _items[_count++] = value (с предварительной провекой емкости), чем вызывать свободную функцию для достижения того же эффекта. опять же, свободная функция такая есть (Array.SetValue)

Извиняюсь, туплю что-то на ночь глядя. Graphics.DrawText действительно не является свободной функцией

И действительно, не является ни свободной в контексте детерминированности, ни свободной в контексте принадлежности экземпляру класса.

Но о чем ты говорил тогда в самом начале, о свободных процедурах?

И знаешь что? В то время как ты рассуждаешь об уровнях свободы функций и значительном улучшении читабельности при изпользовании свободных функций, я даже не могу понять, что именно ты подразумеваешь под "свободными функциями"!

Все-таки твоя способность не замечать суть за формализмами продолжает меня удивлять.

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

Давай совсем по простому. Свободные функции свободны от чего?

З.Ы. Если я тут один не понимаю о чем речь, то попрошу коллег, которые поняли суть, попытаться объяснить мне ее.
Re[43]: Императивная парадигма
От: Undying Россия  
Дата: 24.07.11 04:48
Оценка:
Здравствуйте, samius, Вы писали:

S>Т.е. я просто в твое определение чистоты а затем детерминированности подставляю "свободу" и получаю что-товроде

S>Свободная функция это такая функция, результат работы которой определяется только ее аргументами и ничем более.

Правильно понимаешь. Констатируем термины:

Свободная функция это такая функция, результат работы которой определяется только ее аргументами и ничем более.
Чистая функция это свободная функция, не изменяющая своих аргументов.

Что такое детерминированная функция не важно, для того, что я хотел донести терминов свободная и чистая функция достаточно.

S>Иду в интернет и неоднократно вижу упоминание под свободной функцией функции, не принадлежащие классам.

S>Я в затруднении.

Зачем идти в интернет, если определение термина было дано в дискуссии?

S>

S>Свободные бизнес-функции много выше уровнем, нежели linq.

S>Отсюда следует что функции linq для тебя не являются свободными. Что с ними не так? Они вроде как не функции класса (хоть и лежат в Enumerable классе, но в C# нет возможности делать функции без класса ). Но что-то же ты называешь свободными.

А выделенное ты не заметил? Функции linq это свободные функции, но это низкоуровневые кирпичики, свободные бизнес-функции могут быть намного выше уровнем, чем linq-функции.

S>По каким критериям она свободна, если это метод класса, да еще и нифига не детерминированный (даже не говоря о недетерминированности GDI, достаточно помянуть что комплекты шрифтов разные на разных машинах).


Я уже ответил, что ошибся и graphics.DrawText свободной функцией не является. Что непонятного-то?

S>

S>Свободные функции могут иметь самый разный уровень. Но уровень верхних свободных функций определяется уровнем преобразования.

S>О! Преобразования? Так все-таки наверное речь о чистоте?
S>[q]

Что такое вывод рамки textBox'а? Это преобразование пикселей экрана. Можем ли мы его оформить в качестве свободной функции? Очевидно, да. Может ли это преобразование быть записанным в виде чистой функции, если мы его делаем через graphics? Очевидно, нет, т.к. мы изменяем один из аргументов.

S>Может ты подразумеваешь добавление к императивному списку, тогда делать добавление свободной функцией не с руки, т.к. нужно передавать кучу данных самого списка, причем передавать их для изменения (ref-ами). Что можно заюзать от добавления к списку в другом коде? Если список односвязный/двухсвязный — ничего. Если динамический массив — там куда проще написать _items[_count++] = value (с предварительной провекой емкости), чем вызывать свободную функцию для достижения того же эффекта. опять же, свободная функция такая есть (Array.SetValue)


Повторяю еще раз: http://rsdn.ru/forum/philosophy/4353135.1.aspx
Автор: Undying
Дата: 22.07.11


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

Т.е. реализация list.Add должна выглядеть примерно так:

if (ListHlp.IsOverflowedArray(realCount, logicCount + 1))
  array = ListHlp.ArrayResize(array, realCount * 2, logicCount);

array[logicCount] = addValue;
logicCount++;


Где IsOverflowedArray и ArrayResize это свободные (и в данном случае чистые) функции. Использование list.Add на свободные функции заменять не надо.
Re[39]: Императивная парадигма
От: Sinix  
Дата: 24.07.11 05:57
Оценка:
Здравствуйте, Undying, Вы писали:

U>Если различия все же более серьезные, то, значит, будут разные свободные функции для разных режимов.

Комбинаторика. Даже имея 8 параметров (а их там больше), сколько у нас сочетаний? Что, если рамку понадобится отрисовать хитрым образом, например, отражая в ней текст? Или соседние контролы? Применяя свой алгоритм отрисовки? Сколько "свободных" методов понадобится, чтобы покрыть все варианты? И сколько из них придётся написать пользователям вашего фреймворка — вместо того, чтобы добавить пару строк декларативного описания?

U>Мы захотели написать comboBox и там тоже нужен рыбий глаз. Как ты будешь реализовать его в comboBox'е, если при реализации textBox'а ты свободные функции не использовал? Сдублируешь код?

Зачем? Просто переиспользую стиль XAML-я.


S>>Самый правильный (имхо) подход здесь — разнесение построения декларативного visual tree и собственно рендеринга.

U>То что ты говоришь, совершенно ортогонально свободным функциям.
Неа. Если вы переходим к построению visual tree, наличие или отсутствие свободных функций не играет никакой роли — мы уже перенесли всю сложность в само дерево и нет необходимости в придумывании ещё одного метода абстракции.

U>А кто предлагает избавляться от состояния? Для инкапсуляция состояния придуманы объекты, для инкапсуляции преобразований придуманы свободные функции. Одно другому никак не мешает.

Ок, чем (кроме того, что мы отказываемся от инкапсуляции логики) принципиально отличается
// псевдокод. TextBoxHelpers.cs
static Size Measure(TextBox textBox)
{
  if (textBox.WordWrap)
  {
    // ...
  }
}

от
// TextBox.cs
Size Measure()
{
  if (this.WordWrap)
  {
    // ...
  }
}

?
Re[40]: Императивная парадигма
От: Undying Россия  
Дата: 24.07.11 08:48
Оценка: 18 (1)
Здравствуйте, Sinix, Вы писали:

U>>Если различия все же более серьезные, то, значит, будут разные свободные функции для разных режимов.

S>Комбинаторика. Даже имея 8 параметров (а их там больше), сколько у нас сочетаний? Что, если рамку понадобится отрисовать хитрым образом, например, отражая в ней текст? Или соседние контролы? Применяя свой алгоритм отрисовки? Сколько "свободных" методов понадобится, чтобы покрыть все варианты?

Свободных методов понадобиться не больше, чем методов класса при традиционном подходе. Проблема-то в чем?

S>И сколько из них придётся написать пользователям вашего фреймворка — вместо того, чтобы добавить пару строк декларативного описания?


Сразу предупреждаю, что это оффтопик и никакого отношения к теме свободных функций не имеет. Но проблемой декларативного описания на псевдоязыках является то, что таким образом хорошо решаются только те задачи, которые были предусмотрены при проектировании псевдоязыка. Шаг влево и оказывается, что логически тривиальнейшая задача вообще решения не имеет. Наглядный пример тут http://rsdn.ru/forum/dotnet.gui/4332472.1.aspx
Автор: ariets
Дата: 06.07.11


U>>Мы захотели написать comboBox и там тоже нужен рыбий глаз. Как ты будешь реализовать его в comboBox'е, если при реализации textBox'а ты свободные функции не использовал? Сдублируешь код?

S>Зачем? Просто переиспользую стиль XAML-я.

Господи как с вами сложно. Причем здесь XAML? Стандартная проблема, решая задачу мы обнаруживаем, что часть задачи мы уже где-то делали. Что ты в этом случае делаешь, ждешь пока кто-нибудь напишет какой-нибудь XAML и решит задачу за тебя что ли?

S>Ок, чем (кроме того, что мы отказываемся от инкапсуляции логики) принципиально отличается

S>
S>// псевдокод. TextBoxHelpers.cs
S>static Size Measure(TextBox textBox)
S>{
S>  if (textBox.WordWrap)
S>  {
S>    // ...
S>  }
S>}
S>

S>от
S>
S>// TextBox.cs
S>Size Measure()
S>{
S>  if (this.WordWrap)
S>  {
S>    // ...
S>  }
S>}
S>

S>?

Как минимум тем, что TextBoxHelpers.Measure гарантирует, что пользуется только публичным интерфейсом textBox'а.
Re[44]: Императивная парадигма
От: samius Япония http://sams-tricks.blogspot.com
Дата: 24.07.11 08:56
Оценка:
Здравствуйте, Undying, Вы писали:

U>Здравствуйте, samius, Вы писали:


S>>Т.е. я просто в твое определение чистоты а затем детерминированности подставляю "свободу" и получаю что-товроде

S>>Свободная функция это такая функция, результат работы которой определяется только ее аргументами и ничем более.

U>Правильно понимаешь. Констатируем термины:


U>Свободная функция это такая функция, результат работы которой определяется только ее аргументами и ничем более.

Пусть это будет определение свободной функции (1)
U>Чистая функция это свободная функция, не изменяющая своих аргументов.
Т.е. по твоей версии "чистоты", Enumerable.Where — чистая?

U>Что такое детерминированная функция не важно, для того, что я хотел донести терминов свободная и чистая функция достаточно.

Пусть неважно

S>>Иду в интернет и неоднократно вижу упоминание под свободной функцией функции, не принадлежащие классам.

S>>Я в затруднении.

U>Зачем идти в интернет, если определение термина было дано в дискуссии?


S>>

S>>Свободные бизнес-функции много выше уровнем, нежели linq.

Соответствующее этому определению определение колеса выглядело бы так: Колеса автобуса много выше, нежели колеса самоката. Извини, я не посчитал это за определение.
Да и это определение противоречит определению (1), в котором о "бизнес"-е не было ни слова.

S>>Отсюда следует что функции linq для тебя не являются свободными. Что с ними не так? Они вроде как не функции класса (хоть и лежат в Enumerable классе, но в C# нет возможности делать функции без класса ). Но что-то же ты называешь свободными.


U>А выделенное ты не заметил? Функции linq это свободные функции, но это низкоуровневые кирпичики, свободные бизнес-функции могут быть намного выше уровнем, чем linq-функции.

Опять же, могут быть, а могут и не быть...

S>>По каким критериям она свободна, если это метод класса, да еще и нифига не детерминированный (даже не говоря о недетерминированности GDI, достаточно помянуть что комплекты шрифтов разные на разных машинах).


U>Я уже ответил, что ошибся и graphics.DrawText свободной функцией не является. Что непонятного-то?

Я показывал тебе последовательность моих предполоожений, основанных на твоих постах. Что DrawText свободной не является, я уже понял.

S>>

S>>Свободные функции могут иметь самый разный уровень. Но уровень верхних свободных функций определяется уровнем преобразования.

S>>О! Преобразования? Так все-таки наверное речь о чистоте?
S>>[q]

U>Что такое вывод рамки textBox'а? Это преобразование пикселей экрана. Можем ли мы его оформить в качестве свободной функции? Очевидно, да.

Очевидно, что не очевидно. Согласно твоему определению (1) функция преобразования пикселей экрана свободной в общем случае не является, т.к. ее результат зависит не только от аргументов, а еще и от настроек винды, GDI и т.п.

U>Может ли это преобразование быть записанным в виде чистой функции, если мы его делаем через graphics? Очевидно, нет, т.к. мы изменяем один из аргументов.

Ответ на выделенное — да. Т.е. преобразование может быть записано в виде чистой функции в общем понимании, и в виде чистой функции в твоем понимании.

S>>Может ты подразумеваешь добавление к императивному списку, тогда делать добавление свободной функцией не с руки, т.к. нужно передавать кучу данных самого списка, причем передавать их для изменения (ref-ами). Что можно заюзать от добавления к списку в другом коде? Если список односвязный/двухсвязный — ничего. Если динамический массив — там куда проще написать _items[_count++] = value (с предварительной провекой емкости), чем вызывать свободную функцию для достижения того же эффекта. опять же, свободная функция такая есть (Array.SetValue)


U>Повторяю еще раз: http://rsdn.ru/forum/philosophy/4353135.1.aspx
Автор: Undying
Дата: 22.07.11


U>Не нужно заменять вызовы функций классов вызовами свободных функций, т.к. понятно, что если мы запихали функцию в класс, то скорей всего сделали либо из соображений инкапсуляции, либо полиморфизма, и соответственно замена вызова на свободную функцию невозможна. Есть задача заменить реализацию функции класса на вызовы свободных функций с минимумом обвязки над ними, т.к. это резко упрощает и понимание реализации и резко увеличивает возможности по повторному использованию функциональности.


U>Т.е. реализация list.Add должна выглядеть примерно так:


U>
U>if (ListHlp.IsOverflowedArray(realCount, logicCount + 1))
U>  array = ListHlp.ArrayResize(array, realCount * 2, logicCount);

U>array[logicCount] = addValue;
U>logicCount++;
U>

Вот теперь, я кажется начинаю тебя понимать. Если сравнить этот код с кодом из BCL
public void Add(T item)
{
    if (this._size == this._items.Length)
    {
        this.EnsureCapacity(this._size + 1);
    }
    this._items[this._size++] = item;
    this._version++;
}

То твой код выгодно отличает то, что функции, которые ты используешь как вспомогательные, не используют посторонних эффектов (side effect), и не меняют неявно состояние класса.

U>Где IsOverflowedArray и ArrayResize это свободные (и в данном случае чистые) функции.

Верно. В данном случае они чистые.

U>Использование list.Add на свободные функции заменять не надо.

Вот тут-то и подвох. На самом низком уровне ты можешь использовать чистые функции. Уровнем выше, там где надо заюзать Add, твое правило уже неприменимо. Т.е. говоря о крутоте "свободных бизнес-функций высокого уровня", не надо забывать, что их крутота заканчивается при первом изменении чего-либо, т.е. повышать бесконечно уровень использования таких функций, оставаясь в рамках ИП, невозможно. Т.е. если ты даже сделаешь это и избавишься от сайд-эффектов и недетерминированности на любом уровне, то ты получишь функциональную программу.
Re[41]: Императивная парадигма
От: Sinix  
Дата: 24.07.11 09:40
Оценка:
Здравствуйте, Undying, Вы писали:

U>Свободных методов понадобиться не больше, чем методов класса при традиционном подходе. Проблема-то в чем?

Неа. Для традиционного подхода достаточно одного virtual Draw(), т.к все данные уже доступны из this, для "свободных" методов нам придётся нагрузить API методами, отражающими внутренние детали реализации. Максимум, что удастся — вынести в хелперы элементарщину аля DrawText — см ControlPaint в WinForms. Во что такой подход превращается для сложных контролов, очень легко увидеть на примере ToolStripRenderer — для каждого контрола появляется свой особый api отрисовки. Результат получился прямо противоположный тому, что мы хотели изначально

U>Шаг влево и оказывается, что логически тривиальнейшая задача вообще решения не имеет. Наглядный пример тут http://rsdn.ru/forum/dotnet.gui/4332472.1.aspx
Автор: ariets
Дата: 06.07.11

Одно решение предложили прямо там — обернуть 2 коллекции в одну. Другое — самое правильное — биндинг с конвертером — почему-то забыли


U>Причем здесь XAML? Стандартная проблема, решая задачу мы обнаруживаем, что часть задачи мы уже где-то делали. Что ты в этом случае делаешь, ждешь пока кто-нибудь напишет какой-нибудь XAML и решит задачу за тебя что ли?

Нет. Мы просто переиспользуем кирпичики-элементы visual tree (или добавляем свои), причём делаем это в декларативной манере. Xaml — это самый простой способ описания шаблонов, в шарпе придётся писать больше.

U>Как минимум тем, что TextBoxHelpers.Measure гарантирует, что пользуется только публичным интерфейсом textBox'а.


В принципе, можно закругляться — все всё высказали и подвижек не видно

Спасибо, было приятно поспорить!
Угу. Придётся или расширять public api методами, нужными только для measure, или прятать их в internal.
Re[45]: Императивная парадигма
От: Sinix  
Дата: 24.07.11 09:45
Оценка: 7 (1)
Здравствуйте, samius, Вы писали:

S>То твой код выгодно отличает то, что функции, которые ты используешь как вспомогательные, не используют посторонних эффектов (side effect), и не меняют неявно состояние класса.


Сорри что влажу, но для получения того же эффекта не нужно выносить код в классы-хелперы, достаточно пометить их [Pure] и использовать static-checker ис code contracts. Ну, или написать своё правило к code analysis, у самого где-то прототип валяется (выкинут за практической малопригодностью).

S>Т.е. говоря о крутоте "свободных бизнес-функций высокого уровня", не надо забывать, что их крутота заканчивается при первом изменении чего-либо, т.е. повышать бесконечно уровень использования таких функций, оставаясь в рамках ИП, невозможно. Т.е. если ты даже сделаешь это и избавишься от сайд-эффектов и недетерминированности на любом уровне, то ты получишь функциональную программу.

+1
Re[46]: Императивная парадигма
От: samius Япония http://sams-tricks.blogspot.com
Дата: 24.07.11 09:57
Оценка: +1
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, samius, Вы писали:


S>>То твой код выгодно отличает то, что функции, которые ты используешь как вспомогательные, не используют посторонних эффектов (side effect), и не меняют неявно состояние класса.


S>Сорри что влажу, но для получения того же эффекта не нужно выносить код в классы-хелперы, достаточно пометить их [Pure] и использовать static-checker ис code contracts. Ну, или написать своё правило к code analysis, у самого где-то прототип валяется (выкинут за практической малопригодностью).

Не знал, что code contracts такое умеет. Да, конечно, выносить в классы-хелперы нужно в случае если есть потенциальный реюз. Если реюза нет — незачем плодить хелперы.
Re[47]: Императивная парадигма
От: Sinix  
Дата: 24.07.11 10:11
Оценка:
Здравствуйте, samius, Вы писали:

S>Не знал, что code contracts такое умеет.

Уппс, они и не умеют

This attribute is not enforced by the current analysis tools; you should use this attribute only if you are sure that the methods are pure.


Впрочем, кто знает, что будет в будущем? Поддержку immutable вон почти добавили.

О, нашёл! Намекают, что могут добавить:

Furthermore, in the future, we may provide purity checkers that ascertain that a method declared as Pure actually is pure.


Ну а пока — только правила для code analysis. Сорри, соврал ненамеренно

S>Да, конечно, выносить в классы-хелперы нужно в случае если есть потенциальный реюз. Если реюза нет — незачем плодить хелперы.

Согласен
Re[42]: Императивная парадигма
От: Undying Россия  
Дата: 25.07.11 04:25
Оценка: +1
Здравствуйте, Sinix, Вы писали:

S>Неа. Для традиционного подхода достаточно одного virtual Draw(), т.к все данные уже доступны из this, для "свободных" методов нам придётся нагрузить API методами, отражающими внутренние детали реализации.


В этом Draw() не будет же тысяч строк? Вместо этого будет сотня функций по десятку строк. И многие (если не большинство) из этой сотни функции можно легко записать как свободные, а то и чистые функции. И это даже само по себе заметно упрощает и понимание, и повторное использование кода.

S>Максимум, что удастся — вынести в хелперы элементарщину аля DrawText — см ControlPaint в WinForms. Во что такой подход превращается для сложных контролов, очень легко увидеть на примере ToolStripRenderer — для каждого контрола появляется свой особый api отрисовки. Результат получился прямо противоположный тому, что мы хотели изначально


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

U>>Как минимум тем, что TextBoxHelpers.Measure гарантирует, что пользуется только публичным интерфейсом textBox'а.

S>Угу. Придётся или расширять public api методами, нужными только для measure, или прятать их в internal.

Зачем? Достаточно нужные приватные поля textBox'а передать в качестве аргументов.
Re[43]: Императивная парадигма
От: Sinix  
Дата: 25.07.11 04:40
Оценка:
Здравствуйте, Undying, Вы писали:

U>В этом Draw() не будет же тысяч строк? Вместо этого будет сотня функций по десятку строк. И многие (если не большинство) из этой сотни функции можно легко записать как свободные, а то и чистые функции. И это даже само по себе заметно упрощает и понимание, и повторное использование кода.

Они не будут "свободными", они будут принадлежать или drawing context, или control context. От того, что мы заменим this явной передачей параметра ничего принципиально не изменится.

U>Проблемой являются только те преобразования, которые изменяют множество разнородных сущностей.

+1. Грабля — такие функции могут попасться на самых разных уровнях, причём всегда внезапно. Я не теоретизирую, это одна из основных проблем с построением work tree/проектированием anemic-фреймворков, с чем я сейчас плотно работаю.

U>>>Как минимум тем, что TextBoxHelpers.Measure гарантирует, что пользуется только публичным интерфейсом textBox'а.

S>>Угу. Придётся или расширять public api методами, нужными только для measure, или прятать их в internal.

U>Зачем? Достаточно нужные приватные поля textBox'а передать в качестве аргументов.

Так нам придётся протаскивать по всем стеку хелперов несколько слабосвязанных параметров — начиная с геометрии рамки (она необязательно будет прямоугольной) и заканчивая кистями для рамки/фона. И писать для каждого контрола свою логику по извлечению этих параметров.
Имхо, проще передавать рендереру shape с уже настроенными параметрами. Что для текстбокса, что для комбобокса это будет
<Border x:Name="Border" BorderThickness="{TemplateBinding BorderThickness}"
  CornerRadius="1" Opacity="1"
  Background="{TemplateBinding Background}"
  BorderBrush="{TemplateBinding BorderBrush}">
<!-- ... -->
</Border>
Re[45]: Императивная парадигма
От: Undying Россия  
Дата: 25.07.11 04:50
Оценка:
Здравствуйте, samius, Вы писали:

S>Т.е. по твоей версии "чистоты", Enumerable.Where — чистая?


Да, конечно.

S>>>

S>>>Свободные бизнес-функции много выше уровнем, нежели linq.

S>Соответствующее этому определению определение колеса выглядело бы так: Колеса автобуса много выше, нежели колеса самоката. Извини, я не посчитал это за определение.
S>Да и это определение противоречит определению (1), в котором о "бизнес"-е не было ни слова.

Так это не определение, а утверждение. И твоя аналогия верна, если из всей совокупности колес выделить колеса автобусов (свободные бизнес-функции), то они будут выше, чем колеса самокатов (свободные линк-функции).

U>>А выделенное ты не заметил? Функции linq это свободные функции, но это низкоуровневые кирпичики, свободные бизнес-функции могут быть намного выше уровнем, чем linq-функции.

S>Опять же, могут быть, а могут и не быть...

Естественно, т.к. уровень свободных бизнес-функций определяется уровнем бизнес-преобразований. Если бизнес-преобразование очень примитивное, то и бизнес-функция будет примитивной и сравнимой по уровню с linq-функциями.

U>>Что такое вывод рамки textBox'а? Это преобразование пикселей экрана. Можем ли мы его оформить в качестве свободной функции? Очевидно, да.

S>Очевидно, что не очевидно. Согласно твоему определению (1) функция преобразования пикселей экрана свободной в общем случае не является, т.к. ее результат зависит не только от аргументов, а еще и от настроек винды, GDI и т.п.

Мы эти настройки как параметры функции передали? Передали в виде graphics, поэтому эта функция свободная.

S>Вот тут-то и подвох. На самом низком уровне ты можешь использовать чистые функции. Уровнем выше, там где надо заюзать Add, твое правило уже неприменимо. Т.е. говоря о крутоте "свободных бизнес-функций высокого уровня", не надо забывать, что их крутота заканчивается при первом изменении чего-либо, т.е. повышать бесконечно уровень использования таких функций, оставаясь в рамках ИП, невозможно. Т.е. если ты даже сделаешь это и избавишься от сайд-эффектов и недетерминированности на любом уровне, то ты получишь функциональную программу.


Во-первых, многие преобразования весьма высокого уровня могут быть чистыми.
Во-вторых, для простоты понимания и использования формальная чистота вовсе не обязательна. Например, функция DrawTextCell(graphics, cellRectangle, ...) чистой не является, но хоть у нас и нет гарантий, но есть уверенность, что эта функция изменяет только заданный прямоугольник в переданной области вывода и ничего больше. Соответственно хотя эта функция и не является чистой, ее понимание и использование практически столь же просто.

Проблемой являются только те преобразования, которые изменяют множество разнородных сущностей. Соответственно эта разнородность мешает и дать хорошее название функции, и сгруппировать изменяемые сущности в какую-то дополнительную сущность. В этом случае, да, попытка записать преобразование как свободную функцию ничего не дает, поэтому это по сути единственный случай, когда я использую приватные функции класса. Но таких преобразований по сравнению с общим количеством используемых в программе преобразований немного.
Re[46]: Императивная парадигма
От: samius Япония http://sams-tricks.blogspot.com
Дата: 25.07.11 06:38
Оценка:
Здравствуйте, Undying, Вы писали:

U>Здравствуйте, samius, Вы писали:


S>>Т.е. по твоей версии "чистоты", Enumerable.Where — чистая?

U>Да, конечно.
Приму к сведению

U>Так это не определение, а утверждение. И твоя аналогия верна, если из всей совокупности колес выделить колеса автобусов (свободные бизнес-функции), то они будут выше, чем колеса самокатов (свободные линк-функции).

Меня смутило то что ты написал что это было определение.

U>Естественно, т.к. уровень свободных бизнес-функций определяется уровнем бизнес-преобразований. Если бизнес-преобразование очень примитивное, то и бизнес-функция будет примитивной и сравнимой по уровню с linq-функциями.

Уровень linq-функций тоже определяется уровнем бизнес-преобразований, которые их используют.

U>>>Что такое вывод рамки textBox'а? Это преобразование пикселей экрана. Можем ли мы его оформить в качестве свободной функции? Очевидно, да.

S>>Очевидно, что не очевидно. Согласно твоему определению (1) функция преобразования пикселей экрана свободной в общем случае не является, т.к. ее результат зависит не только от аргументов, а еще и от настроек винды, GDI и т.п.

U>Мы эти настройки как параметры функции передали? Передали в виде graphics, поэтому эта функция свободная.

А если мы в виде строки передадим функции настройки, которые лежат в файле на веб сервисе, эта функция будет свободной? Где грань собственно?

S>>Вот тут-то и подвох. На самом низком уровне ты можешь использовать чистые функции. Уровнем выше, там где надо заюзать Add, твое правило уже неприменимо. Т.е. говоря о крутоте "свободных бизнес-функций высокого уровня", не надо забывать, что их крутота заканчивается при первом изменении чего-либо, т.е. повышать бесконечно уровень использования таких функций, оставаясь в рамках ИП, невозможно. Т.е. если ты даже сделаешь это и избавишься от сайд-эффектов и недетерминированности на любом уровне, то ты получишь функциональную программу.


U>Во-первых, многие преобразования весьма высокого уровня могут быть чистыми.

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

U>Во-вторых, для простоты понимания и использования формальная чистота вовсе не обязательна. Например, функция DrawTextCell(graphics, cellRectangle, ...) чистой не является, но хоть у нас и нет гарантий, но есть уверенность, что эта функция изменяет только заданный прямоугольник в переданной области вывода и ничего больше. Соответственно хотя эта функция и не является чистой, ее понимание и использование практически столь же просто.

Соответственно ты просто приходишь к классическому ExtractMethod, который не требует от выделяемой функции чистоты.

U>Проблемой являются только те преобразования, которые изменяют множество разнородных сущностей. Соответственно эта разнородность мешает и дать хорошее название функции, и сгруппировать изменяемые сущности в какую-то дополнительную сущность. В этом случае, да, попытка записать преобразование как свободную функцию ничего не дает, поэтому это по сути единственный случай, когда я использую приватные функции класса.

Ты приватные противопоставляешь свободным? В твоем определении ничего не было о модификаторах видимости.

U> Но таких преобразований по сравнению с общим количеством используемых в программе преобразований немного.

В таком случае твою программу следует относить больше к ФП, чем к ИП.
А как у тебя обстоят дела с вводом-выводом? Он в твоей трактовке тоже чистый, либо его у тебя немного?
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.