Другое дело, если объект представляет из себя список или хранилище «ключ-значение» без ожидаемого набора ключей и элементов — удаление одного из них ни для кого не окажется сюрпризом, опять же независимо от парадигмы.
Напоминает перенос ошибок со стадии компиляции на стадию выполнения…
и при этом паттерны традиционно считаются сильной стороной ООП.
Попытаюсь найти точку зрения, с которой это так.
Раз паттерны — неизбежное зло, будем использовать. И тут — да, в ОО языках и сами эти костыли красивее и пользы от них больше, чем в не-ОО языках. «Think Haskell, code C++», образно говоря, лучше, чем «Think С, code very bad assembler».
Посмотрел Grails. С точки зрения «джависта» — «полный угар»: методы, котрые являются методами экземпляра у CriteriaBuilder и EntityManager, перобразованы в статические методы у сущностей. Как будто все сущности наследуют от одного предка. Ну еще и прикопипастнуты методы (или пригенерированы по шаблону), вызывающие методы предка с доп.аргументом — классом:
public class Person extends DBExternalizableBase{
...
public static Person get(int id){
return DBExternalizableBase.<Person>get(Person.class, id);
}
...
}
Вкурил дальше — так и есть, делается через препроцессор. От препроцессора в самой Java отказались сразу. Посмотрел дальше — никакой переносимости кода между библиотеками или между контейнерами даже и не подразумевается, что для программирования на самой Java моветон вдвойне.
Согласен. Если для некоего частого поведения требуется паттерн, значит, в языке не хватает идиом или библиотечных функций/макросов. Паттерны — это костыли для хоть какого-то лечения этой нехватки.
Кем считаются? Не мной точно. Паттерны — это по определению «костыли», раз можно не только «так», а ещё и «не так», раз можно, например, не только «собирать мусор», а ещё и «не собирать мусор». Лучший паттерн — это элемент синтаксиса языка, как оператор вызова функции или оператор цикла или интерфейс в Java. Второй — это системная библиотека, подпрограмма или макрос, которые вынуждают его использовать, типа ситуации с ActionListener-ами в Java. Третий — несистемная библиотека, подпрограмма или макрос, которые вынуждают его использовать.
Реализация высокоуровневых черт в низкоуровневыз языках. В 1950-е годы, ещё до изобретения стека и немного после него, на ассемблере некоторых машин вызов подпрограммы тоже был «шаблоном дизайна».
Я прежде всего имел в виду пригодность для полуавтоматического рефакторинга средствами IDE, что в разы увеличивает объём кода, которым можно управлять в одиночку.
Для domain objects — да: «проксируемые structs» и сервис-объекты. Но, кроме «доменщины», описывающей реальный мир, существуют библиотеки подпрограмм: в них ОО-парадигма служит способом более компактной, удобной и читабельной организации кода. Об этом я написал только последний абзац;-)
Если метод можно прицепить к объекту в runtime-е, а не на этапе проектирования, то это уже не tight coupling. Правда, в нагрузку это ещё и не рефакторится.
Средствами контейнера наинженерить класс-наследник-обёртку, который будет транслировать вызовы на сам объект и возвращать полкченный результат и, кроме, делать что-то до/после(/вместо) получения результата от самого проксируемого объекта (в частности, логгирование или управление транзакциями).
С вызовами функций такая фишка проходит, с обращением к полям — нет.
Раз паттерны — неизбежное зло, будем использовать. И тут — да, в ОО языках и сами эти костыли красивее и пользы от них больше, чем в не-ОО языках. «Think Haskell, code C++», образно говоря, лучше, чем «Think С, code very bad assembler».
Вкурил дальше — так и есть, делается через препроцессор. От препроцессора в самой Java отказались сразу. Посмотрел дальше — никакой переносимости кода между библиотеками или между контейнерами даже и не подразумевается, что для программирования на самой Java моветон вдвойне.
Уточню свой ответ — это сейчас в основном реализация черт функциональных языков в языках, в которых функция не является «объектом первого класса».
недавно нашёл — norvig.com/design-patterns/ или www.google.com/search?q=peter+norvig+design+patterns+in+dynamic+languages
А что вы подозревали, что я имею в виду?
Инкапсуляция вынуждает использовать методы. Потом эти методы можно переопределить и(ли) обынтерфейсить.
Важно знать типы на этапе компиляции, это делает язык пригодным для «дешёвого» и интенсивного рефакторинга.
С вызовами функций такая фишка проходит, с обращением к полям — нет.