Расширение класса внешними методами и переменными

whirlwind

TDD infected, paranoid
Вообще, если уж говорить о моках, мокать чужие контракты — так себе затея («don't mock what you don't own»). Тебе может только казаться, что ты понимаешь контракт какой он есть, делая свой мок, а в реальности он может вести себя иначе. Не мокают, например, всякие DataMapper, а пишут интеграционные тесты с реальным MySQL. Если ты будешь придерживаться этого правила, то тебя не будет как минимум раздражать то, что содержится в чужих библиотеках. Они не твои, поддерживать обратную совместимость при изменениях в них не тебе, поэтому ныть по поводу присутствия final как-то даже неэтично, это как требовать бесплатно поработать.
Теперь давайте разберемся откуда растут ноги и почему это не сработает в большинстве случаев. Во-первых первоисточник, насколько я понял


Что мы видим? 1 страница с описанием одного конкретного кейса. Из 5 комментов под текстом 2 спамных, а остальные выражают несогласие или сомнения. Можно еще порыться и найти кучу дебатов на стэке, но положа руку на сердце, с чего вы решили сделать из этой фразы икону уровня TDA, KISS, etc? Это мнение отдельного человека, который даже не удосужился показать нам проблему в виде кода.

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

Теперь пойдем дальше. Вы зациклились на конкретных кейсах из веб разработки. Можно привести массу примеров где нет иного выбора, кроме как мокать. Например, вам нужно протестировать взаимодействие с удаленной платежной системой. Сколько денег вам понадобится закинуть на счет, что бы их хватило для ежедневной сборки? А что если ПС предусматривает off-work часы? Предположим, что вы тестируете работу банкомата. Для связи с оборудованием используется библиотека, которая без оборудования вполно предсказуемо кидает эксепшены. Таких примеров миллион. С entities это работает, потому что все знают про inmemory tables. И потому что залить sql фикстуру в базу легко. Возьмите более сложные случаи, более строгий язык и более продвинутый мок фреймворк. Никаких проблем с моканьем любых абстракций нет.

PS. А уж каким боком из этого текста выводится оправдание файналам это вообще загадка.
PPS. В спринге сегодня есть инструменты для тестирования по описанию Марка. И они прямым текстом называются интеграционными. Моки используются для изоляции в модульных тестах. Кто не понимает разницу - бегом в википедию читать про азы тестирования.
 
Последнее редактирование:

Вурдалак

Продвинутый новичок
Теперь давайте разберемся откуда растут ноги <...> Во-первых первоисточник, насколько я понял
*устало* Это из Growing Object Oriented Software, Guided by Tests, если ты можешь мыслить только авторитетами.

Обсуждать какие-то идеи на основе подсчёта комментариев в каких-то блогах — это прикольно.
 

whirlwind

TDD infected, paranoid
Авторитеты не при чем. Практика критерий истины. Вот мой кейс.
Есть dll провайдера данных. dll-ка подключенная к Java через JNI. Нужно протестить работу враппера

делаем фейк (а мог быть мок - без разницы), имплементирующий интерфейс либы:
сценарии:
делаем тест:

Какие тут проблемы?
*устало* Покажи свой тест, сравним и поговорим
 

fixxxer

К.О.
Партнер клуба
Если вы используете язык, которые позволяет нечеткие контракты (слабая типизация, вольности с сигнатурами вызовов), то вы сами себе злобные буратины.
Одной строгой типизации недостаточно, чтобы полноценно описать контракт. Тут можно углубиться в type theory и всякие dependent types, но и без этого понятно. Пишете не на Idris - сами себе злобные буратины, ага. :)

Никаких проблем с моканьем любых абстракций нет.
Ну вот и я не понимаю, в чем проблема протестировать, если в твоем примере будет final class JTransaqServerImpl implements (или extends abstract) JTransaqServer
 

whirlwind

TDD infected, paranoid
Одной строгой типизации недостаточно, чтобы полноценно описать контракт. Тут можно углубиться в type theory и всякие dependent types, но и без этого понятно. Пишете не на Idris - сами себе злобные буратины, ага. :)
Ну смысл же был не в этом. Смысл в том, что вы оправдываете параноидальную инкапсуляцию недостатками языка.

Ну вот и я не понимаю, в чем проблема протестировать, если в твоем примере будет final class JTransaqServerImpl implements (или extends abstract) JTransaqServer
Приходит мажор в автосалон и говорит менеджеру
- Вот вам чек на 15 лямов, заверните мне вон тот гелик
Менеджер забирает чек и отдает клиенту ключи от приоры. Мужик такой
- Алё, плебей, ты охренел? Нахера мне твоя приора?
А менеджер ему
- А чем Вы недовольны? Руль, педали, 4 колеса и пять посадочных мест, интерфейс имплементс?

Понимаешь абсурдность ситуации? Универсальный и короткий ответ: это не твоя зона ответственности.

Как разработчик класса ты отвечаешь за внутренности, за согласованность реализации ожиданиям пользователя посредством контракта. Если язык не позволяет описать контракт на 100%, то в твои обязанности входит дополнить контракт документацией. В этой части будет работать контракт по согласованию. Как пользователь будет использовать реализацию - не твое дело. Точно так же тебя не должно волновать хочет пользователь унаследовать или нет. А если да, то тебе должно быть плевать для каких целей он это делает.

Причин может быть сколько угодно от самых очевидных, типа такого что implements не обязует класс ограничиваться указанным интерфейсом и любой класс для любых целей может предоставлять дополнительные методы, расширяющие интерфейс (и тут мы можем уйти в обсуждение других фундаментальных проблем ООП, типа критической потери управляемости из-за высокого уровня абстракции). Или могут быть менее очевидные. В приведенном мной примере JTransaqServer это автоматически сгенерированный SWIG-ом файл на основе хидеров C++. Оно не может implements или abstract без заморочек. И если бы кто нибудть заморочился и вкрячил туда final для "обратной совместимости", ну это бы добавило проблем. Почему я должен выдумывать кейсы где final вреден? До сих пор никто не привел удовлетворительных примеров где использование final на метод/класс было бы реально обосновано. Это именно то, о чем я написал пару страниц назад.
 

fixxxer

К.О.
Партнер клуба
До сих пор никто не привел удовлетворительных примеров где использование final на метод/класс было бы реально обосновано.
Мне в очередной раз приводить общеизвестные аргументы против наследования от неабстрактных классов?

Обосновывать надо не использование final, а его отсутствие.

В приведенном мной примере JTransaqServer это автоматически сгенерированный SWIG-ом файл на основе хидеров C++. Оно не может implements или abstract без заморочек.
Окей, это нормальный аргумент, тут обосновано.

Как пользователь будет использовать реализацию - не твое дело.
Это смотря кто ее пользователь.
 

whirlwind

TDD infected, paranoid
Мы ходим по кругу. Спор уровня: "строгой типизации недостаточно для описания контракта, потому что никто не пишет новый тип на каждый чих IntegerFrom0UpTo100, IntegerFromMinus100UpTo100, etc" нет "строгой типизации достаточно для описания контракта, если писать на каждый чих новый тип". В точности как Гриша пошутил ) Мне очевидно, что вы путаете private с final. Из GoF вроде кто то писал, что нужно повышать private -> public только на то, что реально нужно в интерфейсе. final не тот случай. Диктовать пользователю правила использования это типа мужику на гелике запрещать врезаться в четные столбы или ездить по каширке. Любой скажет что требование - абсурд.
 

fixxxer

К.О.
Партнер клуба
Внутри компании я правила использования кода диктовал, диктую и диктовать буду. Может, еще code review отменить и стайлгайды?

В публичной же библиотеке - it depends, скорее всего, не стал бы final делать, хотят унаследоваться - ну пусть наследуются, мне-то что.
 

whirlwind

TDD infected, paranoid
Не надо ревью убирать. Это хорошая практика. Лучше начните писать модульные тесты. Говорят, помогает поборать страх внесения изменений и рефакторинга ;)
 

fixxxer

К.О.
Партнер клуба
А почему ты решил, что мы не пишем тесты? Представляешь, и final-ы есть, и тесты есть!
 

whirlwind

TDD infected, paranoid
Я говорил не про любые тесты, а про модульные. За прошедшие 5 лет ни одного достойного примера у поклонников final-ов так не набралось.
 

fixxxer

К.О.
Партнер клуба
Я не знаю, что ты имеешь в виду под модульным тестированием. Если юнит-тесты, то при соблюдении принципа DIC не возникает абсолютно никаких проблем.
 

Вурдалак

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

whirlwind

TDD infected, paranoid
Ненависть к final как к таковому, включая value objects и реализации с интерфейсами говорит только о том, что человек активно занимается наследованием реализаций. Но признаться в этом как-то стыдно, поэтому заводит шарманку про юнит-тесты, которые уже сто раз обсудили.
Завязывай поллюционировать. Ссылку на свой код я давал. Там не один проект, не один класс и не один тест. Можешь пойти поискать и тыкнуть меня носом в мое дерьмо, если найдешь. Предварительно скинув ссылку на свое. Третью страницу прошу отвас вашего очешуительного кода, но до вас туго доходит. Show me the fucking code или разговаривать неочем.
 

Yoskaldyr

"Спамер"
Партнер клуба
@whirlwind А тут просить показать код бесполезно. NDA и все такое. Я даже просил ссылку на любой опенсорс код готового продукта, который можно назвать бы хорошим. Все равно никто ничего не смог показать.
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
не преувеличивай, fixxxer выкладывал на github и присылал мне как-то либу, больше чем с 5 людьми тут я работал, никто не скрывает - был бы смысл,
и я свое показываю, когда есть что
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
Диалог интересный, заставляет задуматься и сформулировать. Final - штука полезная в userland, но не для всех.
Надо знать, что делаешь. Нельзя использовать отдельно, можно только в нормальном дизайне с DI и продуманными контекстами.
На галере среднего уровня в это лучше не лезть.

Отдельный разговор про фреймвоки, либы и крупные проекты.
"я правила использования кода диктовал, диктую и диктовать буду" не работает ни в enterprise, ни в open source.
"хотят унаследоваться - ну пусть наследуются, мне-то что" - отличный способ получить багрепорты, отвечать на которые придется в стиле фишеровского "простите, я не знал"
 

Yoskaldyr

"Спамер"
Партнер клуба
@grigori Я не преувеличиваю.
вот я задавал вопрос насчет примеров кода не раз (в разных контекстах примеров)
Начиная отсюда я задавал вопрос о коде не один раз, учитывая что тема в разы проще чем текущее обсуждение final-а
В теме как всегда было много писателей, но минимум читателей. И в конце концов @Вурдалак сослался на NDA и на то что коробочные продукты говно (хотя тут я не спорю)

здесь тоже несколько раз спросил тема еще более простая и тоже без примеров

@whirlwind Так что мне кажется не дадут нормальных примеров по final-у если даже по значительно простым вопросам не смогли (NDA или еще какие причины).
 

fixxxer

К.О.
Партнер клуба
NDA или еще какие причины
NDA, конечно. Чтобы показать примеры по твоим вопросам, по которым хоть что-то будет понятно, надо довольно много выложить. Какую-нибудь простую инфраструктурщину - это был бы не вопрос, а тут надо зачищать модели и придумывать что-то отвлеченное, это дофига работы, чтобы делать ее бесплатно.

@Adelf говорил, что над книгой работает, может, у него примеры есть.
 

Yoskaldyr

"Спамер"
Партнер клуба
@fixxxer Я же не просил обязательно что-то закрытое, но ведь не было примеров хотя бы одного оперсорс продукта/проекта.
Поэтому я и написал что это бесполезно. А потому что это статистика и реальность. И вообще не важно какие причины - NDA, не желание или еще что. Примеров кода не будет, поэтому зачем париться по этому поводу :))))

P.S. И я прекрасно понимаю когда NDA серьезно, в последних моих проектах нельзя даже немного показать код учитывая специфику.
 
Сверху