Re[10]: Решение проблемы двух ботинок
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 12.01.12 18:06
Оценка:
Здравствуйте, konsoletyper, Вы писали:

K>>> И тут уже вопрос не только о системе типов языка. Например, в том же C# есть нехорошая в этом смысле конструкция as, которую стараются избегать. Готов обсудить конкретные особенности конкретных языков, которые помогают или мешают легче обнаруживать ошибки.

N>>А что в ней не так?
K>В ней — это в конструкции as из C# или в чём-то другом. На всякий случай про C# (хотя это уже везде, где можно, обсуждали).

Моё знание C# недалеко ушло от helloworld.

N>>Да, javascript — кошмарный ужас, причём не только из-за таких примеров. Тут в соседней ветке обсуждалось. Когда "5" + 3 == 53, но "5" — 3 == 2, авторов языка следует изгонять на Лабрадор. В нормальном языке неявные конверсии типов, такие, как между строкой и числом, должны быть запрещены.

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

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

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


Опечатки в локальных переменных ловятся на одном первом проходе теста, неважно, ручного или
автоматизированного.

K>По поводу конверсии. Конверсии число -> строка вполне допустимы.


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

K> Ошибки, которые возникают из-за конверсии, вполне отлавливаются системой типов.


В Javascript? Прц.

N>>Но не только с ним тут грабли. Я сейчас перечитываю "Рефакторинг" Фаулера. Там в начале есть пример ошибки в коде на Java, выловленной только тестом, от неявной конверсии double -> int.

K>Наверное, из double в int. А можно пример?

Основные строки из примера в книге:

int thisAmount = 0;
...
thisAmount += (each_getDaysRented() — 2) * 1.5;

объявление thisAmount должно было быть double вместо int.
И даже warning'а не выдало, насколько я понял автора, хотя в нормальном языке вообще не должно было скомпилироваться, ибо преобразование из плавучего типа в целый должно быть только явным с указанием необходимого действия (round, trunc, floor или ceil, и тех round'ов может быть несколько).

K>>> Этот undefined может очень долго путешествовать по графу объектов, пока, например, кто-нибудь не попытается вызвать у него метод. В Ruby есть похожая штука, хорошо хоть в случае с локальными переменными это побороли.

N>>Жуть.
K>Да-да, это-то как раз и есть жуть, а не какая-нибудь штука вроде положительного и отрицательного нулей или проблем с бесконечностями и NaN.

А при чём тут они? Это специфика предметной области (плавучка сама по себе уже предметная область, хоть и промежуточная), а не тараканы языка.
The God is real, unless declared integer.
Re[11]: Решение проблемы двух ботинок
От: konsoletyper Россия https://github.com/konsoletyper
Дата: 12.01.12 18:50
Оценка:
Здравствуйте, netch80, Вы писали:

N>>>Да, javascript — кошмарный ужас, причём не только из-за таких примеров. Тут в соседней ветке обсуждалось. Когда "5" + 3 == 53, но "5" — 3 == 2, авторов языка следует изгонять на Лабрадор. В нормальном языке неявные конверсии типов, такие, как между строкой и числом, должны быть запрещены.

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

N>Их тут невозможно избежать. Достаточно получить в аргументах или в пришедшем с сети неожиданный тип данных, и проблема будет замаскирована.


Вот-вот. А в Java, например, если это какой-нибудь JAXB, то все "неожиданные типы данных" отловятся автоматом, без лишних проверок в коде (которые вручную можно и забыть проставить).

N>Опечатки в локальных переменных ловятся на одном первом проходе теста, неважно, ручного или

N>автоматизированного.

Кстати, а для динамически типизированных языков бывают code coverage tools? Или проверка того факта, что весь код покрыт тестами, есть только на честном слове?

K>>По поводу конверсии. Конверсии число -> строка вполне допустимы.


N>Нет. Во-первых, они дают такие вот неожиданные эффекты. Во-вторых, число может быть представлено по-разному в разных случаях, и автоматическая конверсия этого не учитывает.


Ну так оно и ясно, что компилятор не телепат и заранее не знает, в каком формате выводить числа. А вот, например, для логгирования это очень удобно. И эффект очень даже предсказуемый: сложили число со строкой, получили строку, ибо неявное преобразование возможно только из числа в строку. Но это только в нормальных языках, где обратного неявного преобразования не существует. А в JavaScript, да, всё очень неожиданно.

K>> Ошибки, которые возникают из-за конверсии, вполне отлавливаются системой типов.


N>В Javascript? Прц.


Так я и высказался по поводу системы типов в контексте защиты статической типизации. В Javascript её нет, потому получаются вот такие вот внезапности. А была бы статическая типизация — проблем не было бы.

N>Основные строки из примера в книге:


N> int thisAmount = 0;

N> ...
N> thisAmount += (each_getDaysRented() — 2) * 1.5;

N>объявление thisAmount должно было быть double вместо int.

N>И даже warning'а не выдало, насколько я понял автора, хотя в нормальном языке вообще не должно было скомпилироваться, ибо преобразование из плавучего типа в целый должно быть только явным с указанием необходимого действия (round, trunc, floor или ceil, и тех round'ов может быть несколько).

Не верю!

K>>Да-да, это-то как раз и есть жуть, а не какая-нибудь штука вроде положительного и отрицательного нулей или проблем с бесконечностями и NaN.


N>А при чём тут они? Это специфика предметной области (плавучка сама по себе уже предметная область, хоть и промежуточная), а не тараканы языка.


А при том, что ругатели JavaScript часто ругают эти моменты, не обращая внимания на большую беду с локальными/глобальными переменными и undefined'ами.
Re[6]: Решение проблемы двух ботинок
От: Undying Россия  
Дата: 13.01.12 10:33
Оценка:
Здравствуйте, DarkGray, Вы писали:

U>>Лучше тот язык, который позволяет записать решение меньшим количеством сущностей. Биты здесь вообще не в тему.


DG>есть два количества сущностей:

DG>количество сущностей в алфавите (в наборе понимаемых сущностей),

Это не сущности, а количество синтаксических конструкций в языке. Речь не о них.

DG>количество символов(сущностей) в записи решения.


Это тоже не то.

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

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

DG>ты сейчас о каком из них?

DG>если минимизировать первое — то лучшим ЯП становится: машина тьюринга, там всего две сущности в алфавите: 0 и 1

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

DG>если минимизировать второе — то лучшим ЯП становится: ЯП с бесконечным алфавитом, когда все программы записываются одним символом из этого алфавита.


Здесь получается одна сущность, но с огромным весом, соответственно вместо упрощения получается усложнение.
Re[7]: Решение проблемы двух ботинок
От: Undying Россия  
Дата: 13.01.12 10:41
Оценка:
U>Естественно когда речь идет о минимуме количества сущностей, то не нужно понимать это как примитивное определение количества. Сущности разного рода могут иметь кардинально отличающийся вес, например, сеттер для объекта с большим временем жизни может быть много дороже десятка геттеров. Соответственно понятие количества включает в себя веса сущностей.

Т.е. количество сущностей измеряется не в штуках, а в неких единицах сложности. Аналогично тому как, к примеру, количество капитала измеряется не в штуках заводов, домов и тапочек, а в деньгах.
Re[7]: Решение проблемы двух ботинок
От: DarkGray Россия http://blog.metatech.ru/post/ogni-razrabotki.aspx
Дата: 13.01.12 20:09
Оценка: +1
U> Первичным является количество логических сущностей,

да, я в целом понимаю о чем ты, и я с этим согласен.

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

1. Должны ли сущности записи совпадать с сущностями логики решения?
2. Должны ли сущности исполнения совпадать с сущностями логики решения?
3. Что такое вес логической сущности? И как его можно измерить или вычислить?
4. Можно ли выделить какие-то базовые сущности? Что это за сущности?
Re[12]: Решение проблемы двух ботинок
От: FR  
Дата: 14.01.12 11:27
Оценка:
Здравствуйте, konsoletyper, Вы писали:

K>Кстати, а для динамически типизированных языков бывают code coverage tools?


Конечно, например для питона http://nedbatchelder.com/code/coverage/

K>Или проверка того факта, что весь код покрыт тестами, есть только на честном слове?


Все вменяемые тестовые системы для того же питона позволяют запускать и проверку покрытия
параллельно с тестами. Тоже и IDE'шки http://pydev.org/manual_adv_coverage.html
Re[8]: Решение проблемы двух ботинок
От: Undying Россия  
Дата: 14.01.12 13:38
Оценка: 1 (1)
Здравствуйте, DarkGray, Вы писали:

DG>1. Должны ли сущности записи совпадать с сущностями логики решения?


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

DG>2. Должны ли сущности исполнения совпадать с сущностями логики решения?


Нужно для удобства отладки.

DG>3. Что такое вес логической сущности? И как его можно измерить или вычислить?


Если подумать, то вовсе не факт, что вес имеет смысл учитывать. Т.к. если смотреть в корень проблемы, то возможно важны как раз штуки, а не веса. Например, почему очень дороги сеттеры? Потому что при традиционном методе программирования информация в программе дублируется множество раз. Возьмем самый примитивный пример. Есть бизнес-объект, его нужно показать пользователю. Мы берем переменную этого объекта и копируем ее, к примеру, в textBox. Т.е. на ровном месте получаем дублирование информации. Соответственно дальше изменение состояние бизнес-объекта (сеттер) должно порождать множество изменений (сеттеров) объектов от него зависящих. А т.к. отслеживание зависимостей это не тривиальная задача, то сложность программы растет лавинообразно, и возникает впечатление, что ничего страшнее сеттеров нет. Хотя на самом деле корень проблемы не в сеттерах, а в дублировании состояния.

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

DG>4. Можно ли выделить какие-то базовые сущности? Что это за сущности?


По привычке я считал, что главное зло это сеттеры и лишние слои абстракции. Но в свете предыдущего пункта сеттеры оказались реабилитированными, а истинным виновником проблемы оказалось дублирование состояния. По поводу лишних слоев абстракции надо подумать, возможно они тоже плохи не сами по себе, а из-за того что нарушают нечто более фундаментальное. Так вроде да, получается, что и лишние слои абстракций плохи тем, что на ровном создают лишнее состояние с неизбежным дублированием состояния логического. Т.е. похоже, что от принципа минимума состояния и нужно плясать.
Re[9]: Решение проблемы двух ботинок
От: DarkGray Россия http://blog.metatech.ru/post/ogni-razrabotki.aspx
Дата: 15.01.12 19:52
Оценка:
DG>>1. Должны ли сущности записи совпадать с сущностями логики решения?

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


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


DG>>2. Должны ли сущности исполнения совпадать с сущностями логики решения?


U>Нужно для удобства отладки.


а для эффективности исполнения?


DG>>3. Что такое вес логической сущности? И как его можно измерить или вычислить?


U> Потому что при традиционном методе программирования информация в программе дублируется множество раз. ... в дублировании состояния.


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

U>Если же мы с помощью автоматических кэшей и LazyMaker'ов ..

U> Соответственно изменение состояния становится тривиальной операцией, не вносящей дополнительной сложности.

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


DG>>4. Можно ли выделить какие-то базовые сущности? Что это за сущности?


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


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

и при оперировании информацией абстракции часто решают задачи уменьшения кол-ва информации, которым приходится оперировать в ряде конкретных задач.
как это измерять?
Re[10]: Решение проблемы двух ботинок
От: Undying Россия  
Дата: 16.01.12 11:59
Оценка:
Здравствуйте, DarkGray, Вы писали:

DG>а наоборот? могут ли сущности записи решения не совпадать с сущностями логики решения и исполнения? и зачем такое бывает необходимо?


Это может быть оправдано в целях оптимизации, при условии, что оптимизация нам важнее удобства программиста.

DG>>>2. Должны ли сущности исполнения совпадать с сущностями логики решения?

U>>Нужно для удобства отладки.
DG>а для эффективности исполнения?

Аналогично первому пункту.

DG>дублирование состояния в любом случае возникает внутри кэшей, резервировании, при использовании распределенной системы и т.д.


Автоматический кэш не дублирует состояние, т.к. внешним образом невозможно добиться, чтобы он начал возвращать неверное состояние.

DG>при большом кол-ве "выходов"(text-box-ы, экраны, подписки других систем и т.д.) появляется задача отслеживания, какие выходы необходимо пересчитать на основе текущих изменений, и эта задачи не тривиальная


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

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


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

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

DG>как это измерять?

Первый вид сложности — это количество сущностей (как хранимых, так и разновидностей).
Второй вид сложности — это количество степеней свободы сущности. Например, readonly объект имеет меньше степеней свободы, чем модифицируемый объект, и соответственно проще.

В некоторых случаях снижение сложности второго рода приводит к увеличению сложности первого рода. Однозначного ответа когда это оправдано нет, надо рассматривать конкретные [группы] случаев.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.