Здравствуйте, Undying, Вы писали:
U>И с чего ты взял, что у SimpleColumn есть поля CharWidth, FontBold и т.д? Там внутри вообще Dictionary<string, ColumnExtension>, в который все настройки и записываются.
Предположил нормальный дизайн класса. Какой резон хранить настройки в словаре, если все равно они есть в контракте (методы WithBlaBla)?
Z>>Плохой дизайн, как минимум нарушен SRP. Вообще такие конструкторы имеют смысл только для immutable классов. В таком случае я делаю рефакторинг в:
U>И что мне теперь делать, если я не хочу указывать размер шрифта, но хочу указать, что он жирный? Что делать, если мне понадобилось поддержать новую настройку, например, Italic? Изменять FontStyle? А если у меня доступа к его коду нет? И какова цена если я его нечайно при изменении поломаю? Или завтра ячейку двумя шрифтами нужно будет отрисовывать и что тогда делать? Добавлять класс AdditionalFontStyle полностью идентичный FontStyle?
U>Если у нас есть набор настроек, которые пользователь может выбирать произвольным образом, то подход с конструктором не работает. Даже если настроек всего лишь 10, то нужно написать всего-то штук 50 конструкторов. Это, во-первых, малость трудоемко, а, во-вторых, даже если не полениться и заюзать какую-нибудь кодогенерацию, то все равно очень плохо читаемо.
Остается понять, зачем делать такой класс immutable. Если его не делать таковым, смысл кучи конструкторов ускользает.
U>Имя переменной полностью или частично содержит имя класса только в одном случае, когда это узкоспециализированный класс, заточенный под конкретную задачу/сущность бизнес-логики. Как только класс становиться мало-мальски универсальным, имя класса из имен переменных исчезает.
Я не встречал ни одного маломальски универсального класса. Каждый класс предназначен для выполнения какой-то своей задачи (SRP). Хорошая практика отражать это в названии класса. Хорошая практика также называть переменную содержащую экземпляр этого класса в соответствии с задачей которую он выполняет. А если мы можем догадаться о роли объекта, смысл вызовов его методов становится вполне понятен. Нам не важен конкретный тип переменной. Нам важен лишь смысл вызовов методов, его можно понять не зная конкретного типа.
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[10]: LINQ как шаг к функциональному программированию OFF-
Здравствуйте, Ziaw, Вы писали:
U>>Я утверждал, что знание типов упрощает понимание кода. Я не утверждал, что знание типов дает полное понимание кода.
Z>А я утверждаю, что зачастую усложняет. Приходится невольно думать о том, что означают все эти типы, хотя это далеко не всегда важно.
Обычно упрощает. Человеческое мышление же заточено на оперирование типами объектов, а не экземплярами объектов. Ведь большинство существительных в человеческих языках обозначают типы (стол, человек, собака), а экземпляр обозначают только имена собственные (Петя, Шарик), которые в основном используются в хорошо знакомом контексте.
Re[12]: LINQ как шаг к функциональному программированию
Здравствуйте, Undying, Вы писали:
U>Обычно упрощает. Человеческое мышление же заточено на оперирование типами объектов, а не экземплярами объектов. Ведь большинство существительных в человеческих языках обозначают типы (стол, человек, собака), а экземпляр обозначают только имена собственные (Петя, Шарик), которые в основном используются в хорошо знакомом контексте.
Отличная аналогия, в предложении "Собака Шарик виляет хвостом" слово собака несет избыточную информацию. Человек Петя устроился на работу .
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[13]: LINQ как шаг к функциональному программированию
Здравствуйте, Ziaw, Вы писали:
Z>Предположил нормальный дизайн класса. Какой резон хранить настройки в словаре, если все равно они есть в контракте (методы WithBlaBla)?
Тот резон, что WithBlaBla это Extension, который может добавлять кто угодно и откуда угодно, не рискуя ничего поломать. А при добавлении поля надо каждый раз SimpleColumn изменять.
U>>Если у нас есть набор настроек, которые пользователь может выбирать произвольным образом, то подход с конструктором не работает. Даже если настроек всего лишь 10, то нужно написать всего-то штук 50 конструкторов. Это, во-первых, малость трудоемко, а, во-вторых, даже если не полениться и заюзать какую-нибудь кодогенерацию, то все равно очень плохо читаемо.
Z>Остается понять, зачем делать такой класс immutable. Если его не делать таковым, смысл кучи конструкторов ускользает.
Вообще-то immutable код намного проще читать и в нем гораздо труднее сделать ошибку. Но в данном контексте это не важно, mutable класс у тебя как выглядеть будет? Так что ли?
Z>Я не встречал ни одного маломальски универсального класса.
Ты не встречал классы List, object, string?
Z>Каждый класс предназначен для выполнения какой-то своей задачи (SRP). Хорошая практика отражать это в названии класса. Хорошая практика также называть переменную содержащую экземпляр этого класса в соответствии с задачей которую он выполняет.
Естественно, поэтому мы называем коллекцию linkedElements, а не linkedElementList, и соответственно вывести из названия переменной тип не можем.
Z>А если мы можем догадаться о роли объекта, смысл вызовов его методов становится вполне понятен. Нам не важен конкретный тип переменной. Нам важен лишь смысл вызовов методов, его можно понять не зная конкретного типа.
Понять можно, но сделать это значительно сложнее.
Re[13]: LINQ как шаг к функциональному программированию
Здравствуйте, Ziaw, Вы писали:
U>>Обычно упрощает. Человеческое мышление же заточено на оперирование типами объектов, а не экземплярами объектов. Ведь большинство существительных в человеческих языках обозначают типы (стол, человек, собака), а экземпляр обозначают только имена собственные (Петя, Шарик), которые в основном используются в хорошо знакомом контексте.
Z>Отличная аналогия, в предложении "Собака Шарик виляет хвостом" слово собака несет избыточную информацию. Человек Петя устроился на работу .
Есть два варианта:
1) Шарик это собака.
Шарик виляет хвостом.
2) Шарик виляет хвостом.
Откуда во-втором варианте можно узнать, что Шарик это собака, а не кошка?
Re[13]: LINQ как шаг к функциональному программированию
Здравствуйте, Ziaw, Вы писали:
Z>Отличная аналогия, в предложении "Собака Шарик виляет хвостом" слово собака несет избыточную информацию. Человек Петя устроился на работу .
... << RSDN@Home 1.2.0 alpha 4 rev. 1111 >>
Re[14]: LINQ как шаг к функциональному программированию
Здравствуйте, Undying, Вы писали:
U>Тот резон, что WithBlaBla это Extension, который может добавлять кто угодно и откуда угодно, не рискуя ничего поломать. А при добавлении поля надо каждый раз SimpleColumn изменять.
Это уже не Column тогда, а хранилище кучи свойств, которые он сам использовать не в состоянии. Не могу понять, для чего такое может понадобиться. Используй вместо него Dictionary или пустой наследник от него для типизации. И самое главное: зачем в нем дикие конструкторы???
U>>>Если у нас есть набор настроек, которые пользователь может выбирать произвольным образом, то подход с конструктором не работает. Даже если настроек всего лишь 10, то нужно написать всего-то штук 50 конструкторов. Это, во-первых, малость трудоемко, а, во-вторых, даже если не полениться и заюзать какую-нибудь кодогенерацию, то все равно очень плохо читаемо.
Z>>Остается понять, зачем делать такой класс immutable. Если его не делать таковым, смысл кучи конструкторов ускользает.
U>Вообще-то immutable код намного проще читать и в нем гораздо труднее сделать ошибку. Но в данном контексте это не важно, mutable класс у тебя как выглядеть будет? Так что ли?
U>
SimpleColumn column = new SimpleColumn { Title = "Логин", CharWidth = 12; BackColor = Color.MistyRose };
Z>>Я не встречал ни одного маломальски универсального класса.
U>Ты не встречал классы List, object, string?
в чем универсальность-то?
List: ничуть не универсален, хранит список других объектов. Обычно характеризуется тем, что переменная названа существительным во множественном числе. Вобщем-то также называют экземпляры реализущие ICollection, IEnumerable но для понимания алгоритма это неважно.
object: экземпляры object я встречал только в качестве объектов для синхронизации. Менее универсального класса и придумать сложно.
string: абсолютно конкретный класс, хранит строку. вполне ясное и понятное предназначение.
Z>>Каждый класс предназначен для выполнения какой-то своей задачи (SRP). Хорошая практика отражать это в названии класса. Хорошая практика также называть переменную содержащую экземпляр этого класса в соответствии с задачей которую он выполняет.
U>Естественно, поэтому мы называем коллекцию linkedElements, а не linkedElementList, и соответственно вывести из названия переменной тип не можем.
Странно, а я могу: тип коллекция, если я встречу индекс — я пойму, что она индексирована. Пока не встречу, это не имеет ровно никакого значения для понимания.
U>Понять можно, но сделать это значительно сложнее.
Могу поспорить, что ты не писал и не читал код с варами. Либо качество написанного/прочтенного кода стремится к спагетти.
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[14]: LINQ как шаг к функциональному программированию
Здравствуйте, Undying, Вы писали:
U>Откуда во-втором варианте можно узнать, что Шарик это собака, а не кошка?
Я пока мне не докажут обратного, я буду считать, что Шарик собака. Если я узнаю, что в моей программе кто-то назвал кошку Шариком я буду сильно ругаться, вне зависимости, указал он явно что это кошка или это вывел компилятор.
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[15]: LINQ как шаг к функциональному программированию
Здравствуйте, Ziaw, Вы писали:
Z>Я пока мне не докажут обратного, я буду считать, что Шарик собака. Если я узнаю, что в моей программе кто-то назвал кошку Шариком я буду сильно ругаться, вне зависимости, указал он явно что это кошка или это вывел компилятор.
И толку от твоей ругани, если благодаря ложной уверенности в том, что Шарик это собака ты вчера неправильно понял код и внес ошибку?
Чтение кода в основном производиться по двум причинам:
1) Поиск ошибки.
2) Внесение изменений в код.
При поиске ошибок детали кода нас как раз и интересуют, т.к. причина ошибки, как правило, в деталях и скрывается.
При внесении изменений в код, как правило, принципиальное понимание задачи у нас уже есть. А код мы просматриваем для того, чтобы понять как это принципиальное понимание ложится на имеющееся решение и о каких нюансах мы забыли в своем принципиальном понимании задачи. Соответственно детали кода важны и здесь.
Типы переменных эта деталь кода важная для понимания, без них как производить поиск ошибок, так и понимать нюансы бизнес-логики и/или реализованного решения значительно сложнее.
Re[11]: LINQ как шаг к функциональному программированию OFF-
Такое решение неплохое, но у него есть два недостатка: 1) его нельзя расширить внешним образом, при добавлении нового параметра приходется вносить изменения в SimpleColumn 2) C# не поддерживает опциональные параметры в конструкторах.
Но у него есть недостаток, статический интерфейс класса почему-то нельзя расширять внешним образом, соответственно в общем случае придется плодить GridExtAdditional и т.п. With'ы на Extension в этом смысле лучше, хотя и выглядят чуть тяжеловесней.
Re[16]: LINQ как шаг к функциональному программированию
Здравствуйте, Undying, Вы писали:
U>И толку от твоей ругани, если благодаря ложной уверенности в том, что Шарик это собака ты вчера неправильно понял код и внес ошибку?
Толк как раз есть. Если я не буду ругаться в таких случаях, потом рыбки тоже начнут назваться Шариками, а столы Роликами. Проблемы в таком коде, сам понимаешь, серьезные.
U>Чтение кода в основном производиться по двум причинам:
U>1) Поиск ошибки. U>2) Внесение изменений в код.
U>При поиске ошибок детали кода нас как раз и интересуют, т.к. причина ошибки, как правило, в деталях и скрывается.
Не могу представить себе ошибки в которой важен тип переменной в локальном блоке. Если это конечно не кошка по имени Шарик, для борьбы с детскими ошибками лучше именно ругаться, а не выбрасывать фичу компилятора.
U>При внесении изменений в код, как правило, принципиальное понимание задачи у нас уже есть. А код мы просматриваем для того, чтобы понять как это принципиальное понимание ложится на имеющееся решение и о каких нюансах мы забыли в своем принципиальном понимании задачи. Соответственно детали кода важны и здесь.
Внесение изменений в нормальный и покрытый тестами код очень простая процедура. Это не требует вдумчивой медитации над кодом и дебага в голове.
U>Типы переменных эта деталь кода важная для понимания, без них как производить поиск ошибок, так и понимать нюансы бизнес-логики и/или реализованного решения значительно сложнее.
Я уже писал про это. Надо учиться писать понятный код, а не воевать с ветряными мельницами.
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[7]: LINQ как шаг к функциональному программированию
Здравствуйте, Undying, Вы писали:
VD>>Чушь полнейшая. Вот тебе код на C# 1.0: VD>>X(new Y());
U>В этом коде есть объявление переменной?
А какая разница есть она или нет? Ты код перестаешь читать если значение прямо в параметр (без переменной) передается?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: LINQ как шаг к функциональному программированию
От:
Аноним
Дата:
17.01.09 08:27
Оценка:
AG>Кроме того за все в этой жизни надо платить, в том числе и за лаконичность LINQ, вот результаты конкатенации массива чисел из 10000 элементов:
AG>Способ: императивный AG>Расход памяти: 1200 kb AG>Время: 1600 ms
Вообще-то, неправильно выделять этот способ как именно императивный. Это только один из множества императивных способов, причем самый наивный и неэффективный.
Re[10]: LINQ как шаг к функциональному программированию
Разумные слова, но какие они имеют отношение к вопросу описания типов переменных?
Это интересные размышления о том как сделать код читабельнее через указания имен параметров или использовании техник заменяющих этот подход. Но типы тут не причем.
Более того — это пример отлично демонстрирует бессмысленность знания типов для понимания кода (в некоторых случаях).
Всмотрись в свой код. Все типы всех параметров ясны как божий день! Но что тебе это дало? Ровным счетом ничего.
А вот имена переменных тебе тут что-то дали бы. Вот только они привели бы к некоторому захламлению кода. Лучше всего в такой ситуации использовать именовыанные параметры. Nemerle и VB их поддерживают. C# к сожалению — нет. Но будет поддерживать в 4-ой версии.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[16]: LINQ как шаг к функциональному программированию
Здравствуйте, Undying, Вы писали:
U>Чтение кода в основном производиться по двум причинам:
U>1) Поиск ошибки. U>2) Внесение изменений в код.
U>При поиске ошибок детали кода нас как раз и интересуют, т.к. причина ошибки, как правило, в деталях и скрывается.
В обоих случаях важна семантика кода. Ее ни типы, ни имена переменных на 100% не описывают. Можно даже утверждать, что сам факт наличия ошибки говорит о неверной семантике. А раз так, то имена могут только сбивать с толку. Ведь ошибка есть. А значит, что любое имя и любой тип прийдется ставить под сомнение.
Не скажу за всех. Но единственный способ поиска и устранения ошибок для меня является изучение его под отладчиком. При этом сначала я пытаюсь выделить минимальный пример кода воспроизводящий ошибку, а потом пытаюсь понять как код обрабатывает входной поток данных. Поняв что делает код я решаю как нужно его изменить, чтобы добиться корректного поведения. Примерно это же я делаю когда хочу внести изменения.
К чему я? Да к тому, что для поиска ошибок нужно использовать тесты и отладчик или хотя бы тесты и консольный вывод (по дедовски, так сказать). При этом информация о всех типах не просто доступна, а доступна в полном объеме. А наличие типов в коде при этом может даже быть вредным, так как код от этого распухает.
U>При внесении изменений в код, как правило, принципиальное понимание задачи у нас уже есть. А код мы просматриваем для того, чтобы понять как это принципиальное понимание ложится на имеющееся решение и о каких нюансах мы забыли в своем принципиальном понимании задачи. Соответственно детали кода важны и здесь.
U>Типы переменных эта деталь кода важная для понимания, без них как производить поиск ошибок, так и понимать нюансы бизнес-логики и/или реализованного решения значительно сложнее.
Типы доступны в отладчике и интеллисенсе. Без оных все равно на 100 понять код нельзя. А раз это так, то зачем цепляться за неполную информацию основную часть времени только засоряющую код?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[17]: LINQ как шаг к функциональному программированию
Здравствуйте, Ziaw, Вы писали:
Z>Внесение изменений в нормальный и покрытый тестами код очень простая процедура. Это не требует вдумчивой медитации над кодом и дебага в голове.
Это ты выдаешь желаемое за действительное. Бывает разный код. Бывают разные ситуации. И бывает, что даже при наличии тучи тестов и очень хорошо описанном коде, внести изменения в него не нарушив его работы не просто.
Если же тестов мало (или вообще нет), код плохо написан, типы и/или их члены имеют плохие названия, код сильно связан, код слишком долго компилируется, имеются зависимости от внешних нестабильных данных и т.п., то внесение изменений может стать просто мучительным.
При этом информация о типах может стать очень полезной информацией. Вот только информации о типах переменных для этого маловато. Тут лучше иметь хороший отладчик позволяющий залезть в любые дебри.
Само собой, что совершенно все равно как при этом объявлены переменные. Важно чтобы отладчик позволял бы их "смотреть".
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: LINQ как шаг к функциональному программированию
Здравствуйте, <Аноним>, Вы писали:
AG>>Кроме того за все в этой жизни надо платить, в том числе и за лаконичность LINQ, вот результаты конкатенации массива чисел из 10000 элементов:
AG>>Способ: императивный AG>>Расход памяти: 1200 kb AG>>Время: 1600 ms
А>Вообще-то, неправильно выделять этот способ как именно императивный. Это только один из множества императивных способов, причем самый наивный и неэффективный.
Это самый императивный из императивных способов
P.S. Под императивным я понимаю: "расскажу-ка я компу как нужно действовать".
Re[8]: LINQ как шаг к функциональному программированию
Здравствуйте, VladD2, Вы писали:
VD>А какая разница есть она или нет? Ты код перестаешь читать если значение прямо в параметр (без переменной) передается?
В шарпе 2.0 есть три варианта объявления переменной:
1) Переменная объявляется по месту использования:
SomeFunction(new SomeClass());
Здесь тип переменной всегда очевиден.
2) Переменная получена из функции по месту использования:
SomeFunction(GetSomeClass());
Здесь взглядом определить тип переменной нельзя, всегда нужно использовать intellisense.
В этом случае, чтобы определить тип someClass всегда нужно посмотреть на левую часть объявления этой переменной.
Если же в коде используются var, то вариант 3 разбивается на три подварианта:
а) Как в шарпе 2.0
б) var + конструктор
var someClass = new SomeClass();
...
SomeFunction(someClass);
Чтобы определить тип someClass теперь нужно смотреть на правую часть объявления, а не на левую как в варианте а.
в) var + вызов функции
var someClass = GetSomeClass();
...
SomeFunction(someClass);
Упс... зря смотрели на объявление переменной, тип взглядом вывести нельзя, надо юзать intellisense.
Т.е. вариантов стало больше, видя код SomeFunction(someClass), мы теперь, чтобы определить тип someClass, в одном случае должны посмотреть в левую часть объявления переменной, в другом — в правую, в третьем — и вовсе воспользоваться intellisense, а, значит, читабельность стала хоть и чуточку, но хуже. А учитывая, что объявлений переменных в коде очень много, эта чуточка суммируется и становится довольно существенной.