Ну не стоит так уверенно утверждать что с Microsoft не дерутся, с ними дерутся и еще как!
А вообще, почему вообще прогибаютя под одними, а под другими нет? Потому что у одних есть в конкретный момент времени хорошие лидеры, а других нет!
У мелкософт один Стив Балмер чего стоит! Менеджер дай боже! А яблоку в данный момент нужно очень хорошо подумать, ведь они потеряли достаточного серьезного менеджера! От этой потери они оправятся еще не скоро, если вообще оправятся. Надо не забывать и помнить, что когда-то Джобс уходил из Яблока и основал новую компанию Next. Что было тогда с Яблоком? Если бы не Джобс, мы бы о Яблоке сейчас и не знали даже!
Попробую я ответить, если вдруг ошибусь, то меня поправят.
Под поведением я понимаю некоторое целенаправленное действие осуществляемое под влиянием внешних и внутренних факторов. Действие это не один конкретный шаг, это возможное некоторое количество шагов. Мы хотим знать что в результате выполнения этих шагов мы не только достигнем результата, но не произойдет нечто такого, что не должно происходить.
На мой взгляд TDD это акцент на проверку корректности одного шага, а вот BDD допускает несколько шагов.
Примеры:
1) «Тестирование открытия файла по пустому имени файла» это небольшой шаг и это ближе к TDD
2) «Тестирование подписи файла по заданному файлу и приватному ключу» — здесь уже больше чем один шаг, но шаги связаны одной единой целью «подписать файл».
Для чего это надо?
Соблюсти баланс между внешними USE-case-ами и мелкими шагами из мира TDD. Если юз-кейсы «птицы высокого полета», а TDD «Насекомое и слишком приземленное», то как нам быть если мы хотим золотую середину?
ЗЫ: Прошу поправить если чего не так, сам вроде как понимаю, но выразить мысль сложно ;)
Забыл сказать о еще об одной важной фиче для меня:
5) Возможность дать задачу тим-лидом конкретному исполнителю и при этом иметь возможность быстро вспомнить, что делегировал и правильно ли все пашет?
Правда из п.5 для тим-лида может иметь последствия:
«Так ты же сам сказал как сделать-то надо» ;)
Можете поделиться опытом написания tearDown(), setUp() методов?
Возьмем тот же самый пример с тестированием strip() функции. По нормам и правилам TDD мы должны отделить создание тестовых строк от самого тест-метода и написать их в setUp() методе. Однако! Все эти три ситуации требуют трех разных строк s1, s2, s3. создание которых будет каждый раз повторяться при вызове очередного тест-метода. Это несколько напрягает.
На мой взгляд куда правильней иметь возможность создать индивидуальный setUp-метод для каждого тест-метода.
>>Сравните это с одним тестом testSuccess
1) Название тест-метода не testSuccess, а testStrip хотя бы ;)
2) Никто не мешает указывать текст утверждения при вызове assert-функции! Вы по прежнему будете знать где и что отвалилось? Но при этом код будет компактней!
На практике у меня это как-то плохо получается ) Возьму к примеру функцию strip() назначение которой удалить пробельные символы по бокам. При проектировании тест-метода я представляю эту функцию неким магическим черным ящиком работу которого не знаю, но знаю для чего нужен и что должен выдать. Меня интересуют след. ситуации:
1) Что будет если подать пустую строку?
2) Что будет если подать смешанное к примеру один пробел и один таб, либо 2 таба потом 3 пробела и снова таб?
3) Что будет если с одной стороны нет пробельных символов, а с другой есть?
Уже три утверждения которые нужно проверить. Если правильно Вас понял то вы бы на каждый из этих случаев написали бы по тест-методу. Все верно?
В любом случае, скажу что мне куда ближе формулировка:
«Функция strip() на строке работает успешно»
чем формулировки:
* «Функция strip() с пустой строки работает хорошо»
* «Функция strip() на смешанных пробельных символах работает успешно»
* «Функция strip() на пробельных символах с одной из сторон работает успешно»
По факту при использовании функции мне хочется знать ответ «Работает она или нет?» и мне по сути без разницы на какой из перечисленных выше ситуаций она не работает, главное сейчас для меня, что доверять нельзя!
Прежде чем ответить на ваш вопрос поясню что я имел ввиду под словом «умный». Прежде всего надо понимать что тест-метод это прежде всего мини-программа и как всякая программа он должен иметь строгу одну цель ради которой разработан. Но вот на практике оказывается, что также достигается и множество других целей не связанных с основной. Допустим основная цель: «протестить класс по работе с атрибутами файлов», но в результате не явно происходит открытие чего-нить другого, создание чего-нибудь еще и др. Так вот когда мы релизовываем мы условно закладываемся на то что и те, другие вспомогательные объекты тоже хорошо работают иначе тест провален. Поэтому мое мнение таково: т.к. тест-метод это все же не коммерческий продукт мы имеем возможность написать избыточную реализацию, чтобы благодаря этой избыточности можно было бы неявным образом захватить работу и других классов\функций\механизмов. Конечно же нужно понимать что тест-метод должен срабатывать более менее быстро.
Так вот «умный» тест-метод в моем понимании содержит такой код, который позволяет неявным образом больше затестить. Для меня это важно, т.к. в основном тесте для какой-нить функкции я могу забыть что-нить проверить
При моем небольшом опыте использования TDD заметил:
0) «Затык» в написании теста как правило сигнал о том, что не совсем хорошо написал АПИ
1) Это отличная возможность подумать над интерфейсом API на начальном этапе и его удобстве использования
2) Не следует писать много тестов, нужно писать умный тест, даже если придется задуматься на минуту по-дольше
3) Довольно часто хочется знать ответ на вопрос: А не сломал ли я то что у меня уже было?
4) Легко разделяет команду на тестер \ разработчик и также быстро происходит смена ролей
Я бы еще добавил:
Не доказывай с пеной у рта на каком-нибудь форуме, что человек не прав, а ты прав. Сил, а иногда и нервов, потратишь много, но ничего полезного не сделаешь ни для себя ни для своих близких.
Ну так я и не стал утверждать на все 100% ;) Поэтому предварил словами «Насколько помню дело было...», а подразумевает, что человек может неправильно помнить ;)
Очень рад, что вы это привели в более точном варианте!
>>В мануалах белым по-черному написано, что нельзя рассчитывать на то, что функция memcpy правильно отработает при перекрывании dst и src.
Вот и я об этом же! Когда программист пишет:
>>while(length--) *dst++ = *src++;
Он хочет быть полностью уверенным в том что будет работать так как он это видит на экране, а не ждать возможных хитросплетений аналогичной функции из mem*-семейства.
>>Что это? Копипаст? Почему не использовать что то типа mmcpy?
Не думаю. Просто 1) Подобный код пишется на автомате в результате привитой привычки 2) Даже в такой мелкой функции можно «накосячить» это произойдет если не проверить наложение областей источника и получателя. А делать такую проверку не всегда целесообразно.
Да, по одной из такой функции mem* семейства Линус Торвальдс «гладил по головке» разработчиков одного из Open-source проекта. Насколько помню дело было в том что разработчики допустили косяк при разработке функции и произошло наложение областей src и dst, а с течением времени другие разработчики кто использовал функцию в своем коде просто принимали этот косяк как данность и в конечном итоге спустя время, в наши дни решили этот косяк убрать что привело к тому что одна из программ у Торвальдса перестала работать. На что он собственно корректно заявил «Не следует из править баг исправление которого нарушает работоспособность солидное множество других программ».
>>Почитайте описание OllyDbg. В частности, про механизмы трассировки.
Вы хотите меня по учить техникам эмуляции? :))) Забавно! Но прежде чем это сделать, настоятельно рекомендую:
0) Написать элементарный test.cpp проект в котором реализовать небольшую логику на базе мультитредности, для простоты можно взять расчет информационной энтропии переданного в тред как аргумент куска памяти.
1) Взять VMProtect, его загуглить не сложно
2) Защитить им этот самый test.exe
3) Запустить эмуляцию с помощью вашего OllyDbg.
4) Запустить какой нить профайлер в Intel-тулзах их не мало!
Я не пытаюсь вам показать насколько я крут или не крут, просто увидел что вы Линуксоид(на аватарке тукс изображен) и следовательно к экспериментам привычный человек, вот и привел вам тему эксперимента благодаря которому можно получить практическое понимание вопроса.
Вот после того как этот элементарнейший пример посмотрите на практике и увидите как собственно его эмулит OllyDbg, тогда почитайте на авер-сайтах:
1) Как часто используются современные протекторы? Т.е. VmProtect, AsProtect, Themida, etc. (Тут скажу что они(авер-эмуляторы) не все протекторы подобного уровня эмулят, иногда просто тупо по сигнатуре или еще каким методам детектят, но многие самплы(вирье) по броне не сильно-то и уступают им)
2) Затем подумайте а стоит ли эмулировать команду через другие или все же куда эффективней на живом процессоре?
>>Это на вас так поздний час действует или вы решили таки фанатом побыть?)
Причем тут фанатом? Я просто пытаюсь Вам показать, что в громадном количестве задач Far справляется в Разы лучше чем программа с развитым GUI интерфейсом!
>>но никто его в здравом уме с BMW M5 не сравнивает
Сравнивает! Но с умом. Задавая вопрос самому себе: «А чего конкретно в данный момент хочу добиться?». Всегда все и вся нужно решать исходя из сложившейся ситуации. Порою проще доехать на велосипеде, ибо пробка. А где-то, к примеру в другой город, лучше конечно же на машине. Ситуативнее мыслить надо! ;)
>>мы бы с вами до сих пор пользовались браузером mosaic
Не поверите, но я в консольном FreeBSD-шном man-е, который казалось бы кроме нескольких кнопок '/', 'n', 'p' довольно часто нахожу в разы быстрее и больше чем в казалось бы мега-удобном Google Chrome!
>>Не должны любители интерфейсных анахронизмов рассуждать о современном информационном дизайне
Поясните, что Вы вкладываете в «информационный дизайн» и что в «интерфейсных анахронизмов»?
>>1. не навижу FAR, юзаю TotalCommander.
При всем уважении к Тоталу, который я использовал в течении 5 лет и местами юзаю до сих пор, он все же многие вещи не умеет. К примеру банальная вещь «Subshell», т.е. Ctrl+O так и не реализована! ;( Все мои попытки убедить автора были посланы в TotalConsole плагин, который настолько «юзабелен», что…
А вообще, почему вообще прогибаютя под одними, а под другими нет? Потому что у одних есть в конкретный момент времени хорошие лидеры, а других нет!
У мелкософт один Стив Балмер чего стоит! Менеджер дай боже! А яблоку в данный момент нужно очень хорошо подумать, ведь они потеряли достаточного серьезного менеджера! От этой потери они оправятся еще не скоро, если вообще оправятся. Надо не забывать и помнить, что когда-то Джобс уходил из Яблока и основал новую компанию Next. Что было тогда с Яблоком? Если бы не Джобс, мы бы о Яблоке сейчас и не знали даже!
Под поведением я понимаю некоторое целенаправленное действие осуществляемое под влиянием внешних и внутренних факторов. Действие это не один конкретный шаг, это возможное некоторое количество шагов. Мы хотим знать что в результате выполнения этих шагов мы не только достигнем результата, но не произойдет нечто такого, что не должно происходить.
На мой взгляд TDD это акцент на проверку корректности одного шага, а вот BDD допускает несколько шагов.
Примеры:
1) «Тестирование открытия файла по пустому имени файла» это небольшой шаг и это ближе к TDD
2) «Тестирование подписи файла по заданному файлу и приватному ключу» — здесь уже больше чем один шаг, но шаги связаны одной единой целью «подписать файл».
Для чего это надо?
Соблюсти баланс между внешними USE-case-ами и мелкими шагами из мира TDD. Если юз-кейсы «птицы высокого полета», а TDD «Насекомое и слишком приземленное», то как нам быть если мы хотим золотую середину?
ЗЫ: Прошу поправить если чего не так, сам вроде как понимаю, но выразить мысль сложно ;)
5) Возможность дать задачу тим-лидом конкретному исполнителю и при этом иметь возможность быстро вспомнить, что делегировал и правильно ли все пашет?
Правда из п.5 для тим-лида может иметь последствия:
«Так ты же сам сказал как сделать-то надо» ;)
Возьмем тот же самый пример с тестированием strip() функции. По нормам и правилам TDD мы должны отделить создание тестовых строк от самого тест-метода и написать их в setUp() методе. Однако! Все эти три ситуации требуют трех разных строк s1, s2, s3. создание которых будет каждый раз повторяться при вызове очередного тест-метода. Это несколько напрягает.
На мой взгляд куда правильней иметь возможность создать индивидуальный setUp-метод для каждого тест-метода.
1) Название тест-метода не testSuccess, а testStrip хотя бы ;)
2) Никто не мешает указывать текст утверждения при вызове assert-функции! Вы по прежнему будете знать где и что отвалилось? Но при этом код будет компактней!
1) Что будет если подать пустую строку?
2) Что будет если подать смешанное к примеру один пробел и один таб, либо 2 таба потом 3 пробела и снова таб?
3) Что будет если с одной стороны нет пробельных символов, а с другой есть?
Уже три утверждения которые нужно проверить. Если правильно Вас понял то вы бы на каждый из этих случаев написали бы по тест-методу. Все верно?
В любом случае, скажу что мне куда ближе формулировка:
«Функция strip() на строке работает успешно»
чем формулировки:
* «Функция strip() с пустой строки работает хорошо»
* «Функция strip() на смешанных пробельных символах работает успешно»
* «Функция strip() на пробельных символах с одной из сторон работает успешно»
По факту при использовании функции мне хочется знать ответ «Работает она или нет?» и мне по сути без разницы на какой из перечисленных выше ситуаций она не работает, главное сейчас для меня, что доверять нельзя!
Так вот «умный» тест-метод в моем понимании содержит такой код, который позволяет неявным образом больше затестить. Для меня это важно, т.к. в основном тесте для какой-нить функкции я могу забыть что-нить проверить
Это особенно полезно при Agile-разработке
0) «Затык» в написании теста как правило сигнал о том, что не совсем хорошо написал АПИ
1) Это отличная возможность подумать над интерфейсом API на начальном этапе и его удобстве использования
2) Не следует писать много тестов, нужно писать умный тест, даже если придется задуматься на минуту по-дольше
3) Довольно часто хочется знать ответ на вопрос: А не сломал ли я то что у меня уже было?
4) Легко разделяет команду на тестер \ разработчик и также быстро происходит смена ролей
Не доказывай с пеной у рта на каком-нибудь форуме, что человек не прав, а ты прав. Сил, а иногда и нервов, потратишь много, но ничего полезного не сделаешь ни для себя ни для своих близких.
Очень рад, что вы это привели в более точном варианте!
Вот и я об этом же! Когда программист пишет:
>>while(length--) *dst++ = *src++;
Он хочет быть полностью уверенным в том что будет работать так как он это видит на экране, а не ждать возможных хитросплетений аналогичной функции из mem*-семейства.
Не думаю. Просто 1) Подобный код пишется на автомате в результате привитой привычки 2) Даже в такой мелкой функции можно «накосячить» это произойдет если не проверить наложение областей источника и получателя. А делать такую проверку не всегда целесообразно.
Да, по одной из такой функции mem* семейства Линус Торвальдс «гладил по головке» разработчиков одного из Open-source проекта. Насколько помню дело было в том что разработчики допустили косяк при разработке функции и произошло наложение областей src и dst, а с течением времени другие разработчики кто использовал функцию в своем коде просто принимали этот косяк как данность и в конечном итоге спустя время, в наши дни решили этот косяк убрать что привело к тому что одна из программ у Торвальдса перестала работать. На что он собственно корректно заявил «Не следует из править баг исправление которого нарушает работоспособность солидное множество других программ».
Вы хотите меня по учить техникам эмуляции? :))) Забавно! Но прежде чем это сделать, настоятельно рекомендую:
0) Написать элементарный test.cpp проект в котором реализовать небольшую логику на базе мультитредности, для простоты можно взять расчет информационной энтропии переданного в тред как аргумент куска памяти.
1) Взять VMProtect, его загуглить не сложно
2) Защитить им этот самый test.exe
3) Запустить эмуляцию с помощью вашего OllyDbg.
4) Запустить какой нить профайлер в Intel-тулзах их не мало!
Я не пытаюсь вам показать насколько я крут или не крут, просто увидел что вы Линуксоид(на аватарке тукс изображен) и следовательно к экспериментам привычный человек, вот и привел вам тему эксперимента благодаря которому можно получить практическое понимание вопроса.
Вот после того как этот элементарнейший пример посмотрите на практике и увидите как собственно его эмулит OllyDbg, тогда почитайте на авер-сайтах:
1) Как часто используются современные протекторы? Т.е. VmProtect, AsProtect, Themida, etc. (Тут скажу что они(авер-эмуляторы) не все протекторы подобного уровня эмулят, иногда просто тупо по сигнатуре или еще каким методам детектят, но многие самплы(вирье) по броне не сильно-то и уступают им)
2) Затем подумайте а стоит ли эмулировать команду через другие или все же куда эффективней на живом процессоре?
Причем тут фанатом? Я просто пытаюсь Вам показать, что в громадном количестве задач Far справляется в Разы лучше чем программа с развитым GUI интерфейсом!
>>но никто его в здравом уме с BMW M5 не сравнивает
Сравнивает! Но с умом. Задавая вопрос самому себе: «А чего конкретно в данный момент хочу добиться?». Всегда все и вся нужно решать исходя из сложившейся ситуации. Порою проще доехать на велосипеде, ибо пробка. А где-то, к примеру в другой город, лучше конечно же на машине. Ситуативнее мыслить надо! ;)
Не поверите, но я в консольном FreeBSD-шном man-е, который казалось бы кроме нескольких кнопок '/', 'n', 'p' довольно часто нахожу в разы быстрее и больше чем в казалось бы мега-удобном Google Chrome!
>>Не должны любители интерфейсных анахронизмов рассуждать о современном информационном дизайне
Поясните, что Вы вкладываете в «информационный дизайн» и что в «интерфейсных анахронизмов»?
При всем уважении к Тоталу, который я использовал в течении 5 лет и местами юзаю до сих пор, он все же многие вещи не умеет. К примеру банальная вещь «Subshell», т.е. Ctrl+O так и не реализована! ;( Все мои попытки убедить автора были посланы в TotalConsole плагин, который настолько «юзабелен», что…