Pull to refresh

Comments 135

UFO just landed and posted this here
Логика странная. В объект собираетесь сохранить хранилище?
Ага, я тоже так подумал вначале :) Но ниже объяснение…
В Ruby On Rails используется Active Record — соответственно o.save(); В DJango тоже насколько я знаю. И вообще Active Record сейчас он часто используется в динамических языках. В Java же на практике он реже используется так как хорошей подходящей библиотеки нету.
Что тут странного? Если объект умеет сохраняться (метод Save в наличии), значит он должен знать о хранилище.
Если у нас может быть более 1 хранилища и на этапе создания мы не знаем в какое хранилище мы будем сохранять объект, то естественно указать это при сохранении.

Такая запись не менее логична, чем myObject.Save(). Разница только в моменте указания хранилища.

Мне больше нравится storage.Save(myObject), даже не смотря на опыт работы с AR.
объяснение интересное, но с точки зрения объекта:
«завернитесь в белую простыню и следуйте на кладбище»?
Тогда просто myObject.Save() — «завернитесь и ползите», без указания куда.
Действительно, а то второй вариант не полноценен, подразумевает дополнительные действия для привязки хранилища к объекту.
Прошу пояснить почему так или иначе, или предложить какие есть еще варианты?
UFO just landed and posted this here
Меня интересует интуитивные (естественные) представления программиста, а не его логический анализ. А философию можно накрутить на любой вариант. И ИМХО, это не зависит от области применения.
UFO just landed and posted this here
разумно, но с нотацией myObject.Save(storage) — ИМХО, перебор :) Хранилище объект может сам найти, и передавать его нет необходимости.
UFO just landed and posted this here
Если вы не пользуетесь глобальными переменными, то не может.
Есть еще статические переменные. Можно в конструктор объекта передать хранилище. Объект можно зарегистрировать в фреймфорке, который по определенной логике решит в каком хранилище сохранять объект. Варианты есть.
UFO just landed and posted this here
Статическая переменная, регистрация в фреймворке — это все глобальные переменные.
Передача в конструкторе не подпадает под вашу цитату: "передавать его нет необходимости."
> передавать его нет необходимости

Относилось только к самому методу Save
Да неважно где: в конструкторе, сеттере, непосредственно методе. Это не меняет сути взаимодействия этого объекта с внешним миром.
Можно выделить 3 типа взаимодействия:

1. myObject обращается к storage через global state (Глобальные переменные, Синглтоны, статические методы и переменные)
2. myObject обращается к тому storage который был ему передан (конструктор, сеттер, аргумент метода)
3. storage обращается к myObject

В опросе варианты myObject.Save(storage) и storage.Save(myObject) однозначно определяют способ взаимодействия.
«myObject обращается к тому storage который был ему передан (конструктор, сеттер, аргумент метода)»
Я хочу заметить, что это неравнозначные варианты. Хранилище, переданное через конструктор (по идее) не должно меняться во время жизни объекта, а значит, мы не можем решить, куда мы сохраняем объект, в момент его сохранения.
Верно. Но это уже вопрос и к реализации окружения: «Кто знает о storage? Тот, кто создает myObject, или тот, кто его сохраняет?»
Это вопрос в первую очередь к задаче — а как мы определяем, куда надо сохранить объект.
Кстати Фаулер в паттерне ActiveRecords как раз и использует статические члены
как-то привык что бизнес-объекты должны быть без поведения, поэтому голосую за первый вариант.
думаю еще myObject.Save(storage) как вариант можно вставить или даже заменить второй пункт.
Выбрал второй вариант, он мне кажется более естесственным. Покажу на примере людей:
storage.Save(myObject)
myObject.Save()

Допустим myObject это человек, назовем его Боб, а storage это что-то глобальное, например Вселенная.
Мне удобнее и логичнее обратиться к Бобу напрямую и сказать Боб.Заткнись(), чем говорить Вселенная.скажиЗаткнись(Бобу). Но это мое виденье конечно, первый вариант тоже имеет право на существование. :)
Если это маппинг объекта на базу, и мы изменяем свойства — вариант два.
Если storage это какое-то отдельное логическое хранилище (суть, не все объекты класса myObjectClass хранятся в storage) — вариант один.
UFO just landed and posted this here
Проголосовал за первый вариант.
Бизнес-объект не должен знать в какой физической среде он может быть сохранен. БД это или xml-файл, или property-файл, бизнес-объекту должно быть все равно. Абстракция хранилища должна записывать объекты, тогда ее можно будет легко сменить.
Согласен. Есть стойкое ощущение, что большинство (надеюсь) java и .net девелоперов проголосвало за 1ый вариант.
А большинство веб-разработчиков — за второй. В вебе ActiveRecord сильно популярнее остальных подходов.
Существую вариации реализации, когда не смотря, что применяется запись myObject.Save() объект тем не менее не знает «в какой физической среде он будет сохранен». Поэтому как в том, так и в другом случае можно легко сменить абстракцию хранилища.
Всю жизнь пользовался второй нотацией.
Но проголосовал за первую — она более понятная.
А где же вариант с трекингом сущностей?

то есть просто:
... меняем объекты...
storage.Save();
Ты как маленький. Человек только открыл для себя паттерн Repository, а ты хочешь, чтобы он еще и про unit of work знал.
Что, уже и потроллить нельзя? ;)
Почему объект должен что-то знать о хранилищах?
Очевидно, что SRP, как и любой другой принцип не может применяться всегда и везде — есть ситуации, где он объективно хуже.
В вебе, например, ActiveRecord очень популярен. Видимо проявляется различие между софтом и вебом — софт может работать вообще без хранилища годами. Веб-скрипты же не могут — они постоянно работают с хранилищами, обеспечивая цикл load/save при каждом запуске.
Популярен он, потому что наиболее прост.
Зато он вызывает серьезные проблемы, когда вам нужны:
— вменяемое юнит-тестирование;
— poco-объекты;
— структура модели отличная от структуры таблиц в БД;
— действительно эффективные запросы к БД.
… а поскольку эти проблемы в веб-разработке возникают редко и далеко не на всех проектах — ActiveRecord и получил широкое распространение.
Паззл сложился, всем спасибо ;)
«Веб-скрипты же не могут — они постоянно работают с хранилищами, обеспечивая цикл load/save при каждом запуске. „
Это никак не объясняет, почему надо использовать ActiveRecord, а не Repository.
retran выше уже указал почему: ActiveRecord наиболее прост. Нарушаем SRP, соблюдаем KISS. Для проектов с невысокой сложностью (более, чем половина всех веб-проектов) получается заметный профит.
Классический архитектурный компромисс. Для «коротких» веб-проектов, которые пишутся недолго и в которых мало кода/сложной логики, ActiveRecord очень даже приемлем.
У меня есть подозрение, что дело не в том, что он приемлем, а в том, что он уже есть в том фреймворке, которым пользуется разработчик.

Как мы помним и понимаем, для «короткого» веб-проекта на .net ActiveRecord все равно никто не возьмет.
Фреймворки обычно вырастают из успешных проектов.
С этим никто не спорит. Но когда у тебя уже есть фреймворк, и в нем уже есть ActiveRecord, вряд ли кто-то будет искать другой паттерн работы с данными.
Не совсем правда. В тех же рельсах к 3-й версии все-таки развязали зависимость на ActiveRecord. Именно потому что многие хотят DataMapper.
Вам надо просто признать, что нотация myObject.Save() — более естественна для ООП. А все обозначенные якобы проблемы не являются таковыми.

Отсюда и выводы вы делаете совершенно оторванные от реальности.
«Вам надо просто признать, что нотация myObject.Save() — более естественна для ООП.»
Как уже неоднократно обсуждалось, это мнение беспочвенно и не аргументированно.
Опрос говорит об этом лучше чем все ваши софизмы
50/50? Это совершенно точно говорит о том, что ни один из вариантов не «естественней» другого.
Опрос Мы решаем когда сохранять состояние объекта (в базу данных, любое другое хранилище) исходя, говорит нам, что 2/3 хорошо видят, что причиной сохранения является бизнес-логика. 1/3 видит другие причины, из них думаю заметная часть работает с задачами, в которых собственно бизнес-логику вычленить затруднительно (системщики), правда и тут возможно заблуждение в том, что выполняя системные операции никто не смотрит на это как на бизнес-логику.

Этот опрос показывает, что из 2/3 тех кто согласен, что бизнес-логика есть причина сохранения + 0.5*1/3 (системщиков не видящих предмета бизнес-логики в своих задачах), тем не менее не все придерживаются нотации myObject.Save().

А это означает, что как минимум 2/3-1/2 нарушают принципы ООП.

Поэтому я и делаю вывод о естественности в рамках ООП основываясь на той части, которая не нарушает принципы ООП
Вы явно смешали все в одну кучу и пытаетесь обвинить 2/3 разработчиков, что они не понимают ООП? Не вышло.
Я никого не обвиняю, опрос — это вещь статистическая. Я лишь отмечаю статистические несоответствия.
Миллионы мух не могут ошибаться. Помните? ;)

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

Хоть я и не согласен, скажем, с каким то из вариантов, и пусть даже 25% просто заблуждается… мне как архитектору надо удовлетворить ВСЕХ, и дать программистам возможность писать так, чтобы у них бы меньший стресс :) Но внутри ядра надо делать в согласии с ООП.
для специалистов — они не нужны (специалист сам себе фреймворк)

Вы все сами с нуля пишете?
В конце концов фреймворки пишутся для широкой аудитории, для специалистов — они не нужны (специалист сам себе фреймворк)

Что-то я чаще встречал специалистов пользующихся чужим фреймворком и нубов пишущих свои фреймворки, нежели наоборот.
«В конце концов фреймворки пишутся для широкой аудитории, для специалистов — они не нужны (специалист сам себе фреймворк). „
Т.е. .net framework с его BCL вы не используете? WPF, WWF, WCF, asp.net (mvc, webforms) — тоже нет?

“Они лучше чем, что либо показывают — какие возможности надо давать широкой массе разработчиков.»
И вас не волнует, что их предпочтения уже сформированы теми фреймворками, которыми они пользовались раньше?
> Т.е. .net framework с его BCL вы не используете? WPF, WWF, WCF, asp.net (mvc, webforms) — тоже нет?

Нет, многое проверяли. Единственно, хорошая вещь WPF — но тоже глючная, но в определенной связи с WF можно жить.
Так и запишем: .net framework не используете, но активно обсуждаете.

Круто.

«но в определенной связи с WF можно жить. „
С чем, простите?
> И вас не волнует, что их предпочтения уже сформированы теми фреймворками, которыми они пользовались раньше?

Нет. Повторяю всегда стоит задача удовлетворить как много большие число людей. Для этого людей не нужно сортировать по религии.
Это вы так тонко всех на хабре назвали мухами :)
А я своего мнения и не скрываю ;)))
Разница в том, что я не считаю, что я чем-то лучше, а только стремлюсь быть лучше.
«говорит нам, что 2/3 хорошо видят, что причиной сохранения является бизнес-логика»
При этом определение бизнес-логики у вас и у тех, кто отвечает на опрос — разное.

«Этот опрос показывает, что из 2/3 тех кто согласен, что бизнес-логика есть причина сохранения + 0.5*1/3 (системщиков не видящих предмета бизнес-логики в своих задачах), тем не менее не все придерживаются нотации myObject.Save().»
Ась? С чего вы вообще взяли, что эти опросы как-то кореллированы?

«А это означает, что как минимум 2/3-1/2 нарушают принципы ООП. „
А вот это из предыдущего вообще никак не вытекает.

(еще неплохо бы указать, какой именно принцип ООП, дословно, они “нарушают»)
> какой именно принцип ООП, дословно, они нарушают

Это даже принцип логики — противоречие :)

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

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

«Нет разных пониманий бизнес-логики „
Да ну? Есть как минимум бизнес-правила на уровне требований и конкретное место их реализации в коде, и это две _разных_ вещи.
> Это бизнес-логика на уровне требований, а не на уровне кода

Вам самому не смешно от своих объяснений? Кем вы работаете, если не секрет?
Не секрет. Начальник отдела разработки, ведущий архитектор.

Нет, мне не смешно от своих объяснений, мне смешно, что мне приходится рассказывать такие вещи.
> ведущий архитектор

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

Так что у нас, несомненно, проблемы, но уверяю вас, не из-за этого.

«Я вот только удивляюсь как вы еще не поссорились с ведущим проектировщиком — ведь ему постоянно приходится выравнивать ваши косяки. „
Интересно, а что такое “ведущий проектировщик» в вашем понимании, и чем он отличается от «ведущего архитектора»?

(если что, у нас не строительное бюро)
> что такое “ведущий проектировщик» в вашем понимании, и чем он отличается от «ведущего архитектора»?

Зачем же мое, у меня просто нет кодификатора профессий под рукой… но советую посмотреть там.
Подозреваю, что имеется в виду то ли ведущий разработчик, то ли ведущий аналитик.

Если разработчик — то да, я тут уже почти на грани увольнения и к коду меня не подпускают даже на 10 метров.

Если аналитик — то вы тоже угадали, это любимый объект для троллинга.
Дорогой мой, у нас другие стандарты :) Европейские :)
Т. е. проектировщик — designer/developer? В русском языке давно принято слово «разработчик». Ну, и да, приятно познакомиться.
Ну, и даже в указанных вами стандартах — вы их открывали хоть? А жаль, иначе бы без труда нашли бы понятие о проектировщике (правда эти стандарты не акцентирую внимание на отличиях).
Скажу честно — по диагонали.
Ну если серьезно, то код 2513 02 Profesiju klasifikators (осторожно неизвестный язык :) )… у нас отсутствует понятие архитектора в IT. Проектировщик IT во много соответствует вашему архитектору IT, но по сути проектировщик больше кодит ядро системы и дает UML для прикладников (т.е. переводия язык аналитика на проектную документацию, но не выполняет её сам полностью). Ну а чем занимается ваш архитектор — знаете лучше сами.
Очень сильно зависит от процесса разработки. Собственно на вышеуказанные стандарты всем пофигу именно потому что они не отражают процессов.
«Зачем же мое, у меня просто нет кодификатора профессий под рукой… но советую посмотреть там. „
Гм, а при чем тут вообще кодификатор профессий? Я вам свою должность называл по сути, а не по кодификатору.
>а при чем тут вообще кодификатор профессий?

Было заявление «нету такой профессии в IT»
От меня? Не было.
Но я же не только с вами разговариваю :)
Ок, тут я погорячился, признаю. Но вот то, что такое понятие, скажем так, мало где встречается…
> При этом определение бизнес-логики у вас и у тех, кто отвечает на опрос — разное.

Нет разных пониманий бизнес-логики
Это этот, в котором мнения поделились приблизительно пополам?
Это так только для определенного круга задач. Но это не так как для других задач, так и для «чистого» ООП.
Ключевое словосочетание — «на .net». Есть мнение, что делать короткий проект на дотнете — стрельба из пушки по воробьям. Зачем делать его дорогими дотнетчиками на дорогой винде, когда можно взять дешевых пхпшников и захоститься под линуксом?
Или дорогих рубистов/питонистов, но сделать проект раза в полтора быстрее?

Для коротких проектов, есть rad-фреймворки аля rails, и именно потому что они rad там больше упор на скаффолдинг, более простая архитектура, при определенной потере гибкости.
Язык и технология — тут совершенно не причем.
Да?

То есть программирование на языках с динамической типизацией и программирование на языках со статической типизацией — одно и то же?
В вопросе естественной ООП нотации, о которой тут идет речь — да.
tac, скажите, а вы знаете что такое «примесь»?
Я намекаю на то, что «естественная ООП-нотация» в исходном виде — это совсем не то, к чему вы привыкли в C#. И в разных классах языков ООП немножко разное.
Да ну? Именно язык и технология, и естественные для языка и технологии приемы определяют, что будет более естественным для программиста.

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

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

«Как следствие, объем работы с хранилищем заметно выше — и выбор способа работы с хранилищем сильно отражается на сложности чтения, написания и сопровождения кода. „
Если честно, я не очень вижу, чем паттерн Repository хуже с точки зрения чтения/написания/сопровождения, чем паттерн ActiveRecord.

(при правильной архитектуре приложения, конечно же, т.е. получение ссылки на репозиторий не должно быть какой-то проблемой)
При постоянном соединении можно все держать в ОЗУ и вообще не думать о хранилищах.
Постоянном соединении кого с кем? Что мешает все держать в памяти веб-сервера?
При отсутствии постоянного соединения сервера с клиентом, вопрос хранения данных в ОЗУ сводится к вопросу инвалидации кэша. Этот вопрос разумнее отдать на откуп хранилищу, которое будет держать львиную долю актуальных данных в ОЗУ, при необходимости загружая недостающие данные из той же БД.
Вы сейчас вообще не о том говорите, если честно.

_Если_ при постоянном соединении «можно все держать в ОЗУ и не думать о хранилищах», то веб-сервер _тоже_ может «все держать в (своем ОЗУ) и не думать о хранилищах».

Хранилища возникают тогда, когда появляются требования к «долгоживучести» (простите) данных. И тогда, в принципе разница между вебом и толстым клиентом пропадает, потому что сохранять надо в один и тот же момент (когда по требованиям это нужно).
Я вам дам точный ответ почему нельзя все держать в ОЗУ.
Потому что мы не можем гарантировать, что следующий запрос от пользователя придет на этот же сервер, или что предыдущий запрос обслуживался на этом сервере. DNS Round-Robin, например.
Вертикальное масштабирование все еще существует. Почитайте про архитектуру stackoverflow например.
А что, ферма уже является обязательным условием для веб-проекта?

Ладно, это все пустое, если честно.

В реальности я считаю, что такое засилье ActiveRecord в веб-проектах основано исключительно на том, что в массовых фреймворках — ActiveRecord. Вот и все.

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

по вашей логике, только потому что пересели на массовое засилье DI-фреймворков…

Жизнь то она сложнее ;)
«по вашей логике, только потому что пересели на массовое засилье DI-фреймворков… „
А где связь?

На DI мы перешли существено позже, если что.
myObject наследует интерфейс сериализации, storage.Save(myObject) дергает myObject.serialize() и сохраняет сериализованный объект. В таком случае объект сериализует сам себя (только нужные поля и поля эти остаются закрытыми), но ничего не знает про хранилище и работу с ним. По-моему самый логичный вариант
Логика вещь диалектическая (а не формальная :) ) может быть ровно наоборот: myObject.Save() сериализует объект и отправляет свою сериализацию в хранилище.
и да, в завершение: хранилище ничего не знает о объектах.
хранилище и не должно знать, оно хранит строки/xml-ки/etc, полученные сериализацией объекта. Вариант с storage.Save(myObject.serialize()) более явный, но не сильно отличается. А объект и подавно не обязан знать ни о каких хранилищах
А одна из логик нам подсказывает, так как ЧислоХранилищ много меньше ЧислаОбъектов — то в каком случае больше возникает связей?
Отправляет но в какое хранилище? Ведь не указано в какой хранилище, значит эта связь должна быть где-то еще прописана, а это лишние действия. К тому же это бизнес объект, и я не уверен что метод save тоже всегда является бизнес методом, поэтому он лишний :)
Блин, второй день пошел! Дайте поработать!
Второй? кто-то об это с вечера воскресенья плачет!
У кого-то крепкие нервы.
А это правильно, раз пять уже порывался идти работать :)
Не, вы чего! Какая работа? Надо же на хабр что-то написать!
Ага, работа не чл… век стоять будет, пойду ка лучше за пивом и рубанусь в Rise of Nations
До вас и игры вовремя не доходят ;)
Зато проверено временем :)
Sign up to leave a comment.

Articles