LINUX.ORG.RU
Ответ на: комментарий от jtootf

> реализация может меняться хоть сто тыщ раз - в том, как бы, и вся соль инкапсуляции

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

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

а что - из того факта, что класс можно неправильно спроектировать и без геттеров/сеттеров следует что они не порождают проблем? это определённо новое слово в логике :)

из того факта, что класс можно неправильно спроектировать без геттеров и сеттеров следует лишь то, что это не проблема *еттеров, это проблема проектировки.

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

Не очевидно. Более того, я опять же не вижу более-менее жизненного примера таких случаев. Особенно с алгоритмом вычислений, поскольку уж это-то инкапсулировано в абстракцию интерфейса. А если мы меняем логику так что надо менять интерфейс - значит это *новый* интерфейс, и мы должны создавать *новый* интерфейс, а не менять старый. В этом случае всё, что работало со старыми классами будет продолжать с ними работать.

interface dynamicModel<T extends PhysElems>{
  List<T> getList();// возвращает список элементов
  void setList(List<T> list);//устанавливаем список элементов
  void calcutale(double t);//расчитать состояние системы через t секунд
}

приведи пример, что мне надо испортить, чтобы эти *еттеры перестали правильно работать?

Да кстати, рабочий (хотя бы на уровне псевдокода) пример идеологии без сеттеров с твоей стороны не был приведён.

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

ты считаешь, что интерфейсы постоянны, а поля - нет

скажи, зачем нужна инкапсуляция?

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

именно. так и должно быть. но если поле вынесено в интерфейс с помощью геттера/сеттера - свободно менять его мы уже не можем. за всё надо платить

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

> скажи, зачем нужна инкапсуляция?

т.е. ты считаешь, что можешь на 100% продумать интерфейс, который подойдет на все случаи жизни? вы вон с квадратом целую дискуссию устроили, с написанием кучи костылей, чтоб заставить квадрат быть прямоугольником

так и должно быть. но если поле вынесено в интерфейс с помощью геттера/сеттера - свободно менять его мы уже не можем. за всё надо платить


дык и я не за то, чтоб завязывать классы друг на друга на пустом месте - совсем наоборот, но если я что-то вынес в %еттер - я знаю, что это гарантированное свойство объекта, которое логично вписывается в общую картину и которое «смотрит наружу» не зря

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

из того факта, что класс можно неправильно спроектировать без геттеров и сеттеров следует лишь то, что это не проблема *еттеров, это проблема проектировки

с какой радости?

приведи пример, что мне надо испортить, чтобы эти *еттеры перестали правильно работать?

неудачный пример - во-первых, через интерфейс «общего набора данных» работать можно в любом случае (хоть в некоторых случаях и неэффективно - если мы перейдём на внутреннее представление в виде Tree<T>, ли двух списков, каждая установка будет требовать пересчёта); во-вторых, твой класс предполагает геттер и сеттер в интерфейсе в любом случае. давай так:

interface dynamicModel<T extends PhysElems>{ 
  List<T> getList();// возвращает некоторый список
  void setList(List<T> list);//устанавливаем список
  Tree<T> getTree(); // возвращает некоторое дерево
  void setTree(Tree<T> tree);// устанавливаем дерево
  void calcutale(double t);//расчитать состояние системы через t секунд 
} 

реализация состояла из двух структур данных, на которые были заведены геттеры/сеттеры. мы перешли на другую реализацию, которая использует в качестве структуры данных один Vector<T>. что делать с геттерами/сеттерами, на которые уже завязан клиентский код?

сдругой стороны, мы могли бы сделать так:

interface dynamicModel<T extends PhysElems>{ 
  Data<T> getData();// возвращает данные
  void setData(Data<T> data);//устанавливаем данные

  void calcutale(double t);//расчитать состояние системы через t секунд 
} 

где Data<T> - аггрегатор для данных, инкапсулирующий их природу (точно так же, как подлежащий контейнер инкапсулируется в стеке). переход на другую реализацию в dynamicModel теперь не требует ни рефакторинга его интерфейса, ни изменений в клиентском коде

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

т.е. ты считаешь, что можешь на 100% продумать интерфейс, который подойдет на все случаи жизни?

нет, конечно :) но самостоятельно подкладывать себе дополнительную свинью я тоже не буду

если я что-то вынес в %еттер - я знаю, что это гарантированное свойство объекта, которое логично вписывается в общую картину и которое «смотрит наружу» не зря

я сказал бы это другими словами, но в общем - плюсую :)

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

> мы перешли на другую реализацию, которая использует в качестве структуры данных один Vector<T>

практически ежедневная операция - замена списка и дерева на один вектор :)

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

к слову - getData/setData в данном случае не является геттером/сеттером какого-либо поля, т.к. поля типа Data<T> в модели нет - есть поля реализации, по которым данные распределяются наиболее эффективным с точки зрения алгоритма обработки образом

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

практически ежедневная операция - замена списка и дерева на один вектор :)

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

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

>> из того факта, что класс можно неправильно спроектировать без геттеров и сеттеров следует лишь то, что это не проблема *еттеров, это проблема проектировки

с какой радости?

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

У меня складывается ощущение, что в твоём понимании использование *еттеров обозначает написание методов getVar/setVar на любую внутреннюю сущность? Да это конечно плохо и может привести к проблемам. Но ведь как и всё в программировании *еттеры не стоит использовать бездумно. А так это очень полезная вещь, предоставляющая большое количество бонусов и полезных возможностей. При том, что реальную проблему пока сформулировать не удалось, кроме очень дурной головы архитектора.

по поводу твоего примера буду отвечать как и ты: нам нужно изменить функцию calculate(double t) на calculate(double t,double p), что делать клиенту, который завязан на функцию calculate. Нам же придётся всё переделывать? Ровно та же проблема. Кстати если в твоём коде станет необходимо хранить 2 струтуры, то возникнет та же проблема от которой ты хотел уйти :)

Ещё раз, то, что выше это не проблема сеттеров и геттеров, а проблема иерархии. Ты сказал, что мой пример с сеттерами плохой и привёл ровно ту же реализацию, использовав Data<T> вместо List<T>, гениально .

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

> т.к. поля типа Data<T> в модели нет - есть поля реализации, по которым данные распределяются наиболее эффективным с точки зрения алгоритма обработки образом

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

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

подробнее, про то, что имеется ввиду под словами

поля типа Data<T> в модели нет - есть поля реализации

?

т.е. возникает случай когда

каждая установка будет требовать пересчёта

я правильно понял?

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

Ты сказал, что мой пример с сеттерами плохой и привёл ровно ту же реализацию

ты правда не видишь разницы? тогда я могу только посочувствовать

нам нужно изменить функцию calculate(double t) на calculate(double t,double p)

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

Кстати если в твоём коде станет необходимо хранить 2 струтуры, то возникнет та же проблема от которой ты хотел уйти

не встанет - Data<T> может свободно аггрегировать те самые две структуры: установка и снятие данных не требуют дополнительных пересчётов, вызывающий код (кроме непосредственно набирающего данные) об устройстве Data не должен знать ничего, и не должен меняться при его изменении

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

если нам не надо все сразу, а надо лишь получить часть данных

передаёшь Data по константной ссылке, и выбираешь только ту часть данных, которая тебе реально нужна. откуда шуршание диском?

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

> передаёшь Data по константной ссылке, и выбираешь только ту часть данных, которая тебе реально нужна. откуда шуршание диском?

я запросил getData, что мне придет - объект, который будет дергать родителя или объект с готовыми данными?

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

Если в модели я использую List <- заметь интерфейс, а не конкретный тип, то наверное это значит, что я знаю, что мне нужен именно лист, а не Tree и не Map. А если мне его надо поменять на дерево это значит, что у меня суть класса изменилась настолько, что мне нужен новый класс, а не изменение старого. Это упростит жизнь и мне и тем, кто будет пользоваться библиотекой.

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

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

не встанет - Data<T> может свободно аггрегировать те самые две структуры: установка и снятие данных не требуют дополнительных пересчётов, вызывающий код (кроме непосредственно набирающего данные) об устройстве Data не должен знать ничего, и не должен меняться при его изменении

я же попрошу код :) а то твои предложения всё больше походят на сказку (

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

я запросил getData, что мне придет - объект, который будет дергать родителя или объект с готовыми данными?

тут уже есть варианты. если система многопоточная, то у тебя есть выбор - либо дёргать родителя, копируя подлежащие структуры в Data (пересчёт не нужен, т.к. структуры данных совпадают, однако копирование делать в таком случае придётся); либо замыкать мьютекс, получать Data с константными ссылками на поля модели, выбирать нужную тебе часть данных и размыкать мьютекс. проблемы пересчёта (раскидать список в дерево, например) в любом случае нет

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

> либо дёргать родителя, копируя подлежащие структуры в Data

получать Data с константными ссылками на поля модели


дык нет еще данных в полях модели - не вычитались, ленивая оптимизация она такая

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

про то, что передача данных будет идти через посредника + копирование - а значит будет медленней и тратить больше памяти, пока забудем

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

то наверное это значит, что я знаю, что мне нужен именно лист

если ты заранее на 100% знаешь, какая реализация тебе нужна, то инкапсуляция тебе не даст никакого профита. that simple

Такое ощущение, что тебя в детстве кто-то заставлял создавать *еттеры на все поля и выносить их в интерфейс

меня раздражает расхожая (и перепечатываемая из книги в книгу) басня о том, что private + геттер/сеттер для поля = инкапсуляция. посмотри на ответы к этому топику: «зачем нужны геттеры? - инкапсуляция!». я не утверждаю, что геттеров/сеттеров никогда не должно быть, и не утверждаю, что слабая инкапсулированность - это всегда плохо. я всего лишь хочу показать, что знак равенства между геттерами/сеттерами и инкапсуляцией чуть более чем ошибочен

я же попрошу код

код структуры Data<T>, аггрегирующей (например) два списка? код копирования списков из Data<T> в модель?

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

дык нет еще данных в полях модели - не вычитались, ленивая оптимизация она такая

не понял. если их там нет, то считать по вызову их придётся независимо от интерфейса. если же у тебя модель реализована с call-by-need, то и соответствующий механизм получения данных тоже должен быть реализован (некоторый прокси вместо raw-ссылок во втором варианте)

про то, что передача данных будет идти через посредника + копирование - а значит будет медленней и тратить больше памяти, пока забудем

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

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

> то и соответствующий механизм получения данных тоже должен быть реализован

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

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

в результате будет построена «система» по принципу - дай мне только вот это

если у нас есть необходимость в ленивой модели - да

причем она будет на уровне «клиента», посредника и «сервера»

если ты вводишь стратегию call-by-need в строгом по умолчанию языке, то она потребует соответствующего кода на всех уровнях. как это связано с интерфейсом модели? что, в случае если бы там был просто List<T> и Tree<T> в интерефейсе, тех же проблем не было бы?

от чего мы защищались и что нам это дало, кроме минусов?

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

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

> если ты заранее на 100% знаешь, какая реализация тебе нужна, то инкапсуляция тебе не даст никакого профита. that simple

Вывод, мне нужен какой-то List, что будет лучше ArrayList, Vector, или какая-нибудь другая структура реализующая лист мне не важно. Мне важно умение добавлять/удалять/изменять элементы и вытаскивать элемент по номеру. Что именно из List-ов мне нужно точно неизвестно и может меняться в зависимости от задачи. В своём решении я именно это и фиксировал. Поэтому используя List я позволяю принять решение человеку использующему данный класс.

Если вдруг окажется, что мне нужно, например, автоматически сортировать данные или иметь нечёткий поиск и мне потребуется Tree вместо листа, тогда мне придётся делать новую иерархию. Имхо это осмысленно в данном случае.

При этом мне не нужно использовать исключительно сложные типы типа Data<T>, всё чётко и работающему с классом в большинстве случаев понятна логика работы.

меня раздражает расхожая (и перепечатываемая из книги в книгу) басня о том, что private + геттер/сеттер для поля = инкапсуляция. посмотри на ответы к этому топику: «зачем нужны геттеры? - инкапсуляция!». я не утверждаю, что геттеров/сеттеров никогда не должно быть, и не утверждаю, что слабая инкапсулированность - это всегда плохо. я всего лишь хочу показать, что знак равенства между геттерами/сеттерами и инкапсуляцией чуть более чем ошибочен

ок, принято.

код структуры Data<T>, аггрегирующей (например) два списка? код копирования списков из Data<T> в модель?

код структуры Data<T> который будет легко переделываться под изменяющиеся нужды (изменение внутренних полей класса), при этом не накладывающей ограничения на пользователя класса ;)

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

> извлекаться из одной, проходить обработку в Processor, заноситься в другую, проходить обработку в Cleaner, и исчезать. ИМХО, ты усложнил простую и понятную схему без всякого профита.

Неправильно. Переименуй Message в Sesson. Пример - препейдовый биллинг.

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

no-dashi ★★★★★
()
Ответ на: комментарий от jtootf

> если ты вводишь стратегию call-by-need в строгом по умолчанию языке, то она потребует соответствующего кода на всех уровнях.

что, в случае если бы там был просто List<T> и Tree<T> в интерефейсе, тех же проблем не было бы?


а польза тогда от посредника какая? есть все та же завязка на List и Tree, более того - завязка теперь не только в двух исходных классах, но и в посреднике, т.е. вместо упрощения - получили усложнение

от чего защищались, от того мы защитились - изменение реализации не требует изменения интерфейса


вот есть у тебя посредник, как ты ему скажешь, что тебе надо только Tree<T>, и как он в свою очередь попросит его у исходного объекта?

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

Вывод, мне нужен какой-то List, что будет лучше ArrayList, Vector, или какая-нибудь другая структура реализующая лист

тот факт, что вектор в Java - это список, не перестаёт меня удивлять до сих пор. интересно, какой логике следовали те, кто его так назвал?

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

код структуры Data<T> который будет легко переделываться под изменяющиеся нужды (изменение внутренних полей класса), при этом не накладывающей ограничения на пользователя класса ;)

template <typename T> struct Data {
  List<T> field1_;
  List<T> field2_;
}

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

template <typename T> struct Data {
  Tree<T> field_;
}

менять интерфейс модели (и весь код, который с этим интерфейсом работает) необходимости нет

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

а польза тогда от посредника какая? есть все та же завязка на List и Tree

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

вот есть у тебя посредник, как ты ему скажешь, что тебе надо только Tree<T>, и как он в свою очередь попросит его у исходного объекта?

data.field_.force();

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

data.field_();

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

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

> data.field_.force();

что сие значит? я хочу получить только дерево( имя и т.д. ) - как эта строка/строки будут выглядеть

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

> тот факт, что вектор в Java - это список, не перестаёт меня удивлять до сих пор. интересно, какой логике следовали те, кто его так назвал?

да вектор в Java это отдельная история :)

реализация может быть произвольной в рамках порождаемой интерфейсом иерархии

мне хочется утверждать, что в 90% случаев при такой идеологии проблем не будет. Если быть честным, то у меня нету достаточного опыта, чтобы это утверждать.

за код спасибо. обдумаю, может до чего ещё докапаться пропытаюсь.

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

т.е. приведи аналог следующей строки:

Tree<T> tree = obj->get_Tree();
lester ★★★★
()
Ответ на: комментарий от lester

что сие значит? я хочу получить только дерево( имя и т.д. ) - как эта строка/строки будут выглядеть

template <typename T> class Proxy {
public:
  Proxy(T & data) : data_(data) {}
  T operator()() { /* реализация call-by-need */ }
private:
  T & data_;
};

template <typename T> struct Data { 
  Proxy<Tree<T>> field1_; 
  Proxy<List<T>> field2_; 
};

Data data = getData();
Tree<double> tree = data.field1_();

где-то так, например. откуда должны возникнуть проблемы?

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

> где-то так, например. откуда должны возникнуть проблемы?

замечательно :) кроме того, что это будет гораздо медленней, сразу появляется вопрос, а что будет, когда (внезапно) пропадет поле Proxy<Tree<T>> field1_? ну вот отказались мы от представления данных в виде дерева внутри исходного класса - как ты сам стращал, что теперь делать?

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

кроме того, что это будет гораздо медленней

гораздо медленней, чем что? и почему?

что будет, когда (внезапно) пропадет поле Proxy<Tree<T>> field1_?

jtootf

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

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

jtootf ★★★★★
()
Ответ на: комментарий от jtootf
template <typename T> class Proxy { 
public: 
  Proxy(T & data) : data_(data) {} 
  T operator()() { /* реализация call-by-need */ } 
private: 
  T & data_; 
  T cache_;
}; 

изменено во имя луны, а то у меня call-by-name был, а не call-by-need

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

гораздо медленней, чем что? и почему?

чем геттер, потому-что в нем мы попадаем на конструкцию

if( !mCached ) ReadTree();
return mTree;

которая будучи заинлайнена по скорости будет практически равна прямому доступу к полю

эта цель таким образом достигается

в чем? ты так и не сказал, как «таким образом» ты уйдешь от рефакторинга

хотя твой пример мне по-прежнему не понятен

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

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

чем геттер, потому-что в нем мы попадаем на конструкцию

а ничего, что здесь мы попадаем на такую же конструкцию?

template <typename T> class Proxy {  
public:  
  Proxy(T & data) : data_(data) {}  
  T operator()() { if(!cached) { cache_ = readData() }; return cache_  }
private:  
  T & data_;  
  T cache_; 
}; 

которая будучи заинлайнена по скорости будет практически равна прямому доступу к полю

считаем такты?

ты так и не сказал, как «таким образом» ты уйдешь от рефакторинга

при изменении реализации модели интерфейс менять надо или нет?

ты их просто перенес в прокси

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

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

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

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

> а ничего, что здесь мы попадаем на такую же конструкцию?

ты меня разочаровываешь..., а если исходный объект данные перечитает с БД или сбросит флаг «закэшировано», у тебя прокси навечно останется со своей копией?

при изменении реализации модели интерфейс менять надо или нет?


ну епрст :) объем кода перелапатить тебе придется еще больший чем с геттерами - тебе надо будет заменить все обращения + сам прокси изменить, и если у тебя люди дергают методы прокси, то им будет фиолетово, что ты не изменил интерфейс объекта, т.к. им все-равно придется переписать все места, где они обращались к прокси со старой «моделью»

я получил возможность зафиксировать её интерфейс


офигеть :) работы всем больше, код нечитабельней, от рефакторинга не спасает, работает медленней - но зато в одном файле ничего не изменится :)

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

> вообще удивительный спор получается - зачем вообще нужны уровни абстракции

да нужны они - но в меру и по делу, а не лишь бы ООП, и не лишь бы как в книжке

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

если исходный объект данные перечитает с БД или сбросит флаг «закэшировано», у тебя прокси навечно останется со своей копией?

с какой радости? мы вообще что обсуждаем - инкапсуляцию, или то что ты не можешь придумать, как реализовать эффективнй call-by-need в C++?

объем кода перелапатить тебе придется еще больший чем с геттерами

во-первых, заметно меньший; во-вторых - весь этот код будет локализован, а не размазан ровным слоем по проекту

тебе надо будет заменить все обращения

обращения к чему?

+ сам прокси изменить

прокси у меня - в меру универсальный шаблон. каким образом я должен его менять?

если у тебя люди дергают методы прокси, то им будет фиолетово, что ты не изменил интерфейс объекта

если проект спроектирован через жопу, то он спроектирован через жопу. у меня нет серебряной пули, которая делает «всё хорошо»

да нужны они - но в меру и по делу, а не лишь бы ООП, и не лишь бы как в книжке

да используй хоть зелёный сыр, чушь-то пороть зачем?

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

кажется ты ничего не понял из того, что я написал, ну да ладно - давай просто порадуемся, что не работаем вместе :)

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

давай просто порадуемся, что не работаем вместе :)

ок :)

jtootf ★★★★★
()
Ответ на: комментарий от no-dashi

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

Неправильно. Переименуй Message в Sesson

Session - сессия клиента

Sessions - текущие сессии

Events - события

Processor (их может быть множество

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

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

>из того факта, что класс можно неправильно спроектировать без геттеров и сеттеров следует лишь то, что это не проблема *еттеров, это проблема проектировки.

Я лишь замечу, что то, что ты тут написал содержит грубую логическую ошибку

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

ошибку в студию! ^_^ (контекст разговора желательно учитывать)

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

> Давай ты не будешь прятаться за ынтерпрайз-баззвордами.

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

no-dashi ★★★★★
()
Ответ на: комментарий от jtootf

приведённый код, естественно, не работает

Вы читать не умеете, да? в детском садике пока слоги учите? :)

напомните-ка мне уважаемый, где я Вам обещал рабочий код?

будь добр, ответь коротко и по существу - можешь ты добиться обратной совместимости

:) стук-постук об стенку лбом перестук

я Вам персонально писал: «пример некорректный, кто ж так рефакторит» вот здесь

что Вам ещё надо? расписать по строчкам почему Вы привели в пример идиотию? я готов потратить своё время, сделать это для Вас?

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

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

месье эксперт :) скажите как Вы понимаете суть понятия «рефакторинг»?

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

меня раздражает расхожая (и перепечатываемая из книги в книгу) басня о том, что private + геттер/сеттер для поля = инкапсуляция. посмотри на ответы к этому топику: «зачем нужны геттеры? - инкапсуляция!»

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

читая Ваши ответы у мне сложилось впечатление, что, возможно корень разногласий лежит в терминологии

итак, дабы не начинать очередной пустой холивар, что Вы понимаете под инкапсуляцией?

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