LINUX.ORG.RU

Применимы ли паттерны GoF для LISP?


1

2

Меня удивляет, сколько у местных лисперов враждебности в адрес GoF и паттернов проектирования, что «GoF это такой мемуар про то как перцы писали текстовый редактор, там больше пиара». Ну предположим в некоторых паттернах действительно нет нужды... например Visitor не нужен потому ччто есть multiple dispatch. Некоторые паттерны сильно завязаны на ООП, которое я так понимаю в Лиспе не приветствуется. Но подавляющее большинство паттернов не только успешно решает поставленные задачи, но ещё и реализуются красивее, чем в той же Java, за счёт развитой макросистемы и ФПП. То есть задача и способ решения есть, но западло назвать это «паттерном»? Откуда такая боязнь называть вещи своими именами. А то получается как в анекдоте: ж**а есть, а слова нету.

Также хочется услышать опытных лисперов, какой подход к проектированию своего ПО вы практикуете, желательно с пояснениями и обоснованиями. На всякий случай, проектирование - это то, что следует после постановки ТЗ, но предшествует непосредственно кодированию. Спасибо.

Паттерн - это шаблон, а зазубривание шаблонов приводит к амозглию.

достаточно зайти на какуюнить тусовку дотнетчиков.

Вот, для примера, назови паттерн для лиспа который стоит применять.

_________

//wfrr

anonymous
()

> сколько у местных лисперов враждебности в адрес GoF

Да ладно, я над GoF смеялся ещё в бытность ярым плюсовиком. Проблема GoF в том, что там паттерны ну уж слишком примитивные и знакомые всем более или менее опытным разработчикам, ибо придумываются на ходу по мере необходимости.

ООП, которое я так понимаю в Лиспе не приветствуется


Неправильно понимаешь. С чего-бы ему не приветствоваться? Кто тогда изобрёл CLOS/MOP? Это просто один из подходов к декомпозиции, доступный в лиспе.

проектирование - это то, что следует после постановки ТЗ,

но предшествует непосредственно кодированию.



Водопадная модель? Это ведь уже лет 30 как не в моде?

archimag ★★★
()

> Паттерн - это шаблон, а зазубривание шаблонов приводит к амозглию.

Я что-то говорил о зазубривании? Что, приёмы в восточных единоборствах - это тоже шаблоны и зазубривание? Приёмы игры на музыкальных инструментах? В первую очередь - понимание (в том числе достоинств и недостатков), и умение применять. Ну а кто не может понять - для того таки да, зазубривание.

Вот, для примера, назови паттерн для лиспа который стоит применять.


Singleton, Flyweight, Facade, Proxy, Interpreter, Iterator, Observer, Strategy...

и это мы ещё не касались паттернов J2EE

Ignatik
() автор топика
Ответ на: комментарий от Ignatik

>> Вот, для примера, назови паттерн для лиспа который стоит применять.

Singleton

По-моему, Singleton уж много лет как признан антипаттерном даже для Явы. В любом случае, применять его для языка, в котором есть функции, как-то странно.

tailgunner ★★★★★
()
Ответ на: комментарий от archimag

> Да ладно, я над GoF смеялся ещё в бытность ярым плюсовиком.

А над самоучителем игры на гитаре не смеётесь? Там же приёмы ну уж слишком примитивные и знакомые всем более или менее опытным музыкантам, ибо придумываются на ходу по мере необходимости.

Вообще, что смешного в том, чтобы дать имена распространённым приёмам и изучить их применимость, достойнства и недостатки?

Водопадная модель? Это ведь уже лет 30 как не в моде?


Не надо подменять понятия, я не говорил о водопадной модели. Я говорил о подходах к проектировани. По существу есть что ответить? Или вы сразу садитесь писать код, едва прочитав ТЗ?

Ignatik
() автор топика
Ответ на: комментарий от tailgunner

> По-моему, Singleton уж много лет как признан антипаттерном даже для Явы.

Пруфы? А то я так про любой паттерн скажу, что «он уж много лет как признан антипаттерном даже для Явы».

В любом случае, применять его для языка, в котором есть функции, как-то странно.


Функции умеют хранить своё состояние?

Ignatik
() автор топика
Ответ на: комментарий от Ignatik

> Или вы сразу садитесь писать код, едва прочитав ТЗ?

Нет, я просто сажусь писать код и взаимодействовать с пользователями, ТЗ если и возникает, то обычно гораздо позже и никто его не читает.

archimag ★★★
()
Ответ на: комментарий от Ignatik

> Функции умеют хранить своё состояние?

Вполне, через замыкания это делается элементарно.

Norgat ★★★★★
()
Ответ на: комментарий от Ignatik

>Я что-то говорил о зазубривании? ... В первую очередь - понимание (в том числе достоинств и недостатков), и умение применять.

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

Singleton, Flyweight,

Это антипаттерны 8)

Facade, Proxy,

это костыли, в крестах и прочих дубовых языках они смотрятся элегантно

Interpreter,

так можно и метод map назвать паттерном, да 8)

Iterator, Observer, Strategy...

нафига это в функциональных языках? За первое вообще надо собранием сочинений кнута бить по голове.

_________

//wfrr

anonymous
()

То есть задача и способ решения есть, но западло назвать это «паттерном»?

граммарнаци повесились

ПАТТЕРН - это внешнее проявление скрытого свойства, проявляющееся одновременно с этим свойством.

например, есть у тебя два куска кода, оба круто работают. Начинаешь анализивать, и вдишь в обоих кусках кода одну и ту же структуру. Впоследствии эту струтуру назовут каким-нибудь словом, например, «синглтон».

но при этом нужно помнить, что первично, а что вторично. Паттерн - только проявление. Одному и тому же свойству может соответствовать много паттернов.

и самое главное, паттерн, как результат анализа - это вещь безоценочная. Бывают паттерны хороших вещей, бывают паттерны плохих вещей. И даже само «хорошо-плохо» зависит от контекста. Например, многие любят тот самый «синглтон», а мне (вместе с Кентом Беком) кажется, что использовать глобальные переменные в языке, где они явно запрещены - плохо. Наверное, у нас разные контексты.

Но нет, мысль дурака полярна. Прочитав книжку с надписью «паттерны» дурак начинает считать ее чем-то вроде банки с волшебными таблетками. Бяка-плохо, няка-хорошо. Чтобы как-то описать «бяку» больные амозглией придумали слово «антипаттерн», после чего заболевание приобрело характер эпидемии ;)

Так вот возвращаясь к лиспу. Имхо, некорректно говорить нечто вроде «паттерн неприменим, потому что есть multiple dispatch». Вопрос в том, является ли кусок кода на лиспе, в котором наблюдается multiple dispatch действительно крутым кодом. Часто ли оно повторяется, какие последствия несет? И вообще, не являются ли multiple dispatch и visitor проявлением одного и того же свойства?

stevejobs ★★★★☆
()
Ответ на: комментарий от Ignatik

>> По-моему, Singleton уж много лет как признан антипаттерном даже для Явы.

Пруфы?

В гугль.

Функции умеют хранить своё состояние?

1) в глобальных переменных; 2) в аргументах, заданных через карринг.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

>Singleton уж много лет как признан антипаттерном даже для Явы.

А при помощи чего все эти годы реализовывали тот функционал который дает синглтон? При помощи God-класса?

Absurd ★★★
()
Ответ на: комментарий от Ignatik

>Функции умеют хранить своё состояние?

Вообщето об сем даже веб-JS-кодеры знают.

_________

//wfrr

anonymous
()
Ответ на: комментарий от Absurd

Ой вэй дарагой! Любимый мой родной, посмотри как в яве всунуть обработчик аутентификации классу URL, и прикинь насколько это пипец если мне надо открыть несколько соединений к разным серверам 8) И так по всей яве.

_________

//wfrr

anonymous
()
Ответ на: комментарий от Absurd

> А при помощи чего все эти годы реализовывали тот функционал который дает синглтон?

Тебя снова обманули - синглтон не дает никакого функционала.

При помощи God-класса?

При помощи поклонения сатане.

tailgunner ★★★★★
()
Ответ на: комментарий от anonymous

>посмотри как в яве всунуть обработчик аутентификации классу URL

Класс URL вообще очень странный. С одной стороны он являет собой некий ID сетевого ресурса, а с другой стороны это какая-то странная фабрика коннекшенов. Я всеже всегда считал что класс должен делать только одно дело, но делать его хорошо. Что особенно удивительно, класс URL написал лично Гослинг.

Absurd ★★★
()
Ответ на: комментарий от archimag

> Проблема GoF в том, что там паттерны ну уж слишком примитивные и знакомые всем более или менее опытным разработчикам, ибо придумываются на ходу по мере необходимости.

Ты не понимаешь сути паттернов.svg

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

То, что идиоты делают из паттернов религию, - так причина этого известна давно: «научи дурака богу молиться, он и лоб расшибёт».

LamerOk ★★★★★
()
Ответ на: комментарий от tailgunner

>> А при помощи чего все эти годы реализовывали тот функционал который дает синглтон?

Тебя снова обманули - синглтон не дает никакого функционала.

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

Absurd ★★★
()
Ответ на: комментарий от anonymous

>>Singleton, Flyweight,

Это антипаттерны 8)


Пруфы? Особенно хотелось бы услышать про Flyweight. Вы вообще в курсе, что это такое? Книжку-то читали?

Facade, Proxy,


это костыли, в крестах и прочих дубовых языках они смотрятся элегантно


Нет, вы точно книжку не читали. Вы в курсе, что такое Facade? Как это вообще связано с языками? Это абсолютно language agnostic подход.

Iterator, Observer, Strategy...


нафига это в функциональных языках?


Расскажите мне, как вы собираетесь реализовывать подписку компонентов (например, виджетов) на события (например, нажатие кнопки) в функциональных языках.

Ignatik
() автор топика
Ответ на: комментарий от tailgunner

>> Пруфы?

В гугль.


Понятно, пруфов нет.

1) в глобальных переменных;


И этот человек говорит мне про антипаттерны, лол?

2) в аргументах, заданных через карринг.


А менять-то, менять-то их сможет? Вот то-то!

Ignatik
() автор топика
Ответ на: комментарий от tailgunner

> Тебя снова обманули - синглтон не дает никакого функционала.

А что же такое тогда «обеспечить наличие в системе одного (или нескольких) экземпляров класса»? Не функционал ни разу?

Ignatik
() автор топика
Ответ на: комментарий от undet

> Вывод примерно такой: шаблоны — это костыли, которые нужны в ограниченных языках. В языках вроде Lisp такой необходимости в них нет.

Задача. Есть сторонняя библиотека, оперирующая своим набором классов и иинтерфейсов (в смысле CLOS). Есть наша собственная разработка, оперирущая схожей семантикой, но другими интерфейсами.

Задача: воспользоваться из нашей разработки функционалом сторонней библиотеки.
Решение: написать класс-обёртку, который бы реализовал нужный интерфейс над чужим интерфейсом (паттерн Adapter).

Выходит, Лисп - всё-таки ограниченный язык, раз ему нужны костыли?

Ignatik
() автор топика
Ответ на: комментарий от baverman

> У кого-нибудь есть еще сомнения по поводу цвета и ширины ТС?

Есть что по-существу вопроса сказать, дорогой кандидат во френды?

Ignatik
() автор топика
Ответ на: комментарий от Ignatik

Традиционный лисповый подход — делать ООП чисто на замыканиях.

http://letoverlambda.com/index.cl/guest/chap2.html

(да, может показаться жестью, но это и есть прямой ответ на твой вопрос).

Есть еще и CLOS, который больше похож на обычное ООП, только гораздо лучше.

Vadim_Z
()
Ответ на: комментарий от Ignatik

>>> Пруфы?

В гугль.

Понятно, пруфов нет.

Понятно, в гугль не сходил.

1) в глобальных переменных;

И этот человек говорит мне про антипаттерны,

Этот человек отвечает тебе на вопрос.

лол

Бгг.

2) в аргументах, заданных через карринг.

А менять-то, менять-то их сможет?

Я - да, ты - похоже, нет.

.

tailgunner ★★★★★
()
Ответ на: комментарий от Vadim_Z

> Традиционный лисповый подход — делать ООП чисто на замыканиях.

Авторы open-source библиотек для CL активно протестуют.

archimag ★★★
()
Ответ на: комментарий от Ignatik
(defun make-ds (state-table init-state)
	(let ((state init-state))
		(lambda () 
			(setq state (get-jump state-table state)))))

Вполне изменяемое состояние внутри функции. Обычный карринг, как уже было замечено выше(просто в ML\Haskell для этого есть синтаксиеский сахар). Можно вернуть не одну, а несколько лямбд, если сильно надо, и вертеть состоянием\состояниями по разному.

Norgat ★★★★★
()
Ответ на: комментарий от Ignatik

> Пруф?

(let ((str "Hello world"))
  (defun show ()
    (print str))
  (defun change (x)
    (setf str x)))

archimag ★★★
()
Ответ на: комментарий от Ignatik

Есть что по-существу вопроса сказать

Ты ушибленный гофом чудик, с ограниченным кругозором.

baverman ★★★
()
Ответ на: комментарий от Ignatik

> Решение: написать класс-обёртку, который бы реализовал нужный

интерфейс над чужим интерфейсом (паттерн Adapter).


Не. Просто дописать необходимые реализации методов. В CLOS нет интерфейсов, а методы не принадлежат классам.

archimag ★★★
()
Ответ на: комментарий от archimag

А как же 25я глава On Lisp?

ООП в смысле определения Алана Кея выросло, в числе прочего, на традиционных разработках на лиспе. «Штука-на-замыканиях» не меньше похожа на ООП, чем соответствующие аспекты Linux Kernel и WinAPI (причем нигде явно не вводились объекты и классы как элементы языка).

Слова про ООП уже потом начали приговаривать, но насчет «никакого» — это ты погорячился.

Vadim_Z
()
Ответ на: комментарий от tailgunner

> Понятно, в гугль не сходил.

Почему я за вас должен ходить в Google?

Я - да, ты - похоже, нет.


Ну так не стесняйтесь, продемонстрируйте как функция может поменять свои «аргументы, заданные через карринг». Или опять будет как в прошлый раз, отсылом в Google?

Ignatik
() автор топика
Ответ на: комментарий от LamerOk

Ну как-то так, да.

Автор, не дрочи на паттерны GoF. Это просто шаблоны кода, которые где-то применимы, где-то нет. Ну конкретно для CL - мало какие из них в явном виде бывают полезны, если бывают вообще, потому как большая их(паттернов GoF) часть - подпорки и костыли для языков типа C++ и Java, часто имеющие целью, кстати, эмулировать фичи продвинутых языков типа CL(ну приснопамятный визитор, etc).

lovesan

anonymous
()

>Откуда такая боязнь называть вещи своими именами. А то получается как в анекдоте: ж**а есть, а слова нету.

В том то и дело, что это не озночает называть вещи своими именами. Уже в самом слове «паттерн» пафоса просто дофига, а прикрывает оно просто говнецо.

Waterlaz ★★★★★
()
Ответ на: комментарий от archimag

Следует добавить, что CLOS не был ни первой, ни единственной объектной системой в Lisp. Изначально применение таких системы ограничивалось имитационным моделированием и AI, для чего они, собственно, и делались.

;; Вр.И.О. К.О.

Vadim_Z
()
Ответ на: комментарий от Ignatik

>Ну так не стесняйтесь, продемонстрируйте как функция может поменять свои «аргументы, заданные через карринг». Или опять будет как в прошлый раз, отсылом в Google?

(defun make-adder (&optional (value 0))
  (lambda (&optional (i 1))
    (incf value i)))

(defvar *adder* (make-adder 10))
;; ==> *ADDER*

(funcall *adder*)
;; ==> 11

(funcall *adder* 5)
;; ==> 16

lovesan

anonymous
()
Ответ на: комментарий от Vadim_Z

На самом деле, CLOS это закономерный итог развития объектных систем лиспов. Вершина развития. А было их(ОО-систем) много, да.

anonymous
()
Ответ на: комментарий от anonymous

Можно даже так, для большей понятности:

(defun make-adder (&optional (value 0))
  (lambda (&optional (i 1))
    (incf value i)))

(setf (symbol-function 'adder) (make-adder 10))
;; ==> #<CLOSURE (LAMBDA (&OPTIONAL (I 1))) {241CB175}>

(adder)
;; ==> 11

(adder 5)
;; ==> 16
anonymous
()
Ответ на: комментарий от anonymous

Ну правильно, а начиналось все с замыканий. Возможно, именно поэтому основные усилия были направлены не на смехотворную инкапсуляцию данных а-ля С++ (потому что замыкания это уже умеют), а на диспетчеризацию и сабтайпинг.

Что, в общем, и хорошо.

Vadim_Z
()
Ответ на: комментарий от archimag

> Нет, я просто сажусь писать код и взаимодействовать с пользователями, ТЗ если и возникает, то обычно гораздо позже и никто его не читает.

Может, стоило попробовать написать что-то посложнее расстановщика бутылок? Что-нибудь с какой-нибудь смешной сотней-другой сущностей? Ах, не предлагают... Жалко!

А я расскажу, что было бы. После двух-трех таких «итераций» по «взаимодействию с пользователями» код превратился бы в груду немайнтебельной лапши. Отсутствие документированной модели будущей системы наихудшим образом сказывается на управляемости кода.

А если ты скажешь, что ты готов удержать в голове всю сотню сущностей с их атрибутами, методами, связями и иерархией наследования — то я скажу, что ты п....бол.

anonymous
()
Ответ на: комментарий от tailgunner

>Понятно, в гугль не сходил.

Собственного мнения основанного на индивидуальном опыте у tg почему-то нет.

Absurd ★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.