Да какое ж это доказательство. Книгу я привёл в качестве ссылки. А смысл её сложно передать в комментарии к топику на хабре, поскольку в ней его много.
Вы пишете тест таким образом, как вы хотите, чтобы потом ваш код можно было использовать
Вот это и есть весь смысл TDD? Смысл TDD в написании тестов определённым образом? Ну нет. Эта фраза совсем не означает, что вы разбираетесь в TDD (сам факт чего я не отрицаю).
Вот не могу я в статье найти механизма выбрасывания копипаста, хоть как всматриваюсь и перечитываю. В комментариях — вижу фразу «копипаст потом выбрасывается», а когда «потом» и как именно — не вижу.
Мне страшно представить проект, в котором код двух разных программистов общается между собой исключительно через xmlrpc или подобные по назначению протоколы. В любом случае, наличие этого протокола не отменяет необходимости проектировать взаимодействие компонентов.
На выделении методов и классов рефакторинг не заканчивается. Точно так же методы и классы при необходимости выделяются в более общие классы/шаблоны/библиотеки. И я не вижу смысла откладывать рефакторинг на потом, кроме лени. Каждая операция рефакторинга сама по себе проста и очевидна при некотором опыте. Сделать её «потом, когда придёт озарение о более общем классе» не проще, чем «сейчас и потом, если понадобится».
Давно уже придуманы принципы, следуя которым нельзя ухудшить архитектуру или «упустить шанс» её улучшить. Описаны в разных книгах, больше всего, по-моему, у МакКоннелла в «Совершенном коде».
В статье рассказывается про вред тестов, паттернов проектирования и отсутствие вреда копипаста. Мой комментарий — про вред копипаста, пользу паттернов и тестов. Вне зависимост от момента. Перечитайте ;)
А протоко(а)лы у вас откуда берутся? Проектируются, небось. Как говорят умные люди и подтверждает практика, именно на взаимодействиях этих самых узлов бОльшая часть ошибок и происходит. Неплохо, когда хотя бы часть этих ошибок не появляется из-за того, что два человека одинаково понимают, о чём идёт речь (это про использование паттернов).
Например, ситуация полностью противоположна описанной вами, а именно «интерфейс большой и тесты сложные, а реализация маленькая и простая». Ну, что в голову первое приходит. Скажем, тестировать внешний вид визуализатора для музыки, чтобы все варианты анимации соответствовали задуманному алгоритму. Тесты писать вы будете очень долго, а толку от них будет мало, да и разработку они вряд ли ускорят. Проще на результат глазами посмотреть :)
Я бы не только сказал, но и доказать могу, что есть ситуации, когда без тестов быстрее :)
А измерения уже много раз проводились. Западные книгописатели любят на всякие разные измерения ссылаться. Только измерения проводились в одних условиях, а проект делается в других, поэтому тут поможет только здравый смысл и опыт.
Без тестов достигается то же качество кода, что и с тестами, только быстрее.
Это, несомненно, правильно. Но это если сравнивать с этапом разработки по TDD. А если учитывать и этап поддержки, то программисты, которые занимаются поддержкой, скажут автору огромное «спасибо» за код с копипастом и без тестов. Даже если не задумываться о поддержке, если вдруг какому-то другому человеку понадобится внести изменения в код, написанный автором, у него (или у проекта) возникнут проблемы.
Паттерны – это рутины, для тех, кто не умеет программировать. У хороших-же программистов паттерны выскакивают прямо из-под клавиатуры.
Даже если не обращать внимание на то, что одна фраза противоречит другой, паттерны — это не та штука, которую «выучил и начал использовать». Формализация паттернов служит, в основном, таким целям:
* Увидеть как определённые типы механизмов в ООП реализуются наилучшим образом, какие есть в этих механизмах подводные камни, плюсы и минусы.
* Выработать общую терминологию, благодаря которой проектирование идёт быстрее. Это позволяет говорить друг другу «тут можно использовать композит» вместо «можно сделать такую функцию, в которую передаём объект того же базового класса, что класс содержащий функцию чтобы он прицепился к контейнеру и ...»
рефакторинг – это очень просто. Правильно и без ошибок это гораздо быстрее сделать без тестов, чем с тестами.
Это касается только своего собственного кода, написанного меньше недели назад, а если точнее — то только разработки с параллельным рефакторингом. Если нужно отрефакторить чужой код, написанный с применением других методологий (или вообще без оных), разными людьми в разное время — без тестов можно только пожелать побольше удачи.
В общем, если вы разрабатываете программы сами, без команды, не собираетесь заниматься их поддержкой в дальнейшем (и не страшно испортить карму проклятиями от тех, кто поддержкой заниматься таки будет), отлично умеете проектировать и знаете правильные принципы — то описанный подход для вас. Только непонятно, почему вы всё ещё разрабатываете программы сами, без команды и разрабатываете такие программы, которые не планируют развиваться :)
А я ничего и не говорил про информатиков. IM-клиенты — это средство общения в сети, независимо от профессии. Обучить общаться в Pidgin или QIP не сложнее, чем обучить общаться в ICQ. Только в Pidgin можно общаться с людьми, у которых аккаунты на яндексе, гмейле, icq, ..., а через ICQ — только с теми, у кого ICQ.
По-моему, email-рассылки — более «гиковская» тема, чем IM-конференции (ICQ или XMPP). Просто она очень древняя, поэтому кажется проще.
Через jabber работает много полезных ботов, многие сервисы (в основном, западные) отправляют через xmpp уведомления. Можно на их примере показать полезность открытой технологии. К xmpp также есть различные расширения. Наверняка, некоторые из них будут полезны преподавателям. Какие именно — надо искать, не сильно интересовался. IRC большинству, действительно, ни к чему.
Я не спорю, что коробка 12 будет закрыта.
Я говорю о вашем доказательстве, а именно:
1) n != k, тогда состояние коробки будет изменено 2 раза, на проход номер n и на проход номер k. Ничего в результате не изменится, неинтересно.
Состояние, очевидно, не будет изменено 2 раза. Оно будет изменено 5 раз (или 6, если считать, что на 1 проход все коробки открыты). А неверное утверждение не может служить доказательством, т.к. из него, по законам логики, может следовать как верный, так и неверный вывод.
Моё решение не сводится к Вашему. Ответ — да, одинаковый. Но одно дело доказать утверждение, а другое сказать «мне голос свыше сообщил, что оно верно» :).
Не понимаю, почему плюсуют это решение. Очевидно ведь не верное.
Пусть N = n * k. Тогда коробка будет открыта/закрыта на n-й проход, на k-й, а также на все проходы, номера которых являются делителями n или k, а также их комбинаций.
Например, коробка 12 (3х4) будет открыта/закрыта на 2, 3, 4, 6, 12 проход.
Т.е. ответ верный (вероятно, увиденный где-то), но доказательство — нет.
Правильное решение намного проще.
Коробка будет открыта/закрыта столько раз, сколько у неё есть делителей, отличных от 1.
Если число разложить на простые множители, получим что-то вроде
N = a^x * b^y * c^z *… (a, b, c простые; x, y, z больше 1). Для такого числа общее количество различных детилелей равно (x+1)(y+1)(z+1). Почему это так — не буду объяснять, думаю, можно самостоятельно найти.
Чтобы коробка в конце была открыта нужно, чтобы число её делителей было нечётным. Это возможно только когда x, y, z,… — чётные. Но если они чётные — число является полным квадратом.
Вряд ли описанный метод решает проблему. Суть в том, чтобы при выборке Doctrine::getTable( «Base_Class» )->find( $id ) возвращался объект Derived_Class (extends Base_Class), но чтобы при этом Base_Class ничего не знал про Derived_Class (как это и должно быть в ООП).
Может я что-то сильно не замечаю, но по-моему в доктрине нет способа сделать наследование моделей, хранящихся в одной таблице, без указания всех подклассов в базовом классе (кроме Simple, который, по понятным причинам, не подходит).
Там внутри тех классов, которые реально переопределить, используются другие классы доктрины, которые подменить уже не получится. Relation — один из них.
Недавно нам тоже пришлось делать грязный хак доктрины для отвязывания наследования моделей от базового класса (т.е. необходимости перечислять наследников в базовом). Правда, обошлось без изменений библиотеки :)
Если хочется изменить стандарт кодирования или сделать исключение — можно изменить проверяльщика кода. Как показала практика, проблем с проверкой стандартов почти не возникает (а те, что возникают, быстро решаются), а вот код становится почище.
А то тут тролли кругом… такого понапишут.
Вот это и есть весь смысл TDD? Смысл TDD в написании тестов определённым образом? Ну нет. Эта фраза совсем не означает, что вы разбираетесь в TDD (сам факт чего я не отрицаю).
Давно уже придуманы принципы, следуя которым нельзя ухудшить архитектуру или «упустить шанс» её улучшить. Описаны в разных книгах, больше всего, по-моему, у МакКоннелла в «Совершенном коде».
А измерения уже много раз проводились. Западные книгописатели любят на всякие разные измерения ссылаться. Только измерения проводились в одних условиях, а проект делается в других, поэтому тут поможет только здравый смысл и опыт.
Это, несомненно, правильно. Но это если сравнивать с этапом разработки по TDD. А если учитывать и этап поддержки, то программисты, которые занимаются поддержкой, скажут автору огромное «спасибо» за код с копипастом и без тестов. Даже если не задумываться о поддержке, если вдруг какому-то другому человеку понадобится внести изменения в код, написанный автором, у него (или у проекта) возникнут проблемы.
Даже если не обращать внимание на то, что одна фраза противоречит другой, паттерны — это не та штука, которую «выучил и начал использовать». Формализация паттернов служит, в основном, таким целям:
* Увидеть как определённые типы механизмов в ООП реализуются наилучшим образом, какие есть в этих механизмах подводные камни, плюсы и минусы.
* Выработать общую терминологию, благодаря которой проектирование идёт быстрее. Это позволяет говорить друг другу «тут можно использовать композит» вместо «можно сделать такую функцию, в которую передаём объект того же базового класса, что класс содержащий функцию чтобы он прицепился к контейнеру и ...»
Это касается только своего собственного кода, написанного меньше недели назад, а если точнее — то только разработки с параллельным рефакторингом. Если нужно отрефакторить чужой код, написанный с применением других методологий (или вообще без оных), разными людьми в разное время — без тестов можно только пожелать побольше удачи.
В общем, если вы разрабатываете программы сами, без команды, не собираетесь заниматься их поддержкой в дальнейшем (и не страшно испортить карму проклятиями от тех, кто поддержкой заниматься таки будет), отлично умеете проектировать и знаете правильные принципы — то описанный подход для вас. Только непонятно, почему вы всё ещё разрабатываете программы сами, без команды и разрабатываете такие программы, которые не планируют развиваться :)
По-моему, email-рассылки — более «гиковская» тема, чем IM-конференции (ICQ или XMPP). Просто она очень древняя, поэтому кажется проще.
Я говорю о вашем доказательстве, а именно:
Состояние, очевидно, не будет изменено 2 раза. Оно будет изменено 5 раз (или 6, если считать, что на 1 проход все коробки открыты). А неверное утверждение не может служить доказательством, т.к. из него, по законам логики, может следовать как верный, так и неверный вывод.
Моё решение не сводится к Вашему. Ответ — да, одинаковый. Но одно дело доказать утверждение, а другое сказать «мне голос свыше сообщил, что оно верно» :).
Пусть N = n * k. Тогда коробка будет открыта/закрыта на n-й проход, на k-й, а также на все проходы, номера которых являются делителями n или k, а также их комбинаций.
Например, коробка 12 (3х4) будет открыта/закрыта на 2, 3, 4, 6, 12 проход.
Т.е. ответ верный (вероятно, увиденный где-то), но доказательство — нет.
Правильное решение намного проще.
Коробка будет открыта/закрыта столько раз, сколько у неё есть делителей, отличных от 1.
Если число разложить на простые множители, получим что-то вроде
N = a^x * b^y * c^z *… (a, b, c простые; x, y, z больше 1). Для такого числа общее количество различных детилелей равно (x+1)(y+1)(z+1). Почему это так — не буду объяснять, думаю, можно самостоятельно найти.
Чтобы коробка в конце была открыта нужно, чтобы число её делителей было нечётным. Это возможно только когда x, y, z,… — чётные. Но если они чётные — число является полным квадратом.
Недавно нам тоже пришлось делать грязный хак доктрины для отвязывания наследования моделей от базового класса (т.е. необходимости перечислять наследников в базовом). Правда, обошлось без изменений библиотеки :)