Pull to refresh

Comments 175

Ох. Во многих хороших книжках объясняется, что ООП — это не просто философия, а ещё и набор возможностей языка, позволяющих легко вести разработку, отладку, поиск ошибок, если вы придерживаетесь определённой философии (в данном случае — ООП).

Конечно! На любом языке можно писать ООП-шно. Можно писать ООП без классов, можно мыслить ООП-шно… Но надо понимать, что вы при этом можете потерять помощь со стороны языка, со стороны компилятора.

Например, на Perl принято писать ООП-шно. И можно писать OOП-шно. Но Perl не проверяет типы, он не предупредит вас, если конструктор вернул не объект, а undef (что в Perl частенько практикуется), ошибка возникнет в run-time и может вылезти очень далеко, и найти её будет не просто. В C++ такие ошибки невозможны и выявляются ещё в момент компиляции. Этой (и другими) удобной возможностью можно пользоваться, а можно и не пользоваться, дело ваше.

Надо понимать, что флейта не играет как фортепиано, а голосом не изобразить звук флейты. А если музыкант этого не понимает, то хреновый же это музыкант! :-)
Я тоже встречал такие хорошие книжки. Но еще больше (и здесь, на Хабре) я видел статей не об ООП, а про термины. И попытки объяснить ООП какими-то левыми понятиями (вчера-позавчера была такая попытка) мне кажутся неглубокими.

… Музыкант это очень хорошо понимает! Разницу в музыкальных инструментах он впитал с молоком матери. Но так же он понимает, что музыка — инвариантна, и гармоничные звуки как флейты, так и фортепиано — это музыка. Именно это я хотел показать. ООП — не инструмент, а философия.
С первой мыслью полностью согласен! Ни одной удачной попытки объяснить ООП «на примере девушек/мальчиков/пива/семечек» я не видел; а всё виденное вызывает отвращение.

А вот про инвариантность музыки… я бы поспорил. Инвариантен только тон, но не тембр, не интервал (попробуйте флейтой или голосом изобразить гармонический интервал ,-)). Всё же исполняемая музыка зависит от возможностей инструмента. Для исполнения симфонии нужен симфонический оркестр. Конечно, если для исполнения музыки, которая играет в душе музыканта, достаточно трещотки, то ему сойдёт и барабан и свисток… но мне что-то не хочется тратить время на прослушивание музыки его души.

Точно так же в программировании. Отличный пример — lighttpd. Если хотите, почитайте его код. Он написан на чистом С, но полностью ООП-шно. Создан даже некоторый механизм макросов и соблюдаются определённые правила оформления кода и именования переменных (причём слова this, self и подобные — не используются). Выглядит всё великолепно, прям сморишь и радуешься торжеству человеческого гения. Но посмотрите, как часто в этом творение находят утечки памяти, как часто в коде (часто скрыто) идёт перетипизация указателей… Компилятор и без того не помогает находить проблемы, которым ООП-средство просто не позволило бы возникнуть. Но в коде применяются приёмы, которые ещё больше запутывают компилятор и большую часть работы перекладывают на программиста. Правильный ли это подход? Мне так не кажется.
Да я с вами согласен тоже, причем полностью, по всем пунктам, даже насчет инвариантности музыки. Я в ней, если честно, ничего не понимаю, я ее просто люблю. А вот ООП я не только люблю, но и понимаю. Я рад, что его используют, но если, объективно, лучше было бы ООП-подход не использовать — то и не надо, избежим лишней мороки. Наверно, кроме того что ООП — это философия, это и инструмент тоже, а любой инструмент хорош только в своем деле. Равно как и существуют другие, параллельные философии, порой оспаривающие эту.

Пусть так; пусть существуют проекты, где нет классов, но есть ООП. Тот же ваш пример, lighttpd. Возможно, чтобы избавиться от всех проблем с утечной памяти или прочими косяками, стоило бы забыть про ООП и писать все… ну, хотя бы, модульно. Или, если уж «на ООП пошло», писать на С++, избавляясь ООП-методами от проблем с той же памятью. Возможно, вы почувствовали, что я не люблю открытую работу с памятью как раз по причине, что надо быть внимательным. И не зря существуют так называемые «умные указатели» — самая что ни на есть ООП-шная концепция, избавляющая от проблем с утечкой и подсчетом ссылок. Ага, ага, а еще есть С# и сборщик мусора…

Тема эта многогранна. Не использовать ООП трудно сейчас, а понять, где его и не надо использовать — еще труднее. Всё ж таки, я в крайности не впадаю и понимаю, что панацеи не существует.
Полностью согласен; а последний абзац — вообще золотые слова!

Но что касается lighttpd — там как раз OOП уместен. Там, фактически, приложение состоит из машин состояний, которые порождаются и удаляются по мере необходимости. Классический С-шний подход — контекст, функции создания, удаления, изменения контекста. ООП-подход — объект, конструктор, деструктор, методы. Так? ,-) А вот и не совсем так :-)
>попробуйте флейтой или голосом изобразить гармонический интервал

арпеджио? ;)
Не угадали.

Интервал — это когда две ноты звучат ОДНОВРЕМЕННО. В случае с флейтой, ее нужно… 2 штуки! :) (и 2 музыканта впридачу)

А аперджио — это когда ноты аккорда играются ПОСЛЕДОВАТЕЛЬНО, по заданному ритмическому и мелодическому паттерну.
Если, что вас обманули. Интервал — это расстояние между двумя звуками. Интервалы бывают мелодические (последовательные) и гармонические (одновременные).

Не зря сверху написано «изобразить гармонический интервал».
Вот как! Век живи — век учись. Спасибо, не знал.

В любом случае, даже исходя из этих определений, изобразить гармонический интервал с помощью аперджио не получится. :)
Простите, что вклиниваюсь в беседу)
Помню, когда я писал на чистом Си (тоже в некотором роде ООПшно, правда я не читал исходников lighttpd, и не знаю, также как там или нет), я для борьбы с ошибками работы с памятью (утечки, сегфолты и прочее) написал свой простенький менеджер памяти. Ну то есть — выделяем при запуске программы большой блок памяти и дальше орудуем в ней.
Все операции с памятью логируем, проверяем, и т.п. — разумеется только при отладке — ведь в Си есть волшебная система макросов, что позволяет всего 1им дефайном для релиза отключить наш менеджер памяти и воспользоваться стандартным.
Отладка стала просто волшебно простой :)
Какие-то проблемы реализации абстрактного синтаксиса на Си++. :)

Забавно, у меня диплом по этой теме (typeful abstract syntax, разбор, проверка типов, интерпретатор), но там, конечно, все по-другому, и на экспериментальном ЯП.
UFO just landed and posted this here
UFO just landed and posted this here
Статья была не про мою ORM. Статья была про объектно-ориентированное программирование. Все рассуждения с кодом лишь показывают решение одной просто интересной задачи. Если бы я хотел написать про QST, я бы написал. Да и напишу, как только доработаю еще некоторые части…

Если вас интересует обоснование моих методов в QST, то пожалуйста. Передавать условия в виде строки — можно. Однако, их, бывает, нужно сгенерировать динамически. Вы правильно догадались: имена полей очень даже известны, а вот функторы сравнения могут быть разными, в зависимости от того, что нужно программисту на данный момент. Передавать функтор в виде отдельного объекта считаю очень важным.

Написав «QstCondition(QstField(«F1»), FunctorEqual, QstField(«F2»))», я визуально оформил то, что хотел бы видеть: все параметры приходят извне, значит, вместо каждого из них могут быть другие значения. Особенно вместо функтора. Мне не нужно записывать «F1 = F2», поскольку я разрабатываю ORM, а не пишу уже конкретное приложение баз данных. Приведя все эти примеры, я для себя делаю ориентир, к которому потом и двигаюсь.

«Хорошим обоснованием может быть необходимость генерировать запрос динамически, например, если программа может узнать имена полей или какие-либо условия только в рантайме» — именно так и происходит. Почему не написано в статье? Во-первых, ссылка на статью о QST 0.3 дана. Во-вторых, статья о конкретной задаче и ООП-решении.

«Намного правильнее — инкапсулировать доступ к данным в отдельном модуле, в этом случае, билдер запросов можно написать на коленке».

Что вы имеете в виду? Попахивает концепцией ORM. Так именно ее я и пишу…

Спасибо за «expression trees», возможно, они найдут место в моей библиотеке.
UFO just landed and posted this here
Ох, сейчас заклюют… Но! Моё личное мнение: в данной статье описана крайность, когда человек насилует ООП, прикручивая его туда, где без него только лучше. Какую выгоду даёт описанный метод? Красоту?.. Да, это хорошо, я за красоту. Но посмотрите сколько минусов вместо SQL запроса —
Извините, допишу тут :)
Вместо SQL запроса — астрономическая башня из классов.

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

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

Очень скоро вам понадобятся не только AND и OR но и IF() CONCAT() и ещё очень много полезных функций. И тогда либо писать куски запросов на уровне где этого кода по задумке быть не должно. Либо вводить ещё несколько астрономических башен, после чего вы окажетесь запертыми и приковаными к своей системе, потому что уже никто кроме вас в ней не разберётся :)

вот такое ИМХО…
Извините, но Ваш комментарий возмутил меня до глубины души.

Особенно — «вместо SQL запроса — астрономическая башня из классов».

Да, один сферический SQL-запрос в вакууме — это замечательно лаконичная и, в то же время, вполне читаемая штука. А когда их двадцать на обслуживании очень узкого участка функционала? А всего сотни и сотни? И поля названы APP_ID_3240 (каковое поле хранит сумму заказа. Почему? А так исторически сложилось)

Вы когда-нибудь пробовали разбираться в минимально сложной системе, написанной неизвестно кем, где доступ к данным построен на прямом использовании SQL? И сделать в этой системе совершенно тривиальные изменения (типа, изменить тип данный одного поля в самой широко используемой таблице, или изменить тип отношений таблиц). А потом сравнить этот опыт с опытом использования более или менее вменяемого ORM?

Пардон за оффтопик, я понимаю, что холивар на тему ORM против SQL — не есть тема этого поста. Взыграло ретивое.
JuliaTem ничего не говорил против ORM. Наоборот, с моей точки зрения он подводит к тому выводу что
Очень скоро вам понадобятся не только AND и OR но и IF() CONCAT() и ещё очень много полезных функций. И тогда либо писать куски запросов на уровне где этого кода по задумке быть не должно.


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

В предыдущей статье я этого не увидел (http://graninas.habrahabr.ru/blog/78394/), если я пропустил этот момент, то собственно большая часть критики снимается.

Я понял JuliaTem так: не должно быть такого что каждый SQL запрос мы пишем с нуля только используя не чистый SQL, а кучу классов.
А вы хотите почитать о вложенных запросах? Могу написать статью об этом.
UFO just landed and posted this here
Насколько я понимаю, автор и не собирался описывать полностью свое ORM-решение. Насколько я понимаю, это была иллюстрация процесса мышления при дизайне ОО кода. В ответ он получает, что нах это все не надо, надо использовать SQL.
Благодарю. Вы всё поняли правильно.
Ок, пусть унас есть 2 такие системы.

в одной — для выборки данных мы пишем SQL, заворачиваем его в метод, метод принимает параметры или объект, где члены имеют смысловое значение. Внутри метода (его приватная логика) идёт подстановка «говорящих» параметров в сложный SQL запрос. Метод вернул набор данных или объектов. Учитывая, что класс знает соответствие имён полей и юзаемых в системе логических имён для них, то метод вернёт всё в том же формате, что и принимает, т.е. имена полей или ключей будут те самые «говорящие»

Во второй — для выборки данных мы строим запрос по описанному в статье принципу. Т.е. каждое условие — это объект, каждое OR или AND — объект, содержащий набор объектов-условий. Построение Объекта «запрос» состоит из комбинирования объектов-надстроек над OR и AND.

Как мне добавить в запрос условие типа
SUMM( IF( 'some str' like CONCAT(field1, field2), 1, 2)) as mygoal [....] GROUP BY id HAVING mygoal=42
? Будет ли это так же просто? не понадобится ли сперва допилить движок?

Избавит ли меня конструкция вида QstCondition(«F1», FunctorEqual, «F2») от проблем с «не говорящими» полями?

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

А если вместо этого, просто прикидываться, что что это у нас не SQL, а потому можно писать запросы где вздумается, то вместо выгоды получим только более сложный код.
Ну, вроде бы достаточно очевидно, что все эти вавилонские башни классов и функторов делаются не для того, чтобы с их помощью писать запросы руками. Для автомата, конечно же. Не?
Конечно, «не». Если бы делали для автомата, о выделении памяти бы не заботились — автомат не ошибается.
Ох, как же вы заблуждаетесь, как вы заблуждаетесь…
Автомат — не ошибается. Ошибаются люди, которые его программируют.
А где в статье сказано, что все эти ОРМ-функции _не_ выносятся из бизнес-логики?! Я, по крайней мере, понял именно так.
меня убил первый абзац, там где в обилии музыкальные термины разные ) в художественном стиле написано )))
читаю первый абзац — ооп без классов и обьектов. скролю в самый низ — классы, паблики… лолшто??
Могу только пожелать вам читать внимательнее.
Ух, тоже из объектов делал условия для орм: habrahabr.ru/blogs/about_cms/55216/
Но ощущение, что лучше реализовать мета язык, чтоб как и sql писать строкой оптимально выражая условия и будет проще принимать условия со стороны.
Ага, только если у нас объектная модель, то не нужно язык запроса строить по подобию sql с его джойнами
Ну почему же, если сказать себе, что джойны — между классами, а не между таблицами, то морально становится легче.

Вообще, ORM, при всей моей нежной любви к Хайбернейту, есть зло, поскольку продлевает срок жизни реляционному монстру :)
Так нужно понимать, что классы уже связаны и должно быть достаточно указать: выбирать свойство А, у свойства А выбирать свойства В, Г, Д :) Более того, обычно в ORM делают отложенную загрузку, т.е. указывать что выбирать не надо. :)
Естественно. И это работает для большинства случаев. Но рано или поздно все равно приходится пользоваться или HQL запросами, или Criteria. К сожалению :)
Оу. Вы изобрели шаблоны Интерпретатор и Компоновщик. Затем воспользовались Фаулеровским ОбъектомЗапроса и представили это как нечто новое :)

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

«говорите что «в книгах по ООП оперируют сферическими конями в вакууме»» — где вы такое увидели? Не передергивайте, пожалуйста. Все мои слова, вон они, вверху. Я говорил о статьях «про ООП», где даны термины, и ничего больше. А иногда вообще безобразие: термины объясняются левыми понятиями («девушками»), и это гордо называется ООП.
Не «в ООП-стиле», вот в чем дело.

ООП-решение — это просто построить систему объектов и их отношений. Ваше решение к этому имеет очень опосредованное отношение.
Что-то я тогда не пойму, из чего я построил систему. Извините, конечно, но что же это, если не объекты и их отношения?
Ну вот понимаете, чтобы сделать систему критериев, достаточно нескольких классов, описывающих выражения в этой системе. А у вас зачем-то — шаблоны, стратегии, мучения с кучей конструкторов…
А разве не видно, зачем это? Причину же я указал. Точнее, описал задачу: нужно создавать условия, ничего друг о друге не знающие, без использования ручного выделения памяти и без передачи указателей.

И никаких там мучений с конструкторами нет, там вообще нет ничего лишнего, всё для чего-то нужно.

Так все-таки, почему мое решение — не ООП?
Потому что ваша задача — не ООП, а на синтаксис языка. «Как так извернуться, чтобы не передавать указатель».
То есть, стратегии — это не ООП, это синтаксис такой. И отброшенные решения (наследование то же) — это не ООП. Хорошо, я готов принять вашу формулировку, но только с условием: вы признаете, что это все-таки ООП в рамках языка С++.
Понимаете ли, принимаемые вами решения (и стратегии, и отбрасывание наследования) как раз противоречат ООП (в особенности — отбрасывание наследования). А чем они обоснованы? Синтаксическими ограничениями, которые вы сам же себе и поставили.

Понимаете, ООП-решение этой задачи — нормальное дерево наследования. А то, что делаете вы — это отказ от этого наследования ради использования смарт-пойнтеров или чего там еще. В то время, как в любом другом языке с нормальным динамическим выделением памяти, или у любого другого программиста, которому удобно писать выделение памяти по-другому, решение будет иным, нежели у вас.
Я вам твержу, что я не отбрасываю наследование, а очень даже применяю. Есть у меня в библиотеке и чисто абстрактные классы, и передача по указателю, и наследники, реализующие тот же интерфейс, но по-разному, полиморфно. А вот в этой конкретной задаче мне нужно было не допустить указатели, поскольку этим станет неудобно пользоваться.
Вот я и говорю, что ради отказа от указателей вы парадигмы ООП послали к черту.
Никуда я их не посылал. Я применяю то, что нужно, и где нужно — ни больше, ни меньше.
Вот только ООП здесь уже не при чем.

Вам захотелось сделать — вы сделали шаблонами. Захотелось — сделали наследованием. Захотелось — чем-то еще. Нет целостности подхода.
С таким подходом вы далеко не уедете.
Ну, я, по крайней мере, написал одну работающую систему описания критериев.
У меня тоже есть чем похвастаться, — но я, как уже сказал, применяю то, что нужно там, где нужно, чтобы добиться какого нужно эффекта. И не теряет от этого моя архитектура стройности.
Я думаю, lair имеет ввиду примерно вот что:
предложенное решение демонстрирует не пример решения задачи в ООП стиле, а пример решения задачи ВАМИ, на языке С++.
Решал бы эту задачу кто-то другой — решение вышло бы иным. Решали бы эту задачу вы, но на окэмле каком-нибудь — решение вышло бы иным.
А раз так, то здесь никакое не ООП, а просто-напросто обход косяков с++ с целью получить некий желаемый результат.
То есть из этой статьи я бы не делал никаких обобщений типа «смотрите как можно/нужно рассуждать при использовании ООП».
Да, приблизительно так. Спасибо.
Query().raw( 'select * form' ).table( 'xxx' ).raw( 'where x=' ).value( 5 ).toString()
Я, в принципе, могу еще потыкать в дырки в вашей реализации, но самую главную указали выше — expression trees придумали не просто так. И на них это все прекрасно реализуется.

А вся ваша борьба — это не ООП, это борьба с синтаксисом языка, который чего-то не умеет.
В языке операторы перегружаются, вообще-то.

recordset x = fetch(select(table, table.def.column_a == "Y" && table.def.column_b == date("2011-01-01"))));

Я знаю, спасибо. Как это связано с моим комментарием?
При всей моей нелюбви к C++, язык многое умеет.

И уж сделать на нем генератор запросов не хуже чем в SQLAlchemy труда не составляет. См. также Spirit, например. Там и более сложная задача решается.
Так вы это расскажите автору топика, а не мне.
А это не вы написали разве:

«А вся ваша борьба — это не ООП, это борьба с синтаксисом языка, который чего-то не умеет.»

Язык умеет.
Ну вот например, автор не знает, как сделать так, чтобы одновременно было и простое наследование (And и Or наследуют от Bool, конструкторы принимают Bool), и одновременно простое управление памятью. Вот с этим он и борется мучительно.
борьбой это становится для того, для кого это сложно. Автор показал, что это просто.
Что-то я не вижу простоты системе классов аж вообще. Как уже неоднократно говорилось, все это прекрасно делается банальным деревом наследования Expression — BooleanExpression — AndExpression/OrExpression. Безо всяких шаблонов.

Вот это — просто. И понятно. И расширяемо в любой момент в любую сторону.

(нет, ну правда, AST придумали не на пустом месте)
А зачем вам, как пользователю моей библиотеки, знать про то, как реализованы классы QstAnd и QstOr? Да пусть там будут хоть сто раз шаблоны, вы-то этого не увидите! Вы всего лишь берете и вставляете конструкторы классов один в другой, и не надо никаких передач по указателю, и памяти выделять тоже не надо!
Я просто думаю не только о пользователях, но и о программисте, который придет завтра расширять эту библиотеку и дописывать в нее QstNot.
А я думаю, прежде всего, о пользователях, потому что знаю: когда мне понадобится QstNot, я напишу его без всяких проблем. Ибо QstNot — унарный, и для него будет просто класс. Ни в какое наследование или в шаблоны его вставлять не нужно.
Собственно lair пытается сказать что когда вы уйдёте на другую работу, то принятый на ваше место программист будет долго соображать как добавить в вашу библиотеку QstNot или скажем QstXor.
Моя разработка открыта, лежит здесь: sourceforge.net/projects/qstsqltools/. Мои контакты известны. Если к тому моменту, когда мне понадобится XOR, я его еще не сделаю, разработчик смело может обратиться ко мне.
Т.е. как только кому-то понадобится внести в ваш проект изменения — он должен обращаться к вам, т.к. самостоятельно человеку будет очень сложно разобраться в таком коде?

По моему это не есть хорошо. Ну кроме случаев когда изначально ставилась цель затруднить модификацию системы.
А так же разработчик смело может внести изменения в код, поскольку лицензия GPLv3. В моем коде разобраться относительно легко для тех, кто знает С++ и ООП. В статье я тоже ничего сверхъестественного не сделал, ну, разве что финт с наследованием от своего же параметра… Если разработчик захочет разобраться, то он разберется.

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

Вы голословны, друг мой. Я не могу воспринимать всерьез ваши слова. Вы пытаетесь обвинить меня программистских грехах, которых еще даже нет в релизе. Я думаю, вам лучше подождать, когда я выпущу release, и тогда, пожалуй, критикуйте хоть до посинения. А сейчас можете взять либо последнюю бету 0.3 версии, либо pre-alpha 0.4, — только если вы составите претензии по ним, а я вдруг выпущу версию, к которой эти претензии не подойдут, я вас даже не пожалею.
«Два умных разработчика всегда найдут способ договориться.»
Особенно когда один из них недоступен.

«Я думаю, вам лучше подождать, когда я выпущу release, и тогда, пожалуй, критикуйте хоть до посинения.»
Вот именно об этом я и говорю, да. И комментарий про «когда буду думать над Not, тогда и» ниже — тоже об этом же.

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

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

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

Во-вторых, как это не надо вставлять в наследование? Поскольку Not — логическая операция, даром что унарная, она должна использоваться везде, где раньше можно было использовать And и Not.
Ну, возможно, и так. Когда стану думать над Not, обязательно вам сообщу… если не забуду.
Но статья-то не об этом была. Пофиг вообще, что там у него за задача была. Я понял, что смысл статьи — возможность мыслить и дизайнить с использованием ООП вне зависимости от того, какие возможности для реализации даны. ООП — образ мышления. Примерно как Дзен. Или как инь-ян, которые воплощаются в каждой мельчайшей части мира.

И сравнение с музыкой тут очень уместно. Музыка — это тоже набор паттернов. Даже сами ноты можно рассматривать как паттерны. Сыграйте музыку на гитаре, оцифруйте ее как миди — и потом можно будет проиграть ее голосом любого инструмента. Можно даже сразу играть на гитаре, а из колонок будет слышен саксофон или арфа =)

Вот, посмотрите этот видик с ютуба, может натолкнет на какие мысли: www.youtube.com/watch?v=9VymAn8QJNQ&feature=related
«Я понял, что смысл статьи — возможность мыслить и дизайнить с использованием ООП вне зависимости от того, какие возможности для реализации даны.»
Мы, собственно, о том и спорим, что тут превалирует — ООП или желание получить конкретный синтаксис любой ценой.

«Музыка — это тоже набор паттернов.»
Нет.

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

Иными словами, я не уловил вашей метафоры, объясните, пожалуйста, еще раз.
1. «Музыка — это тоже набор паттернов.»
Нет.

Человеческий мозг мыслит паттернами. Эээ, это ко всякому НЛП и Фрейдам. Можно почитать каких-нибудь исследователей типа Грегори Бейтсона, есть у него классная книжка «Шаги к экологии разума».

Музыка (нотная запись или тактильные команды движения пальцами) — результат работы человека, если скиллов по созданию музыки. То есть код, сгенерированный группой паттернов под названием «скиллы по созданию музыки». Из чего следует что музыка — набор паттернов. Следовательно и сама музыка — набор паттернов.

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

Вывод: музыка — набор паттернов.

2. «Мы, собственно, о том и спорим, что тут превалирует — ООП или желание получить конкретный синтаксис любой ценой.»

Мне собственно всё равно, о чем вы спорите с топикстартером =) Потому что я усматриваю в вашем споре совсем другой аспект.

Есть высокоуровневый язык паттернов ООП. Не надо себя обманывать, язык на котором пишется программа в мозгу человека — именно «ООП», а его элементы — скажем, паттерны ГоФ. Каждый из этих элементов может быть реализован на широком спектре различных языков компьютерного (и даже не компьютерного!) программирования. В частности. ее можно оттранслировать на С++. Или на Жаву. Или на Шарпы. Абсолютно неважно.

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

И у паттернов ООП есть свой конкретный синтаксис, который мы должны форсировать любой ценой, чтобы программа на паттернах ООП заработала. Да, на С++ иногда можно сделать лучше, чем в указанном ООП-майндсете. Да, на ассемблере иногда можно сделать лучше, чем на С++. Дикая потеря производительности оправдана тысячью разных причин, которые тысячу раз описаны в соответствующих книгах.
Извиняюсь, писал в полусонном состоянии, сделал стопитьцот грамматических ошибок, один раз повторил предложение «следовательно и сама музыка». Жуть.
Не переживайте. Даже в полусонном состоянии вы написали все правильно.
«Человеческий мозг мыслит паттернами.»
Я так думаю, что это вопрос, кого как учили. Я привык считать, что как человек мыслит, до сих пор никто не понимает по-настоящему. Паттерны человек воспринимает, использует для упрощения окружающего мира и собственного мышления.

«То есть код, сгенерированный группой паттернов под названием «скиллы по созданию музыки». Из чего следует что музыка — набор паттернов.»
Очевидно, что нет. Даже если считать навыки по созданию чего-то группой паттернов (что уже само по себе не верно), как мы все понимаем, результат работы группы паттернов никак не обязан сам быть набором паттернов.

«встроенные в организм человека системы распознавания паттернов уловили некоторый знакомый «рисунок», знакомый паттерн, и поставили ему в соответствие слово «музыка».

Вывод: музыка — набор паттернов.»
Тоже излишне быстрый вывод. Тот факт, что музыка содержит закономерности, узнаваемые слухом, совершенно не означает, что она является только набором таких закономерностей.

«И у паттернов ООП есть свой конкретный синтаксис, который мы должны форсировать любой ценой, чтобы программа на паттернах ООП заработала.»
Удивительно, но я с вами согласен. А вот топикстартер от этого синтаксиса уходит.
«Даже если считать навыки по созданию чего-то группой паттернов (что уже само по себе не верно),»

именно это предположение очень сильно повысило эффективность систем обучения людей.

у вас есть предположение круче этого?

Только чтобы одинаковая терминология: паттерн есть внешнее проявление какого-то процесса, некий сингнал, который возникает одновременно с проходящим процессом.

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

Применительно к музыке. Мы следуем на логическом уровне какой-то последовательности паттернов (взять листочек, нафигарить нотный стан, поставить карандаш на вторую линеечку..), и в это время соответствующие бессознательные процессы делают что-то такое, что потом назовется «музыка». Взять листочек и нафигачить нотный стан — это не само создание музыки, но определенно паттерн (или часть паттерна ))) «композитор».

В обратную сторону, восприятие паттернов есть вообще нечто фантастическое, но как это происходит абсолютно неважно. Достаточно что оно работает, а на выходе получаются паттерны. Человек смотрит на Великого Учителя, показывающего как правильно делать лоу-кик. У него не получается первый раз, третий, десятый, сотый, но раз за разом система распознавания копирует учителя лучше и лучше, и в конце концов ученик начинает делать в точности как учитель. Ученик не знает — почему так, но оно и не нужно, ибо работает. Если спросить ученика потом, что он делает, он ответит какую-то белиберду (словесную репрезентацию паттернов, которым он следует): «я соблюдаю баланс инь и ян», «я объединяюсь с небом и землей», «моя нога становится железной».

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

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

(может оформить это как топик и пообсуждать там уже со всеми?)
«Только чтобы одинаковая терминология: паттерн есть внешнее проявление какого-то процесса, некий сингнал, который возникает одновременно с проходящим процессом.»
А. Привет бихевиоризму.

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

То есть, вы можете называть паттернами что угодно, конечно.
В каком месте я подменил изначальное определение? Скопипастите кусок, плз ))
Просто данное вами определение не имеет отношения к тому, что «нормальные люди» понимают под словом «паттерн». Ваше определение подходит вообще к любой деятельности, и, как следствие, бессмысленно.
Это классическое определение бихевиоризма )) Скорее всего, изначальное определение.

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

Но эта модель абсолютно бесполезна для собственно процесса распознавания паттернов :(( Пока что приходится смириться, что познание чего-то действительно нового — это искусство и магия.
Просто в этом смысле паттерны — все, и сравнивать музыку с программированием настолько же осмысленно, насколько осмысленон сравнивать программирование с копанием ям: и то, и другое — бихевиористские шаблоны, несомненно.
На community.livejournal.com/code_wtf/ есть чувак, который часто сравнивает работу программиста с работой сантехника =)))
В «реальном мире» такие люди тоже есть… всякие руководители. Сделать до обеда сайт — это примерно то же, что завертеть до обеда ржавую трубу, или там выкопать большую яму около дома. В терминах управления проектом. Фигачим диаграмму Ганта, распраделяем ресурсы и пошел, пошел копать сайты от забора и до обеда :)
>> Я понял, что смысл статьи — возможность мыслить и дизайнить с использованием ООП вне зависимости от того, какие возможности для реализации даны.

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

Но ведь «подогнать возможности языка к желаемому синтаксису», это ж очень частая задача.

Если бы, например, это был Java, я бы тут же припомнил паттер Singleton. Ну не позволяет Java делать глобальные переменные. Поэтому нужно как-то так извернуться, чтобы таки сделать эту глобальную переменную. Первая мысль, конечно, просто передавать массив глобальных переменных вообще во всех функции, которые только существуют в программе. Но это некрасиво. Поэтому, есть вот такая запись: http://habrahabr.ru/blogs/complete_code/27108/, которая по духу эквивалентна объявлению глобальной переменной. Это как бы пример «подогнать возможности языка к желаемому синтаксису» №1 :) У меня на создание синглтонов так вообще клавиатурный шорткат стоит, чтобы каждый раз весь этот бред заново не писать.

Ну, или чистый Си. Задача — написать программу на Си (например, по причинам хорошей переносимости). Но вот беда: наша задача формулируется в объектных терминах (банковские операции, например), а язык Си формально не поддерживает ООП. Но это не беда! Фигачим в структуры указатели на функции — и это уже почти классы. Фигачим таблицы виртуальных функций (да, ручками) — и вот уже работает перегрузка. Таким образом на Си можно реализовать что угодно, включая самые извращенные идеи по поводу правил множественного наследования или уровней доступа (public, private, protected, friend, visible-for, что хочешь, чего нет и не будет в той же Java). Если всё это задолбаешься писать ручками, можно написать кодогенератор (писать на чем-то похожем на Objective-C, а реальный код получать на чистом ANSI C'90).
[offtop]Забиндить синглтон это круто. Неужто так часто приходится им пользоваться?? [/offtop]

То, что вы написали, я понял. И с этим согласен. Однако почему же у значительной части прочитавших этот топик так же как у меня после его прочтения возникает некоторое недоумение — непонятно, как соотносится эта мысль, высказанная, в общем, в первых абзацах, и конкретное (не самое удачное, но имеющее право на место под солнцем) решение, которое автор рассматривает ниже?
По-моему, сама задача и способ её решения никак не подтверждают вот эту вот идею про то, что «ООП философия» и всё такое прочее.
ХЗ. Если автор вообще еще читает комменты, может быть пояснит более понятным языком, какие такие возможности он у себя в голове держит, что они эмулируются этим странным способом ;)
Комментарии я очень даже читаю :)
«какие такие возможности он у себя в голове держит, что они эмулируются этим странным способом»

Я не очень хорошо понял это предложение, но вот ответ.

В моей библиотеке есть концепция DFD — Declarative Field Descriptor. По ней чтобы сгенерировать SQL-запрос, нужно составить пакет полей, описывающий основные части запроса. (Сама концепция спорная, но мы ее сейчас обсуждать не будем). Например, для простого SELECT-запроса

SELECT ID, PhoneNumber_ID, Name, Number
FROM ic_vCabinets

я мог бы составить такой описатель:

QstBatch batch;

batch << «ic_vCabinets»
<< QstField(RolePrimaryKey, «ID»)
<< QstField(«PhoneNumber_ID», FieldInvisible)
<< QstField(«Name», FieldVisible, «Название», 100)
<< QstField(«Number», FieldInvisible, «Телефон», 80);

Как видите, классы QstField создаются прямо перед отправкой в batch, и оператор "<<" помогает хорошо их расположить. Теперь у меня появляется потребность в более сложных запросов, где есть те же многоуровневые условия. Представим, что было бы, если бы я передавал указатели:

QstBatch batch;

QstAnd and1(<условие1>, <условие2>);
QstOr or1(<условие1>, &and1);

batch << «ic_vCabinets»
<< QstField(RolePrimaryKey, «ID»)
<< QstField(«PhoneNumber_ID», FieldInvisible)
<< QstField(«Name», FieldVisible, «Название», 100)
<< QstField(«Number», FieldInvisible, «Телефон», 80)
<< QstWhere(&or1); // QstWhere придуман здесь. На самом деле пока механизма нет.

Вот зачем мне нарушать стройную картину вынесенными за пределы блока объектами and1 и or1? И совсем уже плохо, если я буду внутри этого блока вставлять оператор new, потому что генерация запроса по описателю происходит очень много раз. В моем же случае все классы создаются в блоке простым вызовом их конструкторов. Это и для форматирования удобно, и по части работы с памятью безопасно.
«Неужто так часто приходится им пользоваться??»

Нет, я его (и еще несколько конструкций) забиндил чтобы выпендриться (сам перед собой) Жму кнопку, и генерится 100500 бреда. Еще генерирование геттеров-сеттеров для тучи полей. Чувствуешь себя после этого доктором Зло, только что совершившим много тяжкого зла, написавшего в одно прикосновение десять километров мусора :) Логически-то понятно, что если конструкция генерится одним нажатием кнопки (плюс парой параметров в диалоговом окне), то и описываться оно должно одной строчкой.

А еще, прикольно бы сделать язык, в котором first-class objects были не, скажем, переменные или объекты, а именно паттерны и рефакторинги. Может, не только для лулзов, а еще и пригодится кому. (пользуются же люди распределенными VCS :)
Вы каких подтверждений хотите? Как я могу вообще доказать, что ООП — и философия тоже? Не представляю. Могу лишь приводить статьи, подобные этой, где дается задача, дается ход рассуждений с перебором возможных вариантов и отбрасыванием тех, которые неугодны. Принципиально ничего не изменится: кто-то посмотрит ход рассуждений и скажет, что это интересно; кто-то даже читать не станет, а полезет поливать грязью; ну и огромной части народонаселения вообще будет плевать на мои излияния. Кому тут что докажешь? Вы либо верите, либо нет, — но пока никто в этих комментариях не доказал, что ООП — не философия. Они там доказывают лишь, что автор — глупец и с ООП не знаком. Негатива-то, согласитесь, прет больше, чем позитива, и нет, чтобы подумать о том, какие возможности есть в том же С++, — на примере показанных, — вместо этого комментаторы отправляют меня к умным книжкам. Если бы они еще знали, сколько я умных книжек и каких прочитал, может, еще бы подумали.
>> Вы каких подтверждений хотите? Как я могу вообще доказать, что ООП — и философия тоже?

Если так, то зачем вообще было писать статью.
Вы не кипятитесь, я вас ни в чём не обвиняю, а скорее даже поддерживаю.
Но прежде чем писать статьи подобные этой, мне лично кажется, что надо «познать» ООП во всех, или хотя бы в иных его проявлениях. Не с++ единым, так сказать.
Познакомились бы вы с java или шарпом, ocaml, тогда статья могла бы быть иной. Думаю, более интересной.
То есть, топики-ссылки про термины ООП и девушек, набирающие под +80, вам нужны, а статьи подобные этому — ни рыба, ни мясо? Вот что меня возмущает больше всего. Спрашивается: кто больше знает ООП: я или те авторы?

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

> «где справедливость?»

И тут кагбэ сама собой напрашивается рифма…
Вот два топика «про ООП», хотя на самом деле лишь про термины. Толково объяснено, да, но не более.

habrahabr.ru/blogs/edu_2_0/87119/
habrahabr.ru/blogs/edu_2_0/87205/#habracut

Вот топик, хоть и заминусованный, про ООП и девушек:
torsion.habrahabr.ru/blog/91709/

А вот это хороший топик:
habrahabr.ru/blogs/oop/38323/#habracut
«не более чем попытку подогнать возможности языка к желаемому синтаксису»

Чем вам примеры помешали? Первая часть есть, — вот и пожалуйста, можно ее обсуждать отдельно. Вторая часть есть, — ее тоже можно обсуждать отдельно. И есть вся статья. Как вы понимаете, кто хотел, тот о том и задумывался.
… а так хорошо начиналась статья…
> Вы можете выгнать музыканта из-за фортепиано, — он возьмет флейту. Отберите флейту, — музыкант натянет струну и изобразит мелодию. Завяжите ему руки, и он просто станет напевать: музыка в нем самом.

Но ноты то останутся. Так же и классы не бывает ООП без классов.

В ваше решеие не вчитывался — многовато букв — но для кондишнов диаграмма классов была бы очень простой: абстрактный кондишн (с методом превращения в текст), от него наследуются простой кондишн и абстрактный композит кондишн. Абстрактный композит кондишн реализуют ор-кондишн и энд-кондишн. Так что в простой кондишн можно засунуть любой равно-не равно-больше-меньше, а в любой композит кондишн н-ное кол-во любых кондишнов, в т.ч. тоже композитных. Тоесть A or (B and (C or D or E)) было бы 5 интсансов симпл кондишнов — A, B, C, D, E, потом C,D,E запихиваются в ор-кондишн 1, B и 1 запихиваются в энд-кондишн 2, и А и 2 запихиваются в ор-кондишн 3, который потом отдаётся куда надо.
Как превращать в текст простые кондишны понятно. Желательно при этом сразу заключать их в скобки.
С композитными кондишнами всё еще проще (-: — тоже в скобки целиком, а каждый засунутый в него кондишн внутри скобок через ор/энд. Вот и всё.
А вот я вас спрошу, как «кондишины» запихивать в другие? С помощью указателей на них? Или нет? Что мы передаем в этом случае? Учтите, что передавать указатели мне нельзя, причину я в статье написал. Я хочу создавать классы без выделения под них памяти. Вот так:

A a("...", B("..."));

а не так:

B b("...");
A a("...", &b);

и не так:

A a("...", new B("..."))
Конечно указатели на объекты (инстанции классов). Никак иначе. Вы будете выделять память полюбому если строите условия динамически. Да и что там памяти? В композит кондишнах — массив/список/вектор указателей. В симпл кондишнах — поле, тип условия, значение (типа «А < 5», где А — поле, 5 — значение, /=/!= — тип условия). Поле и значение и так записаны в память — вы же их откудато получаете динамически, в виде указателей на стринги скорее всего.

> Я хочу создавать классы без выделения под них памяти.
Детсад терминологии (-:
Память выделяется под объекты, «инстанции» классов.

> передавать указатели мне нельзя, причину я в статье написал
Можно и нужно. В статье вы написали только что вам не хочется это делать (-:
Вы не поверите, в ООП люди постоянно создают и убивают объекты (-;
«Вы будете выделять память полюбому если строите условия динамически»

А вот и не правда. Одно дело, когда я, программист, выделяю память, и другое дело, когда память выделяется косвенным способом и не мной. И можно вполне построить динамически любую сложную структуру данных, не выделяя при том памяти вручную. Подчеркиваю: я про ручное выделение памяти.

Как работают указатели, что есть строки и что происходит, когда мы вызываем конструктор, я знаю. Небольшая поправка: при передачи в качестве параметра строки:

A(«Jkfjkjf»)

я буду ловить ее «на том конце» с помощью Qt-класса QString. Меня совершенно не волнует, как этот класс выделяет память и где хранит строку. Я только уверен, что утечки у меня нет из-за того, что я забыл вызвать delete. За исключением, конечно, случаев, когда утечка есть в самом Qt, ну так потому я его и использую, что выходят новые версии с исправленными ошибками, что он удобен и приятен.

«Можно и нужно. В статье вы написали только что вам не хочется это делать (-:
Вы не поверите, в ООП люди постоянно создают и убивают объекты (-; „

Я сказал, что не хочу этого делать здесь, при сооружении условных конструкций. А так — у меня в библиотеке есть и два чисто абстрактных класса, наследники которых передаются в виде указателей.
Так вот. Все, чем вы занимались в статье — это обходили свое нежелание сделать new.
Нет, я решал поставленную задачу.

Так вы мне скажите, я преступно поступаю, если не хочу в коде писать new\delete? Так я еще больше вам скажу. Готов динамически выделять память только с помощью умных указателей. Либо там, где буду уверен, что она удалится, например, при использовании виджетов Qt.
Ну и написали бы на auto_ptr. Они сами удаляются, если я правильно доки читаю.
В этой задаче указатели ни к чему.
Да ну? На указателях получилось бы стандартное решение с наследованием Or и And от Bool. И все. Никакого цирка, простое и работающее решение.
И вы опять забыли условия задачи.
Отнюдь.

Вам не кажется, что мы по кругу ходим?
"
— Я не использую наследование, чтобы не выделять память явно.
— Возьмите auto_ptr.
— В этой задаче указатели ни к чему.
— Тогда можно было бы использовать наследование.
— Я не использую наследование, чтобы…
"
Прочитайте еще раз условие задачи:

Надо создать два класса, QstAnd и QstOr, чтобы можно было делать такое:

QstAnd(<условие>, QstOr(<условие>, <условие>))
QstOr(<условие>, QstAnd(<условие>, <условие>))

И запретить передачу по указателю, ибо чревато, длинновато и неудобно:

QstAnd(<условие>, new QstOr(<условие>, <условие>))

QstAnd andCond(<условие>, <условие>)
QstOr(<условие>, &andCond)
Ваша концепция очень хороша, из предположения что пользователь библиотеки будет использовать стандартный менеджер памяти. А если он возьмет какой-нибудь другой? А если напишет свой? А если пользователь библиотеки тоже будет писать библиотеку, тоже предназначенную для возможности работать со сменными менеджерами памяти? Это не клиентский код, это код библиотеки. Для библиотеки требование «используйте две с половиной фичи языка из ста возможных» может оказаться вполне стандартной штукой.
Так вы признаёте, что в этом решении очень много специфики с++?
Тогда насколько соотносится идея того, что это статья про ООП вообще, и то, что здесь куда ни плюнь торчат ++уши?
Скажите, почему, ну почему вторая часть статьи в вашем представлении отменяет первую? Первая — про ООП. А кто хочет, тот найдет и во второй части тот же ООП.
Не отменяет, я не так писал.
Боюсь, я не смогу ответить вам на этот вопрос. Я уже пытался, и lair пытался, но вы не понимаете то, что вам пытаются донести. Упреждая возмущение — вовсе не потому, что вы тупой. Скорее потому, что вы мало знакомы с другими языками, поддерживающими ООП.
Скорее потому, что вы и господин lair не приемлете мой подход как ООП. Почему — это уже другой вопрос. Скажу только, что мне это подозрительно в отношении вас обоих.
Уважаемый. Остановитесь на минуту и подумайте, как вы выглядите со стороны. Вам пытаются что-то объяснить, а вы напрочь отвергаете объяснения и говорите, что «кругом одни враги».
Научитесь нормально воспринимать критику. Хотя, кстати, этой самой критики в ваш адрес не так, что бы и много было.

Мне «ваш подход» к ООП как-то совершенно не охота обсуждать. Вполне адекватный подход, но, повторюсь уже в дцатый раз, этот подход такой потому, что вы выбрали с++. Так что скорее это не «ваш подход к ООП», а ваш подход к с++.
Вот я об этом и говорю: вы напираете на то, что я использую возможности С++, и почему-то не хотите считать это проявлением ООП.

Давайте закончим этот бессмысленный спор. Вы меня не убедили, я вас и не стремился убеждать, — я защищал свою позицию в том, что это — тоже ООП. Пусть даже в рамках С++, — но это совершенно несущественно. Или даже очень существенно, если вспомнить о том, какую роль играет С++.
Я нигде не утверждал, что это не ООП. Похоже, вы настолько обижены, что даже не утруждаете себя думать над тем, что вам пишут.
Я не обижен. «Это же не наш метод!» В худшем случае — возмущен.

Вы тут про ООП вообще и ООП в других языках говорите, а мне вот интересно, что вы ожидали увидеть в статье с тегами C++, ООП? Напрашивается здесь такая аналогия: рассматривает человек использование Интернета, скажем, в Opera с ее замечательным кэшем, а ему говорят, что какой же это Интернет, возможности Opera используешь, дорогой мой, а вот в FireFox…
Я на теги не смотрел. а плюсовая привязка из заголовка статьи никак не следовала.
Поймите, всё, что вам пытаются донести, это примерно следующее (сформулирую с помощью так любимых вами аналогий): вы научились водить передний привод летом, и потому пишете статью с заголовком «мастерство вождения». Но вы же не пробовали водить задний привод, не знаете особенностей зимней езды.
С ООП такая же ситуация. Вы громко пишете про «философию», но знаете только один язык?
Я знаю несколько языков, это раз. И еще я знаю, что все, что я сказал про философию, верно и для других языков, это два.

Я больше не буду отвечать вам в этом топике.
Я так понял, топикстартер пишет библиотеку, в которой нельзя использовать указатели чтобы не ограничивать конечного пользователя библиотеки. Это хорошо.
Ох, как бальзам на душу… Спасибо вам.
UFO just landed and posted this here
… так то нормальные языки. А у людей тут C++, все такое, «не использовать указатели».
> Одно дело, когда я, программист, выделяю память,
> и другое дело, когда память выделяется косвенным способом и не мной.
Память то выделяется так или иначе. В чём вин? В том что вместо напрячся (не особо то и напряжно вообще говоря) проконтролировать удаление объектов вы напрягаетесь написать не по человечески?
В чём проблема для композит кондишна оверрайднуть метод (деструктор или что там) с удалением все своих субкондишнов? Вот и все дела — в конце как кверю «отрендерили» в текст колаете кондишну 3 делит, а он уже и дерево своих субкондишнов рекурсивно потрёт.
А знаете ли вы, скольких проблем я избегаю, отказываясь от необдуманного new в коде? Да, я понимаю, что вы хотите сказать. Можно создать механизм, и оно само себя убьет. Все так. Но проблему подсчета ссылок никто не отменял. Пока вы будете отлаживать и искать утечки или неожиданные краши, я в этой части своей программы никаких проблем испытывать не буду. Во-первых, оно выглядит так, как я хотел, и работает прозрачно.
P.S. Вообще надо рассматривать смысл создания дерева кондишнов виде объектов в принципе. Билдер какой-нибудь который в строчку всё популейтает может быть более уместным если кондишны строятся в одном месте и далее с ними никаких манипуляций не происходит. Меньше оперативки будет кушать. Но зато и изменить что-нибудь будет сложнее.
Манипуляции происходят. Вы можете на форме задать кнопочку, которая меняет функтор. Я так делаю очень приятные фильтры. Удобно и просто.
Вот повесили бы на кнопочку лиснер который апдейтил бы соответствующий кондишн (который был бы где-то засунут субкондишном в ваш «общий» кондишн) — было бы элегантно (-:
Я не знаю, что такое «лиснер», но именно так и происходит: указатель передается в условие на место параметра «CompareFunctor», и генерируется новый запрос.
Эээ… Вы имеете в виду реакцию на нажатие кнопочки? Или я чего-то не понимаю?
> Я не знаю, что такое «лиснер»
Listener
P.S. Терминология правда джавишная, вообще это observer pattern.
«создавать классы без выделения памяти» — это что за ересь? Нельзя ничего создать, не выделив память.
Уточню: создать классы без ручного выделения памяти. Вовсе не ересь.
Я все понимаю. И работа проделана неплохая. И ORM это безусловно хорошо, само по себе. Но, черт возьми, я попытался прочитать ваши ORM-SQL-конструкции и как же тяжело читать такой запрос…
Когда ты пишешь это сейчас — хорошо. Но, вернувшись через год, вашему мозгу понадобится время чтобы распарсить ORM-SQL в SQL, а потом и сам SQL в логику.

Я считаю, все эти ORM-ные штуки нужны там, где нужна абстракция:
  1. а) от БД
  2. б) от запросов (генерирование структуры запроса на лету, не оперируя конкатенациями строк)


В остальных случаях должен приментся стандартный синтаксис SQL.
А я и не спорю.

Только статья не про мою ORM и вообще не про ORM… А про конкретную задачу, ООП и красивое решение. Или вы не находите его красивым?
Вашу задачу оно решает, работать с этим удобно? Если да, значит вы все сделали правильно. К черту красивость.
Я точно сказать не могу, насколько это удобно, говорю за себя: я рад, мне — хорошо. Считаю, что ради небольшого профита стоило так крепко задуматься.
Современное ООП — это не просто инкапсуляция, полиморфизм и наследование (от которого, кстати, больше вреда, чем пользы). Современное ООП — это паттерны, такие основные принципы как принцип открытия-закрытия, инверсии зависимостей, подстановки Лискоу и так далее. Без их соблюдения обычно получается процедурный код с использованием объектов.
Это был комментарий к вступительному слову, озаглавленному «Философия ООП» :)
Безусловно, при неверном применении технологии от нее всегда больше вреда нежели пользы, согласен.

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

Выстроить объектную модель в унисон логической модели не всегда просто, иногда невозможно, а иногда и вовсе не нужно. Спроектировать адекватно — вот задача. Применить классы там где нужно, и отказать от них там, где они лишние. Это сложнее чем просто написать код.
Мне одному показалось, что сравнение с музыкантом, да и с музыкой, притянуто за уши? :)
Нет, не вам одному.
> Хотите что-то нестандартное? Тогда вам — в музыкальную школу. В ней вас научат играть на разных инструментах и правильно сочетать их, вы узнаете про паттерны проектирования, шаблонные классы, абстрагирование от алгоритмов, сокрытие информации, и много чего еще. Вы вдруг поймете, что сочинять мелодию — тоже искусство.

У меня для вас плохие новости… В 99% музыкальных школ не учат сочинять музыку! В музыкальных школах дается только обезьянная наработка техники умение разбирать сложные партитуры. И еще дают абстрактную теорию музыки в виде сольфеджио, но это не суть ООП… блин, то есть, музыки.
Так я и не говорил, что вас научат сочинять музыку. Вам покажут аккорды и как их соединять. Сочинять мелодию — это же творческий процесс. Любому творческому процессу, я считаю, научить нельзя. Можно только самому научиться.
Вы ошибаетесь дважды.

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

Второй раз — в том месте, где думаете, что творческому процессу нельзя научить. Можно. Кафедра композиции для этого придумана.
[Оффтопик]

Ну попробуйте научить даже не бездаря, — среднего человека. Он вам насочиняет, да. Диджеи, — вон, — «сочиняют». Только это все не музыка, поделки это. Вы когда-нибудь классику слышали? Вот это — музыка. А вот были же великие композиторы-самоучки. Впрочем, были великие и те, кто закончил музыкальную школу. Только им школа дана была в дополнение, учились они сами. Ибо это творчество, его нельзя нанизать извне.

[/Оффтопик]
А что пробовать-то? Это стандартная программа обучения в музыкальном училище, второй курс самое позднее.

Другое дело, что не надо путать «творческую деятельность» и произведение искусства.
Слушайте, хватит передергивать мои слова. Творческая деятельность и произведение искусства связаны как причина и следствие. Не всегда творчество приводит к появлению произведения искусства, но всегда произведение искусства — результат чьего-то творчества. Я ничего не путаю. Это вы пытаетесь меня запутать.
Вот именно поэтому научить творческой деятельности можно, а научить писать произведения искусства — нельзя.
И что? Где я это отрицал? Мои слова:

«Так я и не говорил, что вас научат сочинять музыку. Вам покажут аккорды и как их соединять»

говорят, что вас научат процессу, и только. Даже не так: вам покажут некоторые правила и принципы этого процесса, отнюдь не всё!

«Ну попробуйте научить даже не бездаря, — среднего человека. Он вам насочиняет, да. Диджеи, — вон, — «сочиняют». Только это все не музыка»

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

Ваша ошибка в том, что вы, говоря «музыка», думаете «Токката и фуга ре-минор», а говоря «стихи» думаете «шедевры».
Я привык равняться на самые лучшие вещи.
Забыв, видимо, при этом, что сначала учатся писать обычные.
Почем вам знать, что я помню и чего не помню?
Ах, вот что…
«Любому творческому процессу, я считаю, научить нельзя».

Ну да, если так, то я ошибся в этом. Точнее, неправильно выразился: нельзя научить создавать произведение искусства.
Sign up to leave a comment.

Articles