Здравствуйте, Ziaw, Вы писали:
Z>В описываемом коде явные проблемы с именованием переменных и/или методов/выражений с помощью которых эти переменные инициализируются. Можно пример кода, для понимания смысла которого важно знание типа какой-либо переменной?
string GetNumberAbonent(AspidContext context, ObjectPropertyBox propertyBox, PassportBox passport, ResultBox3 resultBox, int objId)
{
if (propertyBox == null || passport == null)
return string.Empty;
var objectKind = ObjectExtendedProperty.ObjectKind.FindValue(propertyBox, objId);
var relationName = string.Empty;
if (objectKind.CompareTo("ПТР") == 0)
relationName = "ЦТП - Дом";
else if (objectKind.CompareTo("УУ") == 0)
relationName = "ЦТП - Домовой узел учета";
else if (resultBox != null)
{
var value = new Alias(objectId, "ObjectName").GetValue(resultBox);
if (value != null)
return value.ToString();
}
var links = Passport2.Подключенные_Объекты.FindValue(passport, objId);
var parentLink = links
.FirstOrDefault(link => link.ObjectRelTypeName.CompareTo(relationName) == 0);
if (parentLink == null || parentLink.LinkObjectIds.Length == 0)
return string.Empty;
var parentId = parentLink.LinkObjectIds[0];
var parentProperty = AspidDataModelHlp.GetPropertiesByObjects(context, new[] { parentId },
ObjectExtendedProperty.ObjectName);
return ObjectExtendedProperty.ObjectName.FindValue(parentProperty, parentId);
}
Re[7]: LINQ как шаг к функциональному программированию
В понимании указанного кода реальной проблемой является то, что не ясна суть используемых объектов и общая задача. А как раз var-ы лично мне нисколько не мешают (даже без наличия подсказок от IDE).
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[7]: LINQ как шаг к функциональному программированию
Здравствуйте, VladD2, Вы писали:
VD>Что нормально? Что делать если мне нужно выбрать не объект, а две его колонки?
Тогда все плохо. Никакой типизации и боксинг вдобавок.
var results = session.CreateQuery("select s.Id, s.Name from Supplier s").List<object[]>();
В простейшем запросе поможет linq2nhibernate:
var results = from s in session.Linq<Supplier>() select new { s.Id, s.Name };
В более менее сложных запросах только HQL и работа с row в виде object[]. Можно немного припудрить конечно, но по сути грустно.
var results = session
.CreateQuery("select s.Id, s.Name from Supplier s")
.List<object[]>.Select(s => new { (long)s.Id, (string)s.Name} );
Вообще я не заявлял, что все хорошо в NH. Но приводить в качестве примера код на яве, где выборка идет с помощью голого SQL и возвращается нетипизированый список слегка некорректно.
Здравствуйте, VladD2, Вы писали:
VD>Переменные уровня класса — это наверное поля. Каким боком к ним вообще var относится? VD>Их тип конечно может быть не очевиден (если названия плохие). Но он так же будет не очевиден и без вар. \
Поэтому в шарпе 2.0 для определения типа полей класса приходилось пользоваться intellicence. var же вынуждает пользоваться intellicence и для определения типов локальных переменных тоже, т.е. intellicence приходиться использовать чаще.
VD>У тебя тоже спрошу... А тебе не сильно мешает вывод типов в параметрах функций и алгоритм перегрузки? VD>Скажем, код типа: VD>
VD>f(x);
VD>
VD>ровным счетом ничего не говорит ни о "f", ни о "x".
В сложных случаях мешает сильно. Такой код читабелен:
new SimpleColumn("Логин").WithCharWidth(16).WithFontBold(true).WithBackColor(Color.MistyRose).WithForeColor(Color.Black).WithFrozenColumn(true);
А вот такой, когда у SimpleColumn двадцать пять перегрузок конструктора практически нет:
new SimpleColumn("Логин", 16, true, Color.MistyRose, Color.Black, true);
VD>Ну, где ты видел код в котором для его понимания приходится наводить курсор на все переменные? VD>У переменных ведь есть имена. И их между прочим заводят чтобы использовать в дальнейшем. А из этого использования и так ясно что это за переменная.
Имя переменной присваивается из соображений бизнес логики и обычно никак не связано с типом переменной.
VD>Знаешь, я иногда не могу понять код в котором все типы очевидны как дважды два. Только отладка дает полное (и то не всегда) понимание. Ты наверно гений, раз можешь просто из аннотаций типов понять всю семантику кода.
Я утверждал, что знание типов упрощает понимание кода. Я не утверждал, что знание типов дает полное понимание кода.
VD>Уважаемый, ты похож на старую бабку бурчащую на девочку в мини-юбке показываемую по телевизору.
Ты на личности переходишь из желания самоутвердиться или по каким-то другим соображения? Вроде в твоем возрасте этим уже поздновато заниматься.
Re[10]: LINQ как шаг к функциональному программированию
Здравствуйте, elmal, Вы писали:
E>Здравствуйте, VladD2, Вы писали:
VD>>Можно ссылку на сообщение из форума где наличие var-ов мешало бы пониманию кода?
сvar result = ... E>Да, я прекрасно, если заострю внимание, пойму о чем речь. Но беглым взглядом уже сложнее читать, чем IEnumerable<string> result.
А ничего, что в некоторых местах в угловых скобках придется написать тонну жути, а в некоторых вообще нельзя будет ничего написать, так как тип будет анонимным?
Научись мыслить бастрактно. Если у тебя есть переменная проинициализированная значением возвращенным функций Where или Select, то значит, что это последовательность. Тип элемента ты можешь понять из кода запроса или из его последующей обработки.
В общем, читай код целиком и не обращай внимания на не существенные для его понимания детали.
E> В любом случае result неудачное имя для переменной. Ладно, на деле, я согласен, что если я заменю все свои аннотации типов на var я почти ничего не потеряю, так как у меня имя переменной отражает тип. И если уж будут сторонники var, я в коде не потеряюсь, при условии что переменные будут называться так, чтоб я мог понять что это такое.
Так и есть. Осмысленное имя в сто раз лучше точного типа. Но это примеры. И дать осмысленные имена для их возвращаемых значений практически невозможно. Примеры демонстрируют то, что должны демонстрировать и, на мой взгляд, достигают своей цели. Если это не так, то просьба указать на конкретный пример.
VD>>И еще один вопрос. А почему ты не протестуешь против перегрузки и вывода типов параметров? Они ведь точно так же скрывают информацию о типах выражений и функций. E>Причина проста. Если мне понадобится узнать как именно работает метод, мне в любом случае потребуется лезть в его код, то есть пользоваться ИДЕ.
Нет, нет, нет... Так дело не пойдет!
Ты даже не можешь знать, что за метод ты вызвал, так как при его выборе компилятор пользуется выводом типов и весьма не тривиальным алгоритмом разрешения перегружки. Он может выбрать один из 100 методов!
Честный ответ на этот вопрос и является ключом к пониманию того почему можно жить без явных аннотаций типов. E>Как именно он работает чаще всего знать не надо, надо чтоб у него было нормальное имя.
Именно! Но не только. Не важно не только "как работает метод", но и что это за метод. Важно только, чтобы сочетание объект.Метод(параметры) объясняли тебе что же происходит. По этому очень важны осмысленные имена методов и переменных. Если имена осмысленные и описывают (в купе) происходящее, то мы на весьма высоком уровне абстракции может определить, что же происходит. Ну, а если нам нужны детали, то одними аннотациями типов переменных не отделаешся и потребляется хорошая IDE с навигацией.
E>А вот типы данных, которыми я оперирую, мне более интересны в большинстве случаев (есть допустим переменная number — число. А числа бывают разные, комплексные, целые, беззнаковые, с фиксированной точностью, с неограниченной точностью — и про то, каким числом ты оперируешь очень полезно всегда помнить, так как есть тонкости. Если я тонкости не знаю, я могу про это забыть и допустить ошибку. Вероятность того, что я при беглом просмотре найду ошибку в чужом коде гораздо выше, если я вижу тип).
На самом деле совершенно не важно каким числом ты оперируешь. Ну, или почти никогда не важно. Ты оперируешь абстрактным числ и тебе требуется конкретный результат. Если результат достигается, то детали не важны. Если же тонкости реально важны, то никто не запрещает описать их явно. Просто не надо все доводить до крайностей.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[10]: LINQ как шаг к функциональному программированию
Здравствуйте, Undying, Вы писали:
U>Поэтому в шарпе 2.0 для определения типа полей класса приходилось пользоваться intellicence. var же вынуждает пользоваться intellicence и для определения типов локальных переменных тоже, т.е. intellicence приходиться использовать чаще.
С переходом на var я не то, что не стал чаще обращаться к IntelliSense, а совсем наоборот! Ведь порой не сразу вспомнишь, какой тип функция возвращает, надо юзать IntelliSense. Теперь я написал var и всё. Когда буду использовать переменную, список свойств и методов все-равно "выпадет" после нажатия точки. Видимо правильно написал nikov: "это дело привычки". Я сейчас спокойно часто юзаю var, никакую читабельность он не уменьшает. Скорее наоборот, повышает, убирая чехарду из типов, а если уж там generic'и так совсем щастье
Re[6]: LINQ как шаг к функциональному программированию
Здравствуйте, elmal, Вы писали:
E>Это я прекрасно знаю. Но ... код визуально выглядит очень похоже на языки с динамической типизацией. И если распечатать код чтоб почитать перед сном — без поддержки студии понимать его будет значительно сложнее.
В Erlang'е даже var нету .
На самом деле, когда читаешь код, то часто все равно какого типа переменная, ибо не важно знать ее "внутренности". Когда же дело доходит до внутренностей, то все равно приходится часто "идти" в определение типа. Просто в одном случает — это class (или подобное), а в другом — функция. Отсутствие имен типов стимулирует людей задумываться над тем, что их код должен быть читабельным и сопровождаемым.
Re[10]: LINQ как шаг к функциональному программированию
Здравствуйте, Undying, Вы писали:
U>Поэтому в шарпе 2.0 для определения типа полей класса приходилось пользоваться intellicence. var же вынуждает пользоваться intellicence и для определения типов локальных переменных тоже, т.е. intellicence приходиться использовать чаще.
И что в этом плохого? Не уж-то лучше венгерку использовать или захламлять код тем, что не интересно 99% времени?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[8]: LINQ как шаг к функциональному программированию
Здравствуйте, Ziaw, Вы писали:
Z>Вообще я не заявлял, что все хорошо в NH.
Я понимаю. И первое что хочется сказать — спасибо за консультацию.
Я не использую Гибернэйт по разным причинам (первая из которых — он мне не нужен). По сему не могу привести корректных примеров. Но интуитивно понимаю, что выдвигаемые моим оппонентом аргументы высасоны из пальца. Твои слова это как раз подтверждают.
Z>Но приводить в качестве примера код на яве, где выборка идет с помощью голого SQL и возвращается нетипизированый список слегка некорректно.
Я привел пример который попался первым в Гугле.
Речь то не об Яве или дотнете. Речь о том, что совершенно бессмысленно описывать типы колонок. Они и так выводятся. Важно чтобы мы могли использовать выведенную информацию для контроля качества кода и для ускорения своей работы.
А пример мне этот был нужен чтобы продемонстрировать, то что и в Гибернэйтовском HQL типы колонок возвращаемого результирующего набора не описываются явно. Ты это и продемонстрировал.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: LINQ как шаг к функциональному программированию
Здравствуйте, eao197, Вы писали:
E>Если что-то может быть истолковано неправильно, это будет истолковано неправильно.
E>Мой поинт был в том, что выражение: E>
E>if (i != array1.Length - 1)
E>
E>гораздо сложнее, чем: E>
E>if (i != 0)
E>
E>Поэтому, если "императивный программист" выбирает сложные пути даже в простых программах, то точно так же он будет выбирать сложные пути и в функциональных программах.
Малаец. Теперь перечитай свои слова про неверность истолковывания несколько раз и подумай над тем зачем ты сделал исходное замечание. Ведь мой "поинт" был в том, что императивный программист напишет цикла с подробным описанием того как он будет конкатенировать строку, а не с описанием того, что он хочет получить в итоге. Ты же влез и совершенно не в кассу попытался перевести разговор в русло обсуждения деталей императивной реализации. В итоге ты совершенно заслужено получил упрек в ее неоптимальности. И действительно, если рассуждать об оптималности и ясности, то вариант который привел Andrey Gliznetsov ближе всего к тому что написал бы хороший императивщик. Вот только разговор то не о том был. И все эти частности реализации просто не важны.
Так чего лезть то с замечаниями не по делу?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[9]: LINQ как шаг к функциональному программированию
Здравствуйте, VladD2, Вы писали:
VD>А пример мне этот был нужен чтобы продемонстрировать, то что и в Гибернэйтовском HQL типы колонок возвращаемого результирующего набора не описываются явно. Ты это и продемонстрировал.
Supplier как раз тут и является типом. А когда приходится возвращать часть значений, приходится создавать DTO, в конструктор которого передаются нужные параметры, это имхо лучше чем работать с результатом object[] и кастить к нужным типам.
Re[10]: LINQ как шаг к функциональному программированию
Здравствуйте, elmal, Вы писали:
VD>>А пример мне этот был нужен чтобы продемонстрировать, то что и в Гибернэйтовском HQL типы колонок возвращаемого результирующего набора не описываются явно. Ты это и продемонстрировал. E>Supplier как раз тут и является типом.
Это тип объекта. Если ты его будешь возращать, то ты так же сможешь описать его (если захочешь). А когда речь идет о паре-тройке колонок, то почему-то описаний уже не видать.
E> А когда приходится возвращать часть значений, приходится создавать DTO, в конструктор которого передаются нужные параметры, это имхо лучше чем работать с результатом object[] и кастить к нужным типам.
По любому при передаче чего-то в конструктор ты не указываешь типы явно. Так что подтверждается тезис о не продуктивности данного процесса.
Что до object[], то конечно работать с типизированными значениями надежнее и проще (для статически-типизированного языка). Но этого никто и не оспаривал. Оспаривалось утверждение о том, что все и всегда нужно аннотировать типами.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[10]: LINQ как шаг к функциональному программированию
Плохой дизайн, как минимум нарушен SRP. Вообще такие конструкторы имеют смысл только для immutable классов. В таком случае я делаю рефакторинг в:
new SimpleColumn("Логин",
new FontStyle(16, FontDecoration.Bold, Color.Black),
new BackgroundStyle(Color.Black),
ColumnType.Frozen);
U>Имя переменной присваивается из соображений бизнес логики и обычно никак не связано с типом переменной.
Сравни:
Link first = GetFirstLink();
// полэкрана кода
Console.WriteLine(first.Length); // здесь мы должны пробежаться глазами вверх и узнать что у нас в переменной first
var firstLink = GetFirstLink(); // здесь мы без типа знаем, что это Link
// полэкрана кода
Console.WriteLine(firstLink.Length); // здесь мы легко понимаем, что происходит даже не зная тип переменной
U>Я утверждал, что знание типов упрощает понимание кода. Я не утверждал, что знание типов дает полное понимание кода.
А я утверждаю, что зачастую усложняет. Приходится невольно думать о том, что означают все эти типы, хотя это далеко не всегда важно.
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[11]: LINQ как шаг к функциональному программированию
Здравствуйте, MxKazan, Вы писали:
MK>С переходом на var я не то, что не стал чаще обращаться к IntelliSense, а совсем наоборот! Ведь порой не сразу вспомнишь, какой тип функция возвращает, надо юзать IntelliSense. Теперь я написал var и всё. Когда буду использовать переменную, список свойств и методов все-равно "выпадет" после нажатия точки. Видимо правильно написал nikov: "это дело привычки". Я сейчас спокойно часто юзаю var, никакую читабельность он не уменьшает.
Уточню:
var же вынуждает пользоваться intellicence при чтении кода и для определения типов локальных переменных тоже, т.е. intellicence приходиться использовать чаще.
Запись кода меня мало волнует, т.к. чтение кода занимает куда больше времени.
Re[6]: LINQ как шаг к функциональному программированию
Здравствуйте, VladD2, Вы писали:
U>>Т.к. в C# 2.0 тип переменных всегда писался слева и можно было всегда смотреть влево, а теперь иногда пишется слева, а иногда справа.
VD>Чушь полнейшая. Вот тебе код на C# 1.0: VD>X(new Y());
В этом коде есть объявление переменной?
Re[12]: LINQ как шаг к функциональному программированию
Здравствуйте, Undying, Вы писали:
U>var же вынуждает пользоваться intellicence при чтении кода и для определения типов локальных переменных тоже, т.е. intellicence приходиться использовать чаще.
Да, да. И это тоже при-выч-ка. Ну не можешь без точного типа и всё тут. А нужно просто расслабиться и получать удовольствие Просто попробуй не замечать var — ну есть переменная и Слава Богу! Со временем, привычка "искать тип" уйдет и var начнет нравицца
P.S. intellisense
Re[11]: LINQ как шаг к функциональному программированию
И с чего ты взял, что у SimpleColumn есть поля CharWidth, FontBold и т.д? Там внутри вообще Dictionary<string, ColumnExtension>, в который все настройки и записываются.
Z>Плохой дизайн, как минимум нарушен SRP. Вообще такие конструкторы имеют смысл только для immutable классов. В таком случае я делаю рефакторинг в: Z>
Z>new SimpleColumn("Логин",
Z> new FontStyle(16, FontDecoration.Bold, Color.Black),
Z> new BackgroundStyle(Color.Black),
Z> ColumnType.Frozen);
Z>
И что мне теперь делать, если я не хочу указывать размер шрифта, но хочу указать, что он жирный? Что делать, если мне понадобилось поддержать новую настройку, например, Italic? Изменять FontStyle? А если у меня доступа к его коду нет? И какова цена если я его нечайно при изменении поломаю? Или завтра ячейку двумя шрифтами нужно будет отрисовывать и что тогда делать? Добавлять класс AdditionalFontStyle полностью идентичный FontStyle?
Если у нас есть набор настроек, которые пользователь может выбирать произвольным образом, то подход с конструктором не работает. Даже если настроек всего лишь 10, то нужно написать всего-то штук 50 конструкторов. Это, во-первых, малость трудоемко, а, во-вторых, даже если не полениться и заюзать какую-нибудь кодогенерацию, то все равно очень плохо читаемо.
Z>
Z>var firstLink = GetFirstLink(); // здесь мы без типа знаем, что это Link
Z>// полэкрана кода
Z>Console.WriteLine(firstLink.Length); // здесь мы легко понимаем, что происходит даже не зная тип переменной
Z>
Имя переменной полностью или частично содержит имя класса только в одном случае, когда это узкоспециализированный класс, заточенный под конкретную задачу/сущность бизнес-логики. Как только класс становиться мало-мальски универсальным, имя класса из имен переменных исчезает.