Здравствуйте, Anton Batenev, Вы писали:
c>> Откройте для себя .NET CF и Mono.
AB>Вот тут все про моно да про моно. Но хоть бы кто-нибудь показал мастер-класс на оном, а то складывается впечатление, что его защитники видели его только на картинках, а те, кто его пользовал, молчат, дабы не было стыдно.
Здравствуйте, Anton Batenev, Вы писали:
AB>Здравствуйте, criosray, Вы писали: c>> Откройте для себя .NET CF и Mono. AB>Вот тут все про моно да про моно. Но хоть бы кто-нибудь показал мастер-класс на оном, а то складывается впечатление, что его защитники видели его только на картинках, а те, кто его пользовал, молчат, дабы не было стыдно.
Не, ну если интересно, то можно на официальном сайте глянуть.
Getting Started с разными FAQ и скриншотами. Companies Using Mono рассказывает о реальном использовании Mono. Например, "WikiPedia uses Mono for its search facilities. The indexing and the actual searching is done by Mono-based applications". Вот, кстати, еще интересная новость: "Unity Technologies Implements Award-Winning 3D Game Development System Using Mono".
Я только сразу оговорюсь, что сам на Mono не разрабатываю, т.к. мы пишем только под Windows.
Здравствуйте, criosray, Вы писали:
V>>Не надоело рефлексировать и показывать в очередной раз свой поверхностный взгляд? Все твои вызовы мокков ради ассертов, собственно и сделаны. И хоть они теперь не в фас, а в профиль — они были и есть цель любого автоматического теста (не обязательно юнит...) C>"Все твои вызовы мокков ради ассертов, собственно и сделаны" — это напоминает генератор цепей Маркова. Взять два умных слова, и связать их между собой связующими. Получается билеберда, но звучит вроде как умно для стороннего человека.
C>Так вот, ликбез: мокинг выполняется с целью изолировать тестируемый объект от внешних зависимостей.
Ух ты! А я-то думал, что мокинг нужен для отслеживания последовательности внешних вызовов.
C>Пример мокинга:
C>
C>Что означает, что ожидается, что будет вызван databaseManager.BeginTransaction(), а потом в любом порядке будут вызваны Withdraw и Deposit.
C>Ассерты это всего-лишь предикат, который по-определению всегда true.
C>Assert.Equals(10, someObj.SomeIntProperty); C>Assert.IsTrue(someObj.SomeBoolProperty); C>и т.д. и т.п.
А по-твоему, Expect — это не тот же самый Assert в профиль? Assert — утверждение, Expect — утверждение о некотором ожидаемом событии. Тот же Assert, только специализированный.
C>Ассерты и моки не цель. Это средство и ключевой механизм реализации юнит тестов.
Любое автоматическое тестирование сводится к проверке последовательности утверждений. Иначе оно совсем не нужно. Дальше только вариации способов записи этих утверждений. vdimas прав в том смысле, что если логика достаточно сложная, то и полные тесты достаточно трудно записывать. Вот тебе простейший пример (псевдокод):
{ Тестируемый код }
if (incomingMessage(channel0) is Message1)
sendMessage(channelA, MessageA);
else
{
sendMessage(channelX, MessageX);
sendMessage(channelB, MessageB);
}
{ приблизительный код теста }
when(incomingMessage(channel0) is Message1)
{
check(sentMessage(channelA, MessageA))
}
else
{
check(sentMessage(channelX, MessageX))
check(sentMessage(channelB, MessageB))
}
То есть нужно проверить, что указанные сообщения ушли по заданным каналам, и только после определённого входного сообщения, и только в указанной последовательности, а потом ещё и желательно выдать осмысленное сообщение об ошибке. И получится, что сложность (словарь, длина и т.п.) теста объективно сопоставима со сложностью тестируемой программы, и это даже от языка не зависит. Добавить диагностику — и получится вообще превышение сложности.
Но собственно, я отклонился. Так вот, по сути дела всё, что делает тест — проверяет соответствие программы сложному утверждению, включающему, в том числе, утверждения о последовательности событий. Так что, формально vdimas прав по части assert-ов.
C>При чем тесты ни коим образом не захламляют код. Все тесты находятся в отдельной сборке, которая "видит" (и только она одна) внутренности тестируемых сборок.
Очень рад за вас.
V>>>>У нас в последней системе в центре тупой диспетчер сообщений, и все тупо шлют в систему сообщения, никто ни о ком не знает... что по одиночке, что в любой комбинации прекрасно все тестируется, и произвольные тестовые заглушки прекрасно пишутся с логикой произвольной сложности, которая автомокам и не снилась.
C>>>Перечень того, что не возможно сделать средствами RhinoMocks + xUnit в студию, как говорится. V>>Любую динамическую среду/заглушки, которые генерят переменный по насыщенности траффик или сообщения с разной задержкой и произвольным наполнением. Фишка в том, что реальных задержек-то и нет, текущее время эмулируется, но тестирующая последовательность слишком длинная, чтобы записывать её ручками, она генерируется программой. А таких последовательностей/программ у меня — мама не горюй. C>Еще один ликбез: описанное Вами не является модульными тестами. Это т.н. integration tests.
Это зависит от того, что в данной конфигурации полагается модулем, а что — интеграцией. Поскольку структура любой сложной программы иерархическая, то модуль на одном уровне — это сборная конструкция на другом.
C>При чем ничего невозможного в реализации этого нет — описанное реализуется элементарно в .NET.
А разве кто-то говорил, что такое тестирование невозможно реализовать средствами .Net? Вопрос в автоматической генерации.
V>>Далее, обмен сложными структурами данных заглушки и тестируемого объекта, у объекта приличное пространство состояний, на что заглушка должна грамотно реагировать, т.е. приличная иногда логика на if-ах и case-ах. C>Элементарно средствами RhinoMocks.
И неужто будет проще, чем аналогичная заглушка? Это если учесть, то заглушка реализуется в естественном синтаксисе, а мок — перехватом вызовов. Второе будет почти гарантированно сложнее.
V>>В декларативном синтаксисе мокков это выглядит как удаление гландов через Ж, и чем осмысленнее логика — тем более глубокое погружение в эту Ж. А если процедура внешняя, то это лишняя тестирующая сущность и все такое. C>Демагогия.
Боюсь, что реальность. Хотя я в курсе, разумеется, что самая надёжная основа своей позиции — искусное отрицание очевидного.
C>Выглядит преотлично. На много лучше, чем то, что у вас есть (а точнее нет) в unmanaged C++. lambda выражения и fluent interface дают прекрасную читабельность.
C>
Можно подумать, что в документации приводят сложные нечитабельные примеры. Наверное, там ещё должны были написать о нерешённых проблемах, в том числе — фундаментальных.
V>>А теперь смотри что получается: автомоками удобно пользоваться для оформления относительно несложных тестов, где внешние условия и реакцию на них вполне можно описать декларативно и синтаксис все еще не будет раздражать. C>Модульные или unit тесты ОБЯЗАНЫ быть несложными. В этом их СУТЬ.
Угу. А ещё программы должны быть простыми. Это и называется искать решение сложных проблем простыми средствами, сиречь — руководствоваться лозунгами.
V>>Ах да, чуть не забыл... разумеется без них практически никак, если у кого-то был неудержимый понос на Ынтерфейсы в период дизайна.
Собственно для них в первую очередь оно и есть. C>Нет, не для них. Вам не надоело ламерствовать?
Это тебя регулярно заносит в область квадратуры круга циркулем.
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
Здравствуйте, gandjustas, Вы писали:
G>А shared_ptr — дополнительный оверхед к распределению памяти в куче.
Откройте для себя intrusive_ptr. Я, если честно, недоумеваю — чего так к shared_ptr прицепились ? Если объект наш собственный shared_ptr нафиг не упал, счётчик ссылок прекрасно встраивается. Вот если объект чужой и/или его модификация невозможна...
Здравствуйте, BulatZiganshin, Вы писали:
BZ>я не знаю насчёт net, но в ахскеле и по слузам в яве тоже двухпоколенный сборщик мусора. так он делает малую сборку через каждые 256кб выделенной памяти и никому это не мешает. так что ваозможно тут проблема только в прокладке
Имеем 3 вызова: 3х256кб == 3/4 от 1мб. Да пусть даже всего 256кб на простенький xmlrpc запрос с двумя параметрами... А не зажрались ли вы, батенька ?
Работа конкретно xmlrpc.net в данном случае это: сериализация двух параметров + имя метода в формат пакета XML-RPC, передача на сервер по HTTP/1.1, получение ответа и его десериализация в объектную модель.
Здравствуйте, gandjustas, Вы писали:
G>Самообман — думать что C++ всегда быстрее.
Можно пример программы на .NET, которую невозможно будет обогнать программой на С++ ? Желательно не скатываться на I/O, т.к. в этом случае будем мерять скорость работы сервисов ОС, и отставание .NET станет менее заметным. Под программой на С++ понимаем любой код, компилирующийся современным С++ компилятором, и дающий аналогичный результат работы.
P.S.: подсказка: сам CLR написан на C/С++, и скорость выполнения .NET кода это, в определённом смысле, скорость выполнения некоторой С++ программы. Которую всегда можно, как минимум, не замедлить.
Здравствуйте, Anton Batenev, Вы писали:
AB>Здравствуйте, MxKazan, Вы писали: MK>> Я только сразу оговорюсь, что сам на Mono не разрабатываю, т.к. мы пишем только под Windows. AB>С этого было надо начинать... и этим надо было заканчивать (см. мое предыдущее
сообщение).
Да брось. То, что в разделе КСВ форума RSDN нет людей, которые разрабатывают на Mono, совершенно не означает, что этот проект какой-то не юзабельный и его нельзя приводить в качестве аргументов. Тебе были даны все нужные ссылки. В форуме Работа встречалось обсуждение Mono и вакансии даже были. Я вот, например, и на Compact Framework не пишу, так что же, если меня спросят "что есть у .Net для мобильников", я должен буду отвечать "ничего"?
Здравствуйте, IID, Вы писали:
IID>P.S.: подсказка: сам CLR написан на C/С++, и скорость выполнения .NET кода это, в определённом смысле, скорость выполнения некоторой С++ программы. Которую всегда можно, как минимум, не замедлить.
И тебе подсказка: код на промежуточном языке компилируется при первом вызове, после чего скорость его исполнения в определенной степени перестаёт зависить от "выполнения некоторой С++ программы".
Здравствуйте, IID, Вы писали:
IID>Здравствуйте, gandjustas, Вы писали:
G>>Самообман — думать что C++ всегда быстрее.
IID>Можно пример программы на .NET, которую невозможно будет обогнать программой на С++ ? Желательно не скатываться на I/O, т.к. в этом случае будем мерять скорость работы сервисов ОС, и отставание .NET станет менее заметным. Под программой на С++ понимаем любой код, компилирующийся современным С++ компилятором, и дающий аналогичный результат работы.
IID>P.S.: подсказка: сам CLR написан на C/С++, и скорость выполнения .NET кода это, в определённом смысле, скорость выполнения некоторой С++ программы. Которую всегда можно, как минимум, не замедлить.
Пример не приведу, ибо очень большо получится. Но основная суть в том, что в .NET можно генерировать код в рантайме.
Здравствуйте, Геннадий Васильев, Вы писали:
ГВ>Здравствуйте, criosray, Вы писали:
C>>Так вот, ликбез: мокинг выполняется с целью изолировать тестируемый объект от внешних зависимостей.
ГВ>Ух ты! А я-то думал, что мокинг нужен для отслеживания последовательности внешних вызовов.
+1. Изоляция здесь в качестве средства. Но она сама-по себе хороша, потому изоляцию, достигнутую в целях обеспечения возможности тестирования возводят в бенефиты.
V>>>Далее, обмен сложными структурами данных заглушки и тестируемого объекта, у объекта приличное пространство состояний, на что заглушка должна грамотно реагировать, т.е. приличная иногда логика на if-ах и case-ах. C>>Элементарно средствами RhinoMocks.
ГВ>И неужто будет проще, чем аналогичная заглушка? Это если учесть, то заглушка реализуется в естественном синтаксисе, а мок — перехватом вызовов. Второе будет почти гарантированно сложнее.
Здесь vdimas говорит о FAKE-двойниках. Только они обладают собственным поведением, и эта категория двойников ну никак не генерится мокогенами. Но никто их не запрещает использовать под дотнетом рукописные Fake-и.
Здесь же мы обсуждаем именно мокогены — фреймворки, генерящие двойники без логики, а именно dummy, stub-ы, spy, mock-и. Точнее генерят они как правило стабы и моки, которые можно использовать как dummy и spy. И даже как Fake, но для этого нужна некоторая акробатика:
Fake двойника можно надстроить над генерированным моком, но это оправдано только в том случае, когда объем кода, с помощью которого можно прикрутить логику fake-а к моку не превышает объем рукописного fake-а (Для средних и больших интерфейсов — почти всегда оправдан). Потом, логику fake-а можно поместить в TestFixture, а сгенерированный мок науськать на ту логику. Не обязательно все пихать в тело теста в синтаксисе накачивания двойника констрейнтами .
В чем прелесть мока, сгенерированного мокогеном по сравнению с рукописным? Рассказываю. В отличии от рукописного мока, сгенерированный не требуется писать руками; сгенерированный мок реализует все что надо для отслеживания фактов вызовов, их порядков, и их параметров.
Представим простой пример кода, работающего с интерфейсом IList<int>. Допустим, код работает только со свойством Count и индексатором (а так часто и бывает). Для создания рукописного мока требуется реализовать порядка 10 методов просто. Для каждого теста своих.
Да, можем создать ListMockBase и переопределять нужные методы для каждого теста. Теперь представим, что интерфейс меняется в процессе разработки (а так часто быывает с интерфейсами, не определенными в стандартной библиотеке). Потребуется переписывать все моки и/или карежить базовый рукописный мок. Мокогенератор решает эти проблемы + наполняет моки функциональностью для тестирования (уже говорил).
V>>>В декларативном синтаксисе мокков это выглядит как удаление гландов через Ж, и чем осмысленнее логика — тем более глубокое погружение в эту Ж. А если процедура внешняя, то это лишняя тестирующая сущность и все такое.
Да, фэйки со сложной логикой через моки не пишут. А в моках логики быть не должно.
C>>Выглядит преотлично. На много лучше, чем то, что у вас есть (а точнее нет) в unmanaged C++. lambda выражения и fluent interface дают прекрасную читабельность.
C>>
ГВ>Можно подумать, что в документации приводят сложные нечитабельные примеры. Наверное, там ещё должны были написать о нерешённых проблемах, в том числе — фундаментальных.
Я бы не согласился, что это выглядит отлично. Но создавать для проверки каждого параметра отдельное утверждение с логикой — кошмар.
Здравствуйте, MxKazan, Вы писали:
MK>Здравствуйте, IID, Вы писали:
IID>>P.S.: подсказка: сам CLR написан на C/С++, и скорость выполнения .NET кода это, в определённом смысле, скорость выполнения некоторой С++ программы. Которую всегда можно, как минимум, не замедлить. MK>И тебе подсказка: код на промежуточном языке компилируется при первом вызове, после чего скорость его исполнения в определенной степени перестаёт зависить от "выполнения некоторой С++ программы".
Отвечу в этом месте обоим: JIT связан по рукам и ногам временными ограничениям. У С++ компилятора свободы (времени) гораздо больше. Насколько я понимаю, кода никто не приведёт, и можно засчитывать слив ?
Здравствуйте, IID, Вы писали:
IID>JIT связан по рукам и ногам временными ограничениям. У С++ компилятора свободы (времени) гораздо больше.
И что? Из этого твоего заявления только следует, что JIT круче
IID>Насколько я понимаю, кода никто не приведёт, и можно засчитывать слив ?
Эээ неее, не надо всех под одну гребенку. Я про код ничего не говорил. Более того, ты вообще не найдешь ни одного моего поста, где бы я утверждал, что .Net быстрее С++. Я всего лишь поправил тебя, указав на очевидное.
Здравствуйте, Mamut, Вы писали:
MK>> Например, "WikiPedia uses Mono for its search facilities. The indexing and the actual searching is done by Mono-based applications". M>Уже нет. Уже Java + Lucene
Мотороллер не мой
Здравствуйте, Геннадий Васильев, Вы писали:
V>>>Не надоело рефлексировать и показывать в очередной раз свой поверхностный взгляд? Все твои вызовы мокков ради ассертов, собственно и сделаны. И хоть они теперь не в фас, а в профиль — они были и есть цель любого автоматического теста (не обязательно юнит...) C>>"Все твои вызовы мокков ради ассертов, собственно и сделаны" — это напоминает генератор цепей Маркова. Взять два умных слова, и связать их между собой связующими. Получается билеберда, но звучит вроде как умно для стороннего человека.
C>>Так вот, ликбез: мокинг выполняется с целью изолировать тестируемый объект от внешних зависимостей.
ГВ>Ух ты! А я-то думал, что мокинг нужен для отслеживания последовательности внешних вызовов.
Неправильно думали. Мокинг нужен в первую очередь для изоляции тестируемого объекта. Чтоб сделать возможной эту изоляцию возможной необходимо симулировать поведение внешних зависимостей тестируемого объекта.
C>>Ассерты это всего-лишь предикат, который по-определению всегда true.
C>>Assert.Equals(10, someObj.SomeIntProperty); C>>Assert.IsTrue(someObj.SomeBoolProperty); C>>и т.д. и т.п.
ГВ>А по-твоему, Expect — это не тот же самый Assert в профиль? Assert — утверждение, Expect — утверждение о некотором ожидаемом событии. Тот же Assert, только специализированный.
К чему вопрос?
C>>Ассерты и моки не цель. Это средство и ключевой механизм реализации юнит тестов.
ГВ>Любое автоматическое тестирование сводится к проверке последовательности утверждений. Иначе оно совсем не нужно. Дальше только вариации способов записи этих утверждений.
Само собою. Весь этот спор о том, что на С++ нет даже близко сравнимых по удобству инструментов для тестирования.
ГВ>vdimas прав в том смысле, что если логика достаточно сложная, то и полные тесты достаточно трудно записывать. Вот тебе простейший пример (псевдокод):
И что тут сложного? Элементраный тест (в условиях дотнет) с условно установленными моками.
ГВ>
ГВ>То есть нужно проверить, что указанные сообщения ушли по заданным каналам, и только после определённого входного сообщения, и только в указанной последовательности, а потом ещё и желательно выдать осмысленное сообщение об ошибке.
Вы опять же путаете модульные тесты с интеграционными тестами. Модульные тесты не тестируют работу сети/жесткого диска/клавиатуры/мыши и т.д. Модульные тесты не тестируют взаимодействие подсистем. ит.д. и т.д. Короче, разберитесь в вопросе для начала, ок?
C>>При чем тесты ни коим образом не захламляют код. Все тесты находятся в отдельной сборке, которая "видит" (и только она одна) внутренности тестируемых сборок.
ГВ>Очень рад за вас.
А я очень опечален за вас.
C>>Еще один ликбез: описанное Вами не является модульными тестами. Это т.н. integration tests.
ГВ>Это зависит от того, что в данной конфигурации полагается модулем, а что — интеграцией. Поскольку структура любой сложной программы иерархическая, то модуль на одном уровне — это сборная конструкция на другом.
Нет, не зависит. RTFM, как говорится.
V>>>Далее, обмен сложными структурами данных заглушки и тестируемого объекта, у объекта приличное пространство состояний, на что заглушка должна грамотно реагировать, т.е. приличная иногда логика на if-ах и case-ах. C>>Элементарно средствами RhinoMocks.
ГВ>И неужто будет проще, чем аналогичная заглушка? Это если учесть, то заглушка реализуется в естественном синтаксисе, а мок — перехватом вызовов. Второе будет почти гарантированно сложнее.
С этой глупостью я даже спорить не стану.
V>>>В декларативном синтаксисе мокков это выглядит как удаление гландов через Ж, и чем осмысленнее логика — тем более глубокое погружение в эту Ж. А если процедура внешняя, то это лишняя тестирующая сущность и все такое. C>>Демагогия.
ГВ>Боюсь, что реальность. Хотя я в курсе, разумеется, что самая надёжная основа своей позиции — искусное отрицание очевидного.
Можете продолжать бояться. Как все-таки доберетесь до RTFM`а, то поймете, что я был прав.
V>>>А теперь смотри что получается: автомоками удобно пользоваться для оформления относительно несложных тестов, где внешние условия и реакцию на них вполне можно описать декларативно и синтаксис все еще не будет раздражать. C>>Модульные или unit тесты ОБЯЗАНЫ быть несложными. В этом их СУТЬ.
ГВ>Угу. А ещё программы должны быть простыми. Это и называется искать решение сложных проблем простыми средствами, сиречь — руководствоваться лозунгами.
Да, тестируемые участки кода должны быть простыми. В этом суть дизайна под названием Test Driven Development. Используя алгоритм write failing test -> write code -> until test succeed -> refactor ... добиваемся прекрасного качества кода с соблюдением всех правил современного программирования: DRY, SRP, и т.д.
Если Ваш код на столько сложный и запутанный, что Вы не можете написать серию простых тестов для него, значит Ваш код — плохой. Вот Вам и пища для размышлений.
Здравствуйте, MxKazan, Вы писали:
MK>Здравствуйте, IID, Вы писали:
IID>>JIT связан по рукам и ногам временными ограничениям. У С++ компилятора свободы (времени) гораздо больше. MK>И что? Из этого твоего заявления только следует, что JIT круче
Круче, потому что тормознее ?
вот твоя цитата:
MK>И тебе подсказка: код на промежуточном языке компилируется при первом вызове, после чего скорость его исполнения в определенной степени перестаёт зависить от "выполнения некоторой С++ программы".
C++ код изначально компилируется. Так что непонятно, что "волшебного" даст "компиляция при первом вызове", особенно если не забывать про ограничения по времени на эту компиляцию. Рассматриваем пока в контексте одинакового железа для выполнения, не скатываясь к "потенциальным оптимизациям в будушем под свежее железо". На этот случай, например, есть GCC + LLVM. Но речь о другом.
IID>>Насколько я понимаю, кода никто не приведёт, и можно засчитывать слив ? MK>Эээ неее, не надо всех под одну гребенку. Я про код ничего не говорил. Более того, ты вообще не найдешь ни одного моего поста, где бы я утверждал, что .Net быстрее С++. Я всего лишь поправил тебя, указав на очевидное.
товарища gandjustas, в котором тот утверждал, что:
G>Самообман — думать что C++ всегда быстрее.
Т.е. товарищ всеръез считает, что можно написать на .NET программу, которая окажется быстрее чем С++. Мой же поинт в том, что С++ всё-таки быстрее (уж во всяком случае точно не медленнее).
Здравствуйте, IID, Вы писали:
MK>>Здравствуйте, IID, Вы писали:
IID>C++ код изначально компилируется. Так что непонятно, что "волшебного" даст "компиляция при первом вызове", особенно если не забывать про ограничения по времени на эту компиляцию. Рассматриваем пока в контексте одинакового железа для выполнения, не скатываясь к "потенциальным оптимизациям в будушем под свежее железо". На этот случай, например, есть GCC + LLVM. Но речь о другом.
речь о csc + JIT?
IID>Т.е. товарищ всеръез считает, что можно написать на .NET программу, которая окажется быстрее чем С++. Мой же поинт в том, что С++ всё-таки быстрее (уж во всяком случае точно не медленнее).
Товарищ уже ответил
Пример не приведу, ибо очень большо получится. Но основная суть в том, что в .NET можно генерировать код в рантайме.