Абстрактный тип данных. Часть 1: Данные (Тип Данных) 0


AliExpress RU&CIS

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


Вместо предисловия


Абстрактный Тип Данных (далее АТД) — это набор, включающий данные и выполняемые над ними операции (С. Макконнелл, “Совершенный код”, глава 6.1. Основы классов: абстрактные типы данных). В данном цикле статей будет рассмотрен именно такой взгляд на АТД, расширенный типом данных.

Информация — сведения независимо от формы их представления. Знания относительно фактов, событий, вещей, идей и понятий, которые в определенном контексте имеют конкретный смысл (ISO/IEC 2382:2015).

Данные — это зарегистрированная информация.

Информационные Технологии — это приемы, способы и методы применения средств вычислительной техники при выполнении функций сбора, хранения, обработки, передачи и использования данных (ГОСТ 34.003-90).

Класс, наряду с понятием «объект», является важным понятием объектно-ориентированного подхода в программировании (хотя существуют и бесклассовые объектно-ориентированные языки, например, Прототипное программирование)
Класс является типом данных, определяемым пользователем.

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

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

Параметры у объектов мира есть всегда! У яблока например это его вкус, его цвет. У цели это ожидаемый результат, параметры достижения результата и т.д. и т.п. Объекты мира могут обладать каким либо действием, а могут и не обладать, но всегда действие можно применить к ним. Например обычная палка не способна самостоятельно производить какие либо действия, но мы можем применить к ней действие, допустим подпереть ею дверь. Автомобиль обладает действием “передвижение на плоскости”, и мы можем применить к нему действие, например завести двигатель или заглушить его. Также мы можем применить действие к автомобилю такое же как он может произвести самостоятельно, переместить его на плоскости (установить параметры нахождения на используемой плоскости).

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

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

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

Перед тем как продолжить, давайте определимся с некоторыми понятиями:

Вычисление — это получение из входных данных нового знания.

Действие (формулировка данной статьи) — изменение состояния ТД в процессе вычислений и регистрация данного состояния не меняя при этом самих данных которые участвуют в вычислениях. Например: мы меняем состояние автомобиля на плоскости (находился в точке А, переместился в точку Б), при этом данные самого автомобиля мы не затрагиваем. Еще один пример: мы имеем какой либо документ у которого есть срок действия, в процессе вычислений мы получаем состояние документа на какой то момент времени и фиксируем его, сообщаем/отмечаем, что на такой то момент времени документ действителен/недействителен, при этом сам документ мы не меняем.

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

Для корректного выделения ТД (данных) из окружающего нас мира определил следующие правила:

  1. Тип данных должен определять реальную сущность мира, материальную или нематериальную, т.е. быть именем существительным, отвечать на вопрос “кто?” или “что?”
  2. Если минимально избыточное количество параметров (отсутствие параметров избыточных для вычислений, например для квадрата достаточно знать длину одной стороны т.к. все остальные стороны такой же длины и углы между ними равны 90 градусов) и тип этих параметров у независимых друг от друга предметов (одушевленных или неодушевленных) одинаковые, то эти предметы можно отнести к одному и тому же типу данных. Если минимально избыточное количество параметров отличается или отличаются типы этих параметров, то это различные предметы, а значит и различный тип данных.


До данного момента говорил о данных в ООП и данных в реляционной СУБД, но в них есть существенное отличие, данные в БД не могут производить вычисления сами над собой, это просто зарегистрированная информация, в то время как ТД ООП может производить вычисление со своими данными, хотя принципы выделения ТД одинаковые. Более того, в ООП Классы данных являются плохим тоном и придают коду “запашок”, ТД в ООП должен уметь производить вычисления со своими данными, например для фигуры он должен быть способен вычислить ее площадь, хотя и это не аксиома, например для объекта-параметра.
Возникает закономерный вопрос — чем отличается ТД ООП от АТД по С.Макконнеллу? ТД ООП может производить вычисления со своими данными, но не может/не должен придавать им действие, в то время как АТД может производить вычисления со своими наборами данных, получать результаты вычислений ТД и придавать им действие (формулировку, что такое действие смотрите выше)

Будьте гибче!

Какие есть требования по работе объекта ООП со своими данными смотрите ниже.


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

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

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


Какие есть требования к ТД:

  1. ТД должен производить вычисления только со своими данными, иначе на выходе мы можем получить непредсказуемый результат т.к. на входе могут оказаться данные предусмотреть которых мы не могли.
  2. Данные в ТД не должны зависеть от внешнего состояния приложения работающего с ними, это также может привести к непредсказуемому результату и лишит нас некоторых возможностей, например лишить возможности кешировать результат или использование ТД в другой части ПО, код будет менее подвижен т.к. в другой части программы, которую пишем, могут отсутствовать нужные параметры состояния.
  3. Данные ТД, участвующие в вычислениях, должны быть неизменяемы на момент работы с ними. Это так же избавит нас от непредсказуемого результата вычислений, когда один метод ТД изменил данные, а другой метод не зная об этом произвел свои вычисления с уже измененными данными, хотя на входе ожидались первоначальные значения. Или например непозволит реализовать паттерн «Легковес»

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

ВАЖНО: в первую очередь надо бояться непредсказуемого изменения данных, т.е. при использовании в вычислениях данные не должны меняться (требование к ТД №3), если же вы намеренно меняете их, то это изменение предсказуемо и вы можете произвести какие либо действия для получения в дальнейшем корректного результата.

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

И так, правила для достижения неизменяемости (стабильности) данных:

  1. С. Макконнелл, “Совершенный код”, глава 7.5 “Советы по использованию параметров методов” — “Не используйте параметры метода в качестве рабочих переменных. Создайте для этой цели локальные переменные”. Т.о. вы избежите непредсказуемого изменения данных вне использования метода, например если вы передали параметр по ссылке, то изменив их в методе они изменятся так же и для другого кода класса, что потенциально ведет к ошибке. Хотя С.Макконнелл говорит несколько о другом эффекте, непредсказуемость значения внутри метода, но смысл тот же, стремление избежать непредсказуемости результата.
  2. В приватных методах класса не используйте внутренние поля напрямую, передавайте их в качестве параметров этого метода. Т.о. вы избежите случайного/непредсказуемого изменения данных, когда один метод изменил данные, а другой не зная об этом приступил к вычислениям над ними.
  3. В методах класса не обращайтесь к внутренним полям напрямую, используйте для этого специально созданные методы. Т.о. вы получите единую точку входа для работы с внутренними полями и полный контроль над ними.
  4. Стремитесь к использованию приватных методов, С.Макконнелл, “Совершенный код”, глава 5 — Почаще задавайте себе вопрос «Что мне скрыть?», и вы удивитесь, сколько проблем проектирования растает на ваших глазах.


Никоем образом не хочу сказать, что это все является панацеей, конечно же есть и другие способы решения сложных задач, волшебной таблетки не существует, будьте гибче, применяйте в своей работе разные подходы. Приведу также в пример цитату одной из моих любимых статей на хабре “Топ-11 самых частых ошибок в JavaScript” — ошибка №11: Ты следуешь всем правилам, правила для того, чтобы их ломать, если вы понимаете, почему нельзя использовать тот или иной прием, то он становится инструментом, который вы можете правильно применять в правильной ситуации.


Итог:

  1. ПО работает с данными, придает им действие или производит с ними действие. Данные, это зарегистрированная информация.
  2. Под данными (Тип Данных) подразумевается объект мира в совокупности с его параметрами.
  3. Для корректного определения Типа Данных (выделения данных) применяйте следующие правила:

    1) Тип данных должен определять реальную сущность мира, материальную или нематериальную, т.е. быть именем существительным, отвечать на вопрос “кто?” или “что?”
    2) Для одного типа данных минимально избыточное количество и тип параметров должны быть одинаковыми.
  4. ТД должен уметь производить вычисления только со своими данными (полями).
  5. Данные ТД не должны зависеть от внешнего состояния.
  6. Данные ТД, участвующие в вычислениях, должны быть неизменяемы на момент работы с ними.
  7. Бойтесь/избегайте непредсказуемого изменения данных.

Используемая литература, ссылки:

  1. С. Макконнелл, “Совершенный код”
  2. Функционвльное программирование
  3. Классы данных
  4. объекта-параметра

Теги:




Комментарии (70):

  1. amarao
    /#21723210

    Я зашёл почитать про ADT, а вместо этого увидел упоминание 1C.


    Я боюсь того дня, когда у нас будет 1C: Монада для управления расписанием уборки туалетов.

    • snegprog
      /#21723422

      Добрый день,
      Где Вы увидели упоминание про 1С, возможно Вы подразумеваете что там так же все устроено?
      Вдохновил меня на такое решение С.Макконнел с его АТД, вначале статьи и упомянул его.

  2. lair
    /#21723718

    В концепции ООП ТД это класс

    А вы в курсе про то, что бывает ООП без классов?

    • snegprog
      /#21724018

      Здесь подразумевается именно класс ООП

      • lair
        /#21724030

        … что же делать с ООП, в котором классов нет?

        • snegprog
          /#21724070

          Привел два правила, как выделять данные из мира насущного, данные правила можно так же применять и к реляционным БД, думаю и в ООП без классов тоже можно найти им применение.

          • lair
            /#21724072

            Так что же соответствует типу данных в ООП без классов?

            • snegprog
              /#21724122

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

              • lair
                /#21724128

                Я не владею вопросом ООП без классов

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

                • snegprog
                  /#21724202

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

                  • lair
                    /#21724208

                    А можно тогда пример мейнстримного языка, в котором такой используется такой подход к ООП?

                    • snegprog
                      /#21724238

                      А можно тогда пример мейнстримного языка, в котором такой используется такой подход к ООП?

                      Может Вы подскажите язык с ООП где нет классов? Вы ведь начали говорить о таком.
                      Один из пример языка где есть классы это Java

                      • lair
                        /#21724296

                        Может Вы подскажите язык с ООП где нет классов?

                        Много их, но первыми на ум приходят JavaScript, Lisp и Lua.


                        Один из пример языка где есть классы это Java

                        А еще там есть примитивные значения. Они не типы данных?

                        • snegprog
                          /#21724450

                          Типы Данных здесь не подразумевается как какие то скалярные типы или ссылочные. Здесь больше подразумевается как сущность, единица с которой потом далее мы производим работу. Когда мы определяем класс в ООП мы создаем новый Тип Данных на основе которого далее создаются объекты.
                          В реляционной БД теоретически, во избежания аномалий работы с данными Вы можете создать несколько таблиц, Но придерживаясь правил которые предоставил выше вероятней всего это будет одна таблица, если это будет несколько таблиц, то вы что то сделали не так.

                          • lair
                            /#21724460

                            Здесь больше подразумевается как сущность, единица с которой потом далее мы производим работу.

                            Ну так целое число, дата или строка — это разве не "сущность, единица, с которой потом далее мы прозводим работу"?


                            А в соседнем C# еще и структуры есть, которые не классы, а структуры. Они Типы Данных или нет?


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

                            Мы пока даже не определились, относятся ли эти правила к таблицам.

                            • snegprog
                              /#21724570

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

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

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

                              • lair
                                /#21724582

                                Сущность, если для начала отвечает на вопрос «кто?» или «что?»

                                Так вы о типах данных или о сущностях? А если о сущностях, то по какому определению сущности?


                                Вернемся к примеру про параллелограммы

                                Ну да. Вот мне надо получить ответ на вопрос "сколько параллелограммов учтено в системе". М?

                                • snegprog
                                  /#21724632

                                  Ну да. Вот мне надо получить ответ на вопрос «сколько параллелограммов учтено в системе». М?

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

                                  Тип Данных как набор данных. С.Макконнел говорит об АТД как набор, включающий данные. Описал как выделить данные чтобы потом было с ними легче работать.

                                  • lair
                                    /#21724928

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

                                    Ну то есть правила — они и не правила, получаются.


                                    Тип Данных как набор данных.

                                    Значит, сущности не при чем. Выкидываем сущности, возвращаемся к вопросу: целые числа, строки или даты — это Типы Данных или нет?

                                    • snegprog
                                      /#21725016

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

                                      Далее, выделенные данные (совокупность объекта мира и его параметров) буду определять как Тип Данных (далее ТД).

                                      Т.е. в данной статье Тип Данных рассматривается как совокупность объекта мира и его параметров, а не как тип данных одного из языков программирования. Данную формулировку посчитал наиболее подходящей т.к. изначально речь идет об Абстрактном ТД в ООП о котором написал С.Макконнел.

                                      • lair
                                        /#21725030

                                        Т.е. в данной статье Тип Данных рассматривается как совокупность объекта мира и его параметров

                                        Вот я и спрашиваю: целые числа и даты — это Типы Данных или нет?

                                        • snegprog
                                          /#21725042

                                          Это тип данных, но не тот о котором идет речь в данной статье

                                          • lair
                                            /#21725054

                                            Окей, целые числа — не Типы Данных. А теперь напомню вашу фразу: Типу Данных в ООП соответствует класс. Так вот, в Java есть класс Integer. Он — Тип Данных или нет?

                                    • snegprog
                                      /#21725038

                                      Ну то есть правила — они и не правила, получаются.

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

                                      • lair
                                        /#21725046

                                        А Вы знаете волшебную таблетку, так чтобы правила работали абсолютно везде?

                                        Не "везде", а в области определения. Математика так построена, например.

  3. GarryC
    /#21723798

    Следующий пост будет про полиморфизм?

    • snegprog
      /#21724032

      Следующую часть уже опубликовал, она к сожалению не про полиморфизм, она про управление данными — habr.com/ru/post/506204

  4. lair
    /#21723832 / +1

    Данные должны быть неизменяемые (immutable) [...] неизменяемые данные объекта принято называть “внутренним состоянием”.

    Нет, не "принято". Внутреннее состояние объекта — это все то состояние, которое не видно снаружи. И если оно состояние, то достаточно странно называть его неизменяемым.

    • snegprog
      /#21724006

      Александр Швец, “Погружение в паттерны проектирования”, паттерн “Легковес” — неизменяемые данные объекта принято называть “внутренним состоянием”

      Именно об этом идет речь.

      • lair
        /#21724026

        Я не знаю, кто такой "Александр Швец", и его мнение не является для меня никаким авторитетом. Вы могли бы привести полную цитату, чтобы можно было по крайней мере понять контекст этого высказывания?


        При этом, скажем SO со мной согласен.

        • snegprog
          /#21724054

          Я купил его книгу на refactoring.guru, считаю этот ресурс достаточно авторитетным. Речь идет о паттерне «Легковес», полная цитата так и звучит

          Неизменяемые данные объекта принято называть «внутрен-
          ним состоянием». Все остальные данные — это «внешнее состояние».

          Считаю это все уже просто игра слов, в данной статье подразумевается именно неизменяемые данные.

          • lair
            /#21724066

            Я купил его книгу на refactoring.guru, считаю этот ресурс достаточно авторитетным

            И про этот ресурс я тоже первый раз слышу.


            в данной статье подразумевается именно неизменяемые данные.

            Тогда уберите из статьи все упоминания состояния. Если АТД должен быть immutable, у него нет состояния.

            • snegprog
              /#21724096

              Пожалуй Вы правы, постарался удалить из статьи упоминания о состоянии ТД

              • lair
                /#21724112

                … так вот, если данные в ТД неизменны, то в СУБД ТД принципиально нет (ой). Да и в ООП начинаются большие проблемы, прямо скажем.

                • snegprog
                  /#21724162

                  В реляционной СУБД есть таблицы которые так же хранят данные, в классах мы можем придать действие данным, в реляционной БД (непосредственно в таблицах) нет. Тип Данных это определение которое дал именно в этой статье и все остальные совпадения случайны, хотя и могут совпадать по смыслу с другими трактовками.

                  Далее, выделенные данные (совокупность объекта мира и его параметров) буду определять как Тип Данных (далее ТД).

                  Да и в ООП начинаются большие проблемы, прямо скажем.

                  В последнем параграфе написал, волшебной таблетки не бывает, это один лишь прием из множества возможных.

                  • lair
                    /#21724170

                    Тип Данных это определение которое дал именно в этой статье

                    Так оно относится к данным в БД или нет? И если нет, то к чему оно относится?


                    В последнем параграфе написал, волшебной таблетки не бывает, это один лишь прием из множества возможных.

                    Я не знаю, о каких "приемах" вы говорите, я цитирую ваши "требования к ТД".

                    • snegprog
                      /#21724224 / -2

                      Так оно относится к данным в БД или нет? И если нет, то к чему оно относится?

                      В первом комментарии упомянули о Монадах, к ним пожалуй и относится — единица, простая сущность, «единое, как неделимое»

                      • lair
                        /#21724232

                        Давайте сначала с БД разберемся.


                        (потому что обычно, когда говорят о программировании, под монадами понимают не то, что вы написали)

                        • snegprog
                          /#21724292 / -1

                          В данном случае говорю о монаде не как часть ФП.

                          Давайте сначала с БД разберемся.

                          Т.о. это различные типы данных, в ООП эти фигуры должны быть представлены различными классами и различными таблицами в реляционной БД

                          • lair
                            /#21724298

                            Так таблица в реляционной БД — это тип данных или нет?

                            • snegprog
                              /#21724394

                              Да, в данном контексте таблица рассматривается как тип данных, не скалярный тип. Нормализация отношений это уже отдельный вопрос, так один тип данных в реляционной БД может состоять из нескольких таблиц.

                              • lair
                                /#21724396

                                Это противоречит вашему требованию на иммутабельность.


                                Что-то у вас не так в фундаментальных определениях.

                                • snegprog
                                  /#21724458

                                  Если придерживаться этих правил, то у Вас будет одна таблица и в дальнейшем с ней будет работать проще, правила и должны к этому привести.
                                  Что именно противоречит требованию иммутабельности?

                                  • lair
                                    /#21724464

                                    Если придерживаться этих правил, то у Вас будет одна таблица

                                    … одна таблица в БД? Или что?


                                    Что именно противоречит требованию иммутабельности?

                                    Данные в таблицах РСУБД по определению мутабельны.


                                    (я не рассматриваю редкий случай append-only databases, мне почему-то кажется, что вы вряд ли про них)

                                    • snegprog
                                      /#21724508

                                      одна таблица в БД? Или что?

                                      За один тип данных (набора данных примитивного типа) будет отвечать одна таблица, да.

                                      Бойтесь/избегайте непредсказуемого изменения данных

                                      Важнее это. Требование про неизменчивость удалил, вероятно лишнее.

                                      • lair
                                        /#21724576

                                        За один тип данных (набора данных примитивного типа) будет отвечать одна таблица, да.

                                        … а почему? И что такое "примитивный тип"?


                                        Бойтесь/избегайте непредсказуемого изменения данных

                                        Ну давайте это обсудим. Возьмем ваше "определение":


                                        Далее, выделенные данные (совокупность объекта мира и его параметров) буду определять как Тип Данных (далее ТД).

                                        Согласно нему, у Типа Данных нет поведения. Как можно отличить "непредсказуемое" изменение от "предсказуемого"?


                                        И методов у таких классов быть тоже не может.

                                        • snegprog
                                          /#21724664

                                          И методов у таких классов быть тоже не может.

                                          Об этом так же писал и даже писал что в ТД реляционной БД и ТД ООП есть принципиальное отлицие, и даже писал что «Обекты данных» являются плохим тоном в ООП.
                                          Согласно нему, у Типа Данных нет поведения. Как можно отличить «непредсказуемое» изменение от «предсказуемого»?

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

                                          • lair
                                            /#21724936

                                            Об этом так же писал

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


                                            даже писал что «Обекты данных» являются плохим тоном в ООП.

                                            Вот только к типам данных это отношения не имеет.


                                            результате работы с данными.

                                            Любой "результат" — это следствие поведения. Нет поведения — нет результата.

                                            • snegprog
                                              /#21725064

                                              Любой «результат» — это следствие поведения. Нет поведения — нет результата.

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

                                              • lair
                                                /#21725082

                                                управлением данными занимается уже АТД и об этом во второй части.

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


                                                например в ООП можно написать методы работы с данными.

                                                Тогда это не будет Тип Данных по вашему определению.


                                                Ну или у вас проблема с определениями.

                                                • snegprog
                                                  /#21725086

                                                  Тогда это не будет Тип Данных по вашему определению.

                                                  Где Вы такое увидели, подскажите?
                                                  ТД должен уметь работать только со своими данными (полями)

                                                  По моему везде говорится о работе ТД с данными. Только в реляционной БД это не так, об этом так же сказано.
                                                  Все вокруг нас это данные и надо их корректно выделять, а как работать с ними это уже другой вопрос, об этом и идет речь.

                                                  • lair
                                                    /#21725098

                                                    Где Вы такое увидели, подскажите?

                                                    Там, где "выделенные данные (совокупность объекта мира и его параметров) буду определять как Тип Данных (далее ТД)". Это значит, что поведения нет, есть только данные.


                                                    По моему везде говорится о работе ТД с данными.

                                                    Без определения понятия "работа с данными" это бессмысленно.


                                                    Еще раз: либо Тип Данных может иметь поведение, либо нет. Если может, то чем он отличается от абстрактного типа данных по МакКоннелу?

                                                    • snegprog
                                                      /#21725486

                                                      Кажется понял, в чем нестыковка

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

                                                      В реляционной БД например есть таблицы и методов у таблицы быть не может. Структуры в различных языках программирования это так же наборы данных без методов работы с ними. В классах ООП же можно написать и даже нужно написать методы работы с данными, да, это пожалуй то же самое о чем и говорит МакКоннелл, просто развил мысль дальше и во второй части описал как можно управлять всеми данными которые имеем и это назвал АТД, т.к. одна единица ТД может работать только со своими данными, а нам как правило надо управлять набором данных.

                                                      • lair
                                                        /#21726048

                                                        Я повторю свой вопрос: чем ваш Тип Данных отличается от АТД по МакКоннелу, если ваш Тип Данных может иметь поведение?

                                                        • snegprog
                                                          /#21726184

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

                                                          Спасибо! Вы мне помогли сформулировать требование по поводу неизменяемости данных.

                                                          • lair
                                                            /#21726252

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

                                                            Конечно, относить. А почему нет?

                                                            • snegprog
                                                              /#21726378

                                                              Скажу Вам честно, у самого возникал такой вопрос, чем ТД отличается от АТД по С.Макконнелла. А еще он же говорит, что в классах должны быть «нормальные» методы, да и на том же refactoring.guru пишут, что объекты данные это плохо. МакКоннелл вдохновил меня на такой подход, поэтому и упоянул его здесь, хотя про ТД в таком аспекте он не припомню чтобы говорил. По хорошему здесь описан несколько иной подход, я как бы расширил АТД добавив к нему ТД и описав требования к нему. В итоге у нас есть данные в виде ТД и структура которая работает с этими данными, назвал ее АТД т.к. это самое что не на есть наборы данных и методы работы с ними. Это все больше похоже на иной подход, но не буду говорить какой т.к. не хочу здесь устроить холивар.

                                                              Основное отличие ТД от АТД (по моему описанию), это то, что первый не может изменять свои данные в процессе вычислений производимых им самим, а второй может.

                                                              • lair
                                                                /#21726390

                                                                Скажу Вам честно, у самого возникал такой вопрос, чем ТД отличается от АТД по С.Макконнелла

                                                                А зачем вы вообще ввели дополнительное понятие?


                                                                По хорошему здесь описан несколько иной подход, я как бы расширил АТД добавив к нему ТД и описав требования к нему.

                                                                Для того, чтобы расширять что-то, надо с этим чем-то разобраться, а к определению АТД мы даже еще не приблизились.


                                                                Основное отличие ТД от АТД (по моему описанию), это то, что первый не может изменять свои данные в процессе вычислений производимых им самим, а второй может.

                                                                Т.е., как только я добавляю в ТД кэширование результатов, он становится АТД?


                                                                В чем смысл этого разделения?

                                                                • snegprog
                                                                  /#21726520

                                                                  А зачем вы вообще ввели дополнительное понятие?

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

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

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

                                                                  • lair
                                                                    /#21726536

                                                                    Потому что без этого дополнительного понятия я как то раз очень долго мучался над решением одной из задач и никак не мог решить ее

                                                                    Какой задачи? Почему понятия АТД было недостаточно для ее решения?


                                                                    У ТД по определению не может быть много вычислений т.к. его данные неизменны

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


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

                                                                    Так зачем нужно это разделение, если простое добавление кэша, не меняющее наблюдаемое поведение (кроме производительности), меняет категорию объекта?

                                                                    • snegprog
                                                                      /#21726654

                                                                      Какой задачи? Почему понятия АТД было недостаточно для ее решения?

                                                                      Какой именно задачи не могу сказать в силу юредических ньюансов, но во второй части привел пример который на мой взгляд подходит для подобной ситуации. Понятия АТД не хватало т.к. работать приходилось не только с классами ООП, для них вероятно и достаточно его определения, а вот как быть с данными в БД, у таблиц ведь не напишешь свои методы, а еще и для работы с БД используется Data Mapper. Вот и пришёл к тому, что для начала надо корректно выделить данные из окружающего нас мира, с которыми в дальнейшем будет легко работать.

                                                                      • lair
                                                                        /#21726680

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

                                                                        Ваша "вторая часть" работает с АТД. Никаких достоинств ТД как отдельной категории там нет.


                                                                        Понятия АТД не хватало т.к. работать приходилось не только с классами ООП

                                                                        Вообще-то, понятие АТД намного шире, чем классы ООП.


                                                                        вот как быть с данными в БД

                                                                        Для них есть ER-модели.


                                                                        еще и для работы с БД используется Data Mapper

                                                                        А это описано в PoEAA у Фаулера, и никак не связано с АТД.


                                                                        для начала надо корректно выделить данные из окружающего нас мира

                                                                        Это называется "построение модели". Вводить понятие "типа данных" для этого не нужно. Методик моделирования сильно больше одной.


                                                                        Ну и да, ничто из описанного вами не объясняет, зачем нужно разделение на АТД и ТД по признаку "не изменяет данные при вычислениях".

                                                                        • snegprog
                                                                          /#21729712

                                                                          Вообще-то, понятие АТД намного шире, чем классы ООП.

                                                                          Статья не о ADT, в самом начале и было написано что подразумевается под АТД. ADT действительно понятие широкое и эта статья явно не о нем.
                                                                          Для них есть ER-модели.

                                                                          Должен признаться не совсем пойму к чему это, каким образом постороение модели Сущность-Отношение поможет? Более того, как раз эти правила и помогут корректно составить модель БД, да и Вы ниже написали, что это уже вопрос не ТД, а построения модели.
                                                                          А это описано в PoEAA у Фаулера, и никак не связано с АТД.

                                                                          Здесь я описал как выделить данные (сущность мира и минимально избыточные параметры), Data Mapper упомянул потому, что если все запихнуть в одну таблицу, то и в коде ООП это все будет в одном классе (если не заниматься извращениями), что приведет ко множеству IF, а это значит и логика усложнится, и поддержка станет сложнее и в производительности приложение станет дороже (почему, я как раз написал в примере с параллелограммом).
                                                                          Ну и да, ничто из описанного вами не объясняет, зачем нужно разделение на АТД и ТД по признаку «не изменяет данные при вычислениях».

                                                                          Как уже писал выше, у самого возникал вопросы по АТД и ТД. Опишу чуть по подробнее, для чего это все надо было, как к этому пришёл:
                                                                          1. Поступила задача — написать систему по учёту «чего то там» (не буду конкретизировать в силу трудового договора) и на основе этого получать «что то». Вроде все просто, написал сервисный класс в котором вся логика работы. ну и дело в шляпе.
                                                                          2. Поступила задача — добавить в систему функционал по работе еще там с «чем то». Еще один сервисный класс и дело в шляпе.
                                                                          3. Поступила задаче — добавить функционал по работе еще с «чем то». Еще один класс и дело в шляпе.
                                                                          4. Поступила задача — первое «что то» оказывается влияет на второе «что то». Хм, пришлось подумать, как два сервиссных класса совместить.
                                                                          5. Поступила задача — второе «что то» влияет на третье «что то», в свою очередь третье «что то» влияет на первое «что то». Кроме этого, надо добавить функционал для работы с еще «чем то» который в свою очередь влияет на третье «что то», ну а как мы помним третье «что то» влияет на первое «что то». Хм, вот тут бессонные ночи и начались. Ладно, кое как сделал, даже тесты проходят.
                                                                          6. Поступила задача добавить еще «что то» которое в свою очередь влияет на первое и второе «что то». Хм, при малейшем пчихе все тесты повалились, несколько бессонных ночей никчему не привели.
                                                                          Что делать, уволят ведь!?
                                                                          Тут я вспомнил про АТД С.Макконнелла и меня посетила мысль, может от каждого функционала получать нужные данные, собирать их в одном месте и управлять ими как только потредуется!? В итоге перешел на «провайдеры данных» которые получают нужные данные от кажного «чего то там», создаю класс (АТД по С.Макконнелу), передаю в него данные от всех провайдеров данных и далее уже работаю в нем с этими данными, сравниваю эти данные, меняю данные первого «чего то там» в зависимости от данных второго «что то там» и т.д. и т.п.
                                                                          В итоге получилась очень гибкая система, можно добавить любой функционал или изменить старый без лишних хлопот. Заказчик очень доволен и сам своим глазам не верит, что все работает и работает стабильно (подобный пример во второй части и описал).
                                                                          Решил поделится своими мыслями, возможно кого то это так же натолкнет на хорошее решение его задач.
                                                                          Вот и вопрос, отличаются ли данные полученные провайдерами данных от АТД в котором происходит работа с ними? Думаю отличаются, как минимум по функциональным возможностям, возможно Вы меня и натолкнете на правильную формулировку.
                                                                          К чему пришел, как выделять данные с которыми далее работать в АТД здесь и написал. Да, с формулировками у меня сложновато, но если варится в своем соку сами по себе они не появятся.

                                                                          • lair
                                                                            /#21731248

                                                                            Статья не о ADT

                                                                            А почему в заголовке тогда написано "Абстрактный тип данных"?


                                                                            самом начале и было написано что подразумевается под АТД

                                                                            … определение по МакКоннелу. Оно не противоречит тому, что я сказал.


                                                                            Должен признаться не совсем пойму к чему это, каким образом постороение модели Сущность-Отношение поможет?

                                                                            Ровно таким, что оно описывает то, что вы пытаетесь назвать Типом Данных применительно к РСУБД.


                                                                            Data Mapper упомянул потому, что если все запихнуть в одну таблицу, то и в коде ООП это все будет в одном классе

                                                                            Нет, не будет. Весь смысл Data Mapper как паттерна в том, что объектная модель не обязана соответствовать реляционной.


                                                                            что приведет ко множеству IF,

                                                                            Нет, не приведет.


                                                                            db.Get<Square>(); //вот вам квадраты
                                                                            db.Get<Rectangle>(); //вот вам прямоугольники
                                                                            db.Get<Circle>(); //вот вам круги
                                                                            db.Get<Shape>(); //вот вам все фигуры

                                                                            Что делать, уволят ведь!?

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


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

                                                                            … которая никак с АТД по МакКоннелу не связана. Но посетила вас, да.


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

                                                                            Это называется god object. В вашем случае — god class. Не надо так.


                                                                            И нет, это не АТД. Это ровно наоборот.


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

                                                                            А что такое "провайдер данных", и почему он возвращает не АТД?


                                                                            Думаю отличаются, как минимум по функциональным возможностям

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

                                                                            • snegprog
                                                                              /#21731716 / -1

                                                                              Это называется god object.

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

                                                                              Спасибо конечно.
                                                                              декомпонуете вашу задачу на доменные сущности

                                                                              По хорошему об этом речь и идет.
                                                                              определение по МакКоннелу. Оно не противоречит тому, что я сказал.

                                                                              По хорошему нично ничему не противоречит, поэтому и привел в пример ошибку №11 «Строгое следование правилам». Джун пишет все в контроллерах, мидл пишет все на интерфейсах, сеньер знает где можно написать код в контроллере, а где и как использовать интерфейсы (не мои слова).

                                                                              • lair
                                                                                /#21731738

                                                                                Это совсем совсем о другом.

                                                                                Почему? Это соответствует вашему описанию "собирать их в одном месте".


                                                                                Такое ощущение, что мы говорим с вами на различных языках о разных вещах

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


                                                                                По хорошему об этом речь и идет.

                                                                                Нет, не идет. У вас речь идет об АТД и "Типах Данных", а не о доменных сущностях.


                                                                                Терминология важна, понимаете?


                                                                                По хорошему нично ничему не противоречит

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


                                                                                Джун пишет все в контроллерах, мидл пишет все на интерфейсах, сеньер знает где можно написать код в контроллере, а где и как использовать интерфейсы (не мои слова).

                                                                                … мне, конечно, в этот момент очень любопытно, кем вы себя считаете из этого списка.

                                                                                • snegprog
                                                                                  /#21731774 / -1

                                                                                  Терминология важна, понимаете?

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

                                                                                  Богом всевышним, кем я могу себя еще считать то!

                                                    • snegprog
                                                      /#21725986

                                                      “Топ-11 самых частых ошибок в JavaScript” — ошибка №11: Ты следуешь всем правилам,

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

                                                      • lair
                                                        /#21726054

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

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

      • mayorovp
        /#21725842

        У паттерна "Легковес" (хотя обычно его переводят как "Приспособленец") своя терминология, связанная с тем, что несколько классов виртуально "представляют" один.


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