All streams
Search
Write a publication
Pull to refresh
0
0.3
Дмитрий @qrKot

Энтузиаст

Send message

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

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

Не суть есть важно, БД это, диск, лог, очередь - вообще по барабану, это копия, с которой надо так или иначе синхронизироваться. Вы можете брать значение из памяти и отливать в хранилище или спрашивать из хранилища значение и класть в память - вопрос только в том, кто "источник истины". Суть от этого не изменится, для работающего приложения значение в хранилище будет внешним.

Причем, тут уже без разницы, ФП/императивный подход. Надеяться, что ФП магическим образом само как-то решит за вас проблему консистентности данных - какая-то наивность. В случае любой программы есть данные в памяти, и данные за ее пределами.

Не пользуйтесь, разрешаю

Я, откровенно говоря, C++-style ООП тоже не пользуюсь, процедурным языком кормлюсь

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

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

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

ФП: у нас нет разделяемого состояния, можете не заботиться о потокобезопасности (пока не понадобится shared state/shared resourse, но с ними из без потокобезопасности больно было).

ООП: вот вам инструмент, вы его знаете, он с вами давно, называется "инкапсуляция". А вот новые, называются "примитивы синхронизации". Защитите себя сами, вы на это и программисты.

С хрена ли тут какие-то гарантии дополнительные у ООП появиться должны были - решительно непонятно.

Вот это ваша цитата, ответ на которую вы сейчас цитируете.

Но ООП и не помогает с инкапсуляцией в смысле потокобезопасности. Скорее, мешает.

Теперь таки "конечно, помогает".

Вы там определитесь уже, что ли. Так помогает или мешает? Люди волнуются!

из определения

Покажите мне уже это определение, на которое вы ссылаетесь. Я ни одного подходящего не видел.

цель инкапсуляции - защита инвариантов

Нету у нее такой цели.

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

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

И вы, ссылаясь на следствие из парадигмы ФП, утверждаете, что оно же должно быть заложено в определении ООП? Вы в своем уме вообще?

любая с конечной согласованностью подойдет

Буду краток: нет.

и событийная туда же

Еще раз: нет.

банки" бывают с разными требованиями

И еще раз: нет.

Вы просто, опираясь на то, что ФП дает гарантии защиты в многопоточной среде (ввиду отсутствия разделяемого состояния), считаете, что ООП или процедурная парадигма должны давать таковые же.

Ну вот не должны. Потому что ООП - парадигма, построенная на наличии разделяемого состояния, со своими ограничениями и областью применения. Вся фишка в том, что в 90% случаев именно ФПшные гарантии вообще не нужны, а ограничения накладывают.

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

Код на 90% синхронный, и да, в современном серверном применении - тоже. Многопоточные гарантии "искаропки" хорошо, когда вычислительно-сложные задачи выполняешь. Их, как правило, в процессинге пользовательских запросов нет.

Вот и получается, что ФП-парадигма - это, может быть, и хорошо, но в подавляющей массе решений не нужно.

И как вы собираетесь, не используя инкапсуляцию, защитить поле? synchronized? Ну так:

  1. Работает либо с методами, либо с блоками кода - т.е. поверх инкапсуляции.

  2. Собственно по сути является инкапсуляцией.

Как без инкапсуляции защищать собираетесь? Обертывать в synchronized каждое обращение к полю ручками? Ну, удачи, чо...

А мешает, простите, как?

Вот есть поле, поле вы никак защитить не можете. Плохо.

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

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

Т.е., получается, помогает? Ну, исходя из элементарной логики!

Инкапсуляция должна включать гарантии потокобезопасности

Кому должна?)))

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

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

Был бы другой пример, другой бы разговор был. А для банковских счетов есть 2 неотъемлемых требования:

  1. Транзакционность

  2. Последовательность операций.

Требование параллельно 2 операции по одному счету выполнять - ересь, высосанная из пальца. На банковские транзакции ФП ложится отвратительно, не надо его тащить. А ООП вы не понимаете, от слова "вообще"

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

Вот это вы странное спрашиваете. В контексте беседы "внешние данные" - это все данные, хранящиеся не в памяти приложения.

Вот тут вы несколько несправедливы. Беседа таки в ключе исходной статьи ведется, а в статье таки в качестве примера BankAccount приводится. И вот хранить стейт банковских счетов в "долгоживущих Erlang процессах" (т.е. инмемори, я же верно понимаю) - ну вот такая себе идея.

В исходном ключе обсуждения таки да, данные о состоянии банковских счетов могут храниться только в БД. Мало того - еще и обязательно в транзакционной!

В многопотоке абстракция течёт. Потому что появляется время, которое разделяет состояние на до изменения и после.

Ну, т.е. любая абстракция течет? о_О Всегда есть время до и после!

Приведите пример в многопотоке.

Приводил уже.

public void Deposit(decimal amount) {
  this.mutex.Lock()
  this.amount += amount
  this.mutex.Unlock()
}

Lock управляет временем (заставляет ждать)

Все верно, в этом и есть смысл абстракции! Абстракция - это класс BankAccount, который позволяет просто дернуть ручку Deposit, на задумываясь, что внутри. Мьютекс - внутри, в реализации. Нам не надо заботиться о необходимости лочить мьютекс снаружи, потому что внутри мы этим уже озаботились - это и называется "абстракция".

но способ не безопасный и не эффективный

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

Ну и с понятием транзакции вы, видимо, тоже не знакомы. И реальных проектов не писали...

Зато мнение имеете.

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

Я не понял

Ну, хоть признаешь, уже хлеб)

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

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

Ну началось. Окей, давайте поанализируем то, что в Вике написано:

Термин «инкапсуляция» может означать следующее в разных языках программирования:

  • механизм языка, ограничивающий доступ одних компонентов программы к другим;

  • языковая конструкция, связывающая данные с методами для их обработки.

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

Итак, мы видим "черный ящик", а также 2 положения, первое из которых - буквально "сокрытие".

А теперь про второе, давайте посмотрим интересный пример (договариваемся сокрытие не использовать, все public).

class RectOrdPoint { // точка на определенной диагонали квадрата
  public int coordX;
  public int coordY;
  public void setCoord(int coord) {
    this.coordX = coord;
    this.coordY = coord;
  }
  public void setX(int coord) {
    this.setCoord(coord);
  }
  public void setY(int coord) {
    this.setCoord(coord);
  }
}

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

Вроде все норм, с методами все отлично. Осталось только понять, кто запретит мне, как потребителю этого класса ручками поле поменять? Мы напишем в заголовке "отдельно координаты менять нельзя, координаты должны относиться друг к другу по формуле x=y". Ну вот это буквально "текущая абстракция", которой тут все пугают.

Как же защититься от такой закавыки? Сделать так, чтобы координаты могли меняться только совместно. Ну, например, объявить поля приватными, ибо "нефиг лезть". Я других действительно действующих механик не вижу, а конкретно эта называется "сокрытие".

Вот и выходит, что в отрыве от сокрытия в том или ином виде инкапсуляция в дикой природе почти не встречается. В концепции ООП, особенно в исходной формулировке Алана Кея, именно сокрытие и является краеугольным камнем.

«ООП для меня означает лишь обмен сообщениями, локальное сохранение, и защита, и скрытие состояния, и крайне позднее связывание». Алан Кэй

Из "троицы" наследование-инкапсуляция-полиморфизм в основе ООП только инкапсуляция и есть, причем в виде сокрытия.

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

Вот это я вам и пытаюсь донести.

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

Каким боком она подтекать-то начинает???

Вот у нас метод BankAccount.Deposit(decimal amount) - это наша абстракция.

public void Deposit(decimal amount) {
  this.amount += amount
}

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

Вот, смотрите, ща я реализацию исправлю, а абстракция та же самая останется:

public void Deposit(decimal amount) {
  this.mutex.Lock()
  this.amount += amount
  this.mutex.Unlock()
}

А абстракция та же, ничего никуда не утекло!

Так что, прежде чем писать в публичный доступ о текущих абстракциях, потрудитесь, хотя бы, нагуглить, что такое "текущая абстракция"

Information

Rating
2,266-th
Location
Бийск, Алтайский край, Россия
Date of birth
Registered
Activity