Как запутать аналитика. Часть вторая: что такое моделирование предметной области?

Комментарии (23)

  • НЛО прилетело и опубликовало эту надпись здесь
    • 1 июля 2017 в 12:40

      +1

      Начальные данные таковы, что это не была одна транзакция. Это были две модели разных операций в разных хранилищах.
      • НЛО прилетело и опубликовало эту надпись здесь
        • 1 июля 2017 в 13:13 (комментарий был изменён)

          +1

          обращение в транзакцию убьет информацию, которая была изначально в хранилищах, а мы этого не хотим. Ведь никто не захочет, чтобы кто-то извне менял его модель. Сидоров хочет, чтобы информация о продажах хранилась в том виде, в котором он ее создал. Кому-то, кому надо, пусть создает новые модели, но Сидоров хочет видеть то, что он сделал. Он не согласен на транзакцию, он утверждает, что это была продажа.
          • НЛО прилетело и опубликовало эту надпись здесь
            • 1 июля 2017 в 13:57 (комментарий был изменён)

              +1

              Транзакция — не есть продажа. Это изменилось. Если мы перепишем класс sale в виде обертки над transaction, то вопрос: что делать, если появится третья точка зрения, в которой эта же операция была операцией по истреблению остатков. Если мы перепишем класс истреблений остатков в виде обертки над классом транзакций, то получится, что класс транзакций — это и есть класс неклассифицированных объектов учета. То есть, это будет еще один способ моделирования объекта учета и его классификации при помощи оберток.
              • НЛО прилетело и опубликовало эту надпись здесь
  • 1 июля 2017 в 13:05 (комментарий был изменён)

    +1

    using System;
    using System.Collections.Generic;
    using static System.Console;
    using static System.FormattableString;
    
    namespace InterfacesSample
    {
        interface IColoredEntity
        {
            int ColorCode { get; }
        }
    
        interface IVehicle : IColoredEntity
        {
            string VinNumber { get; }
            int WheelCount { get; }
            int MaxCarryingKgs { get; }
        }
    
        interface IBuilding : IColoredEntity
        {
            bool IsResidental { get; }
            int FloorCount { get; }
        }
    
        class PassengerCar : IVehicle
        {
            public string VinNumber { get; }
            public int WheelCount => 4;
            public int MaxCarryingKgs => 400;
            public int ColorCode { get; }
            public PassengerCar(string vinNumber, int colorCode)
            {
                VinNumber = vinNumber;
                ColorCode = colorCode;
            }
        }
    
        class ResidentalBuilding : IBuilding
        {
            public bool IsResidental => true;
            public int FloorCount { get; }
            public int ColorCode { get; }
            public ResidentalBuilding(int floorCount, int colorCode)
            {
                if (!(floorCount >= 1 && floorCount <= 100))
                    throw new ArgumentOutOfRangeException(nameof(floorCount));
    
                FloorCount = floorCount;
                ColorCode = colorCode;
            }
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                var car1 = new PassengerCar(vinNumber: "VIN 1", colorCode: 0);
                var car2 = new PassengerCar(vinNumber: "VIN 2", colorCode: 1);
    
                var house1 = new ResidentalBuilding(floorCount: 100, colorCode: 2);
                var house2 = new ResidentalBuilding(floorCount: 100, colorCode: 3);
    
                var coloredObjects = new List
                {
                    car1,
                    car2,
                    house1,
                    house2
                };
    
                var vehicles = new List
                {
                    car1,
                    car2
                };
    
                WriteLine("Colored Objects:");
                foreach (var coloredObject in coloredObjects)
                {
                    WriteLine(Invariant(
                        $"Color: {coloredObject.ColorCode:X8}"));
                }
    
                WriteLine("Vehicles:");
                foreach (var vehicle in vehicles)
                {
                    WriteLine(Invariant(
                        $"Vin Number: {vehicle.VinNumber}; Color: {vehicle.ColorCode:X8}"));
                }
    
                // Output:
                //Colored Objects:
                //Color: 00000000
                //Color: 00000001
                //Color: 00000002
                //Color: 00000003
                //Vehicles:
                //Vin Number: VIN 1; Color: 00000000
                //Vin Number: VIN 2; Color: 00000001
            }
        }
    }
  • 1 июля 2017 в 13:54 (комментарий был изменён)

    0

    А можно попросить объяснить мне что такое предметная область? А то я не понимаю, какое отношение имеет цвет, когда описывается предметная область сбыта автомобилей.
    • 1 июля 2017 в 14:50

      +1

      Есть условие задачи. Оно сформулировано в статье. Надо ее решить. Это не практическая задача по моделированию сбыта авто. Это мысленный эксперимент.
      • 1 июля 2017 в 15:06

        0

        Я понимаю что мысленный, но звучит он как «овощи очень вредны, ведь если съесть три тонны лука — то умрешь».
        Мне кажется что если задачу поставить заведомо неправильным образом, то она может привести к неправильным решениям. Почему Вы говорите авто-плаволка, а не транспортное средство? Почему поведение зависит от второстепенных данных не относящихся к предметной области, как например цвет?
        • 1 июля 2017 в 15:16 (комментарий был изменён)

          +1

          Если съесть три тонны лука, то умрешь. Это верно. Но из этого не следует вредность овощей. Из какого тезиса в моей задаче я сделал неверный вывод? То есть, если можно: тезис, вывод, и то, почему он неверный.
      • 1 июля 2017 в 15:13 (комментарий был изменён)

        0

        И почему не введено понятие «товар» с которым бы и проводились все операции. В условиях явно перемешались области-слои, какой Вывод Вы хотели получить? И Вы описываете структуру, а не поведение модели предметной области.
        • 1 июля 2017 в 15:21 (комментарий был изменён)

          0

          Я хочу решение поставленной задачи. Более ничего. Есть два хранилища, их надо соединить в одно. Как бы программист решал эту задачу? Вот мой интерес. При этом стоит условие — для пользователя ничего не должно поменяться — ни названия объектов, ни их свойства.
          • 1 июля 2017 в 15:23

            0

            Программист бы спросил «Зачем?». То есть, какая цель у этой операции.

            • 1 июля 2017 в 16:02

              0

              Будем считать, что ему ответили на этот вопрос, дали денег и заключили контракт. Как он будет это делать?
              • 1 июля 2017 в 16:46

                0

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

                • 1 июля 2017 в 17:03

                  0

                  Его попросили объединить два хранилища так, чтобы каждый из пользователей остался при своих моделях, но тот, кто заказал эту музыку, мог бы видеть, как модели объектов учета меняются в зависимости от разных точек зрения на них. Мы выяснили, что операция была одна и та же, но знаем, что было множество разных стейкхолдеров, которые могли бы видеть ее по-разному. Нам надо построить такую модель, которая удовлетворила бы потребности стейкхолдеров в своих представлениях о мире и могла бы дать нам возможность видеть общую картину в целом. То есть, наша задача интегрировать хранилища, обеспечить их представление для разных пользователей и дать нам инструмент для анализа.
                  • 1 июля 2017 в 18:18

                    0

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


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


                    было:
                    
                    операции_продажи: (хранилище 1)
                    id: 123, время: 2017-06-10 10:26, товары: [A,B,C]
                    id: 124, время: 2017-06-10 10:27, товары: [D,E,F]
                    
                    операции_покупки: (хранилище 2)
                    id: 678, время: 2017-06-10 10:28, товары: [A,B,C]
                    id: 679, время: 2017-06-10 10:29, товары: [D,E,F]
                    
                    стало:
                    
                    операции_продажи: (общее хранилище)
                    id: 123, время: 2017-06-10 10:26, товары: [A,B,C]
                    id: 124, время: 2017-06-10 10:27, товары: [D,E,F]
                    
                    операции_покупки: (общее хранилище)
                    id: 123, время: 2017-06-10 10:28, товары: [A,B,C]
                    id: 124, время: 2017-06-10 10:29, товары: [D,E,F]
                    

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


                    В свою очередь прошу привести пример вашего решения на основе этих данных.

                    • 1 июля 2017 в 19:58

                      0

                      Верно, одним из атрибутов объекта учета является первичный ключ. Но можно добавить еще и другие. Поскольку объект (не множество) — есть 4-хмерный объем, то атрибутами его могут быть границы этого объекта, например, временные: с и по.
              • 1 июля 2017 в 16:47

                0

                ну так ответа однозначного нет. Все дело в том, что машина может быть выражена множеством вариантов в зависимости от позиции наблюдателя — предметной области. Если бы я продавал авто, то мне бы было удобно чтобы тип «авто» инкапсулировал даже цвет. Если бы я продовал машины по запчастям, то авто бы выражалось в виде коллекции её частей. Если бы мне сказали перепроектировать архитектуру магазина авто в магазин запчастей без изменения кода, да ещё за пару часов и пару тыщь, то скорее всего я бы послал просто нафиг.
          • 1 июля 2017 в 15:28

            0

            Я перечитал ещё раз про цвет и транспорт и хочу поправить себя — тут я согласен с Вам, атрибута цвет у транспорта нет.
  • 1 июля 2017 в 14:02

    0

    using System.Collections.Generic;
    using System.Globalization;
    using static System.Console;
    
    namespace InterfacesSample2
    {
        interface ILandVehicle
        {
            int MaxCarryingKgs { get; }
            int MaxPassengers { get; }
        }
    
        interface ISwimmingVehicle
        {
            int MaxCarryingKgs { get; }
            int MaxPassengers { get; }
        }
    
        interface IAmphibian : ILandVehicle, ISwimmingVehicle
        {
        }
    
        class Sedan : ILandVehicle
        {
            public int MaxCarryingKgs => 400;
            public int MaxPassengers => 4;
        }
    
        class Pickup : ILandVehicle
        {
            public int MaxCarryingKgs => 500;
            public int MaxPassengers => 1;
        }
    
        class Boat : ISwimmingVehicle
        {
            public int MaxCarryingKgs => 450;
            public int MaxPassengers => 3;
        }
    
        class UniversalVehicle : IAmphibian
        {
            public int MaxCarryingKgs => 250;
            public int MaxPassengers => 2;
        }
    
        class SwimmingCar : IAmphibian
        {
            public int MaxCarryingKgs => 300;
            public int MaxPassengers => 3;
    
            int ISwimmingVehicle.MaxCarryingKgs => 200;
            int ISwimmingVehicle.MaxPassengers => 1;
        }
    
        class Amphibian : IAmphibian
        {
            int ILandVehicle.MaxCarryingKgs => 350;
            int ILandVehicle.MaxPassengers => 3;
    
            int ISwimmingVehicle.MaxCarryingKgs => 250;
            int ISwimmingVehicle.MaxPassengers => 1;
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                var sedan = new Sedan();
                var pickup = new Pickup();
                var universalVehicle = new UniversalVehicle();
                var swimmingCar = new SwimmingCar();
                var amphibian = new Amphibian();
                var boat = new Boat();
    
                var landVehicles = new List()
                {
                    sedan, pickup, universalVehicle, swimmingCar, amphibian
                };
    
                var swimmingVehicles = new List
                {
                    universalVehicle, swimmingCar, amphibian, boat
                };
    
                var amphibians = new List
                {
                    universalVehicle, swimmingCar, amphibian
                };
    
                WriteLine("Land Vehicles:");
                foreach (var vehicle in landVehicles)
                {
                    WriteLine(string.Format(
                        CultureInfo.InvariantCulture,
                        "MaxCarryingKgs: {0}; MaxPassengers: {1}",
                        vehicle.MaxCarryingKgs, vehicle.MaxPassengers));
                }
    
                WriteLine("Swimming Vehicles:");
                foreach (var vehicle in swimmingVehicles)
                {
                    WriteLine(string.Format(
                        CultureInfo.InvariantCulture,
                        "MaxCarryingKgs: {0}; MaxPassengers: {1}",
                        vehicle.MaxCarryingKgs, vehicle.MaxPassengers));
                }
    
                WriteLine("Amphibians:");
                foreach (var vehicle in amphibians)
                {
                    WriteLine(string.Format(
                        CultureInfo.InvariantCulture,
                        "MaxCarryingKgs: {0}/{1}; MaxPassengers: {2}/{3}",
                        ((ILandVehicle)vehicle).MaxCarryingKgs,
                        ((ISwimmingVehicle)vehicle).MaxCarryingKgs,
                        ((ILandVehicle)vehicle).MaxPassengers,
                        ((ISwimmingVehicle)vehicle).MaxPassengers));
                }
    
                // Output:
                //Land Vehicles:
                //MaxCarryingKgs: 400; MaxPassengers: 4
                //MaxCarryingKgs: 500; MaxPassengers: 1
                //MaxCarryingKgs: 250; MaxPassengers: 2
                //MaxCarryingKgs: 300; MaxPassengers: 3
                //MaxCarryingKgs: 350; MaxPassengers: 3
                //Swimming Vehicles:
                //MaxCarryingKgs: 250; MaxPassengers: 2
                //MaxCarryingKgs: 200; MaxPassengers: 1
                //MaxCarryingKgs: 250; MaxPassengers: 1
                //MaxCarryingKgs: 450; MaxPassengers: 3
                //Amphibians:
                //MaxCarryingKgs: 250/250; MaxPassengers: 2/2
                //MaxCarryingKgs: 300/200; MaxPassengers: 3/1
                //MaxCarryingKgs: 350/250; MaxPassengers: 3/1
            }
        }
    }

© Habrahabr.ru