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

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

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

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

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

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

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

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

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

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

Сколько от этого пользы судите сами.

  1. Уменьшаются разногласия между составителем ТЗ и разработчиком. Общие слова подкреплены конкретикой.
  2. Уменьшается вероятность того, что в отлаженный алгоритм попадут параметры, на которых он не тестировался.
  3. Становятся видны места в коде, где надо добавлять обработку новых типов.
  4. Повышается уровень дисциплины в коде. Увеличивается вероятность, что логика будет концентрироваться в одном и том же месте, а не будет разбросана.
  5. Облегчается формализация и автоматический анализ кода.


Я не предлагаю хардкодить списки, когда их можно вести в базе. Просто привожу простейшие примеры для иллюстрации принципов на псевдокоде, похожем на pl/sql.

//Пример 1.
//Неверный код, нет проверки на попадание нового типа.
//Список изменяется со временем, появляются разночтения с начальным ТЗ.
//Со временем этот кусок кода влияет на все большее количество данных,
//поэтому изменения становится рискованным.
forall type_id in (all_type_list) loop
  do_something;
end loop;

//пример 2
//тоже
if type_id not in (555,666) then 
  do_something;
end if;

//пример 3
//Неверный код, нет проверки на попадание нового типа.
//В случае нового типа выполнение продолжается без предупреждений
//Действие не выполняется, и на это могут не обратить внимания
if type_id in (333,444) then 
  do_something;
end if;

//////////////////////////////////////////////////////////////////////
//Верный код и его развитие. ////////////////////
//Пример 4.
if type_id in (1,2,3) then
  do something;
else
  //Попался неизвестный тип, сигнал добавить новую обработку, см ниже.
 raise error;
end if;


//Развитие кода для новых типов 4,5,6.
//Вариант 1, новые типы обрабатываются стандартно по старому.
if type_id in (1,2,3,4,5,6) then
  do_something;
else
 raise error; 
end if;


//Вариант 2, новые типы обрабатываются особо.
if type_id in (1,2,3) then
  do_something;
elsif type_id in (4,5,6) then
  do_something_2;
else
 raise error; 
end if;

Планирую написать продолжение на темы:

  • как обрабатывать связки условий типов/под-типов
  • как автоматически обнаруживать противоречивые требования в ТЗ
  • как автоматизировать составление списков и позволить аналитику ими управлять
  • как использовать математику для анализа системы
  • развитие проекта через мета-системы

Д.А.Рыбаков, 2016
к.т.н.
Поделиться с друзьями
-->

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


  1. samizdam
    18.10.2016 13:08
    +1

    Если посмотреть с точки зрения объектно-ориентированной парадигмы, то озвученная проблема решается следующим образом:
    Есть абстрактный тип данных «Договор» в виде интерфейса или абстрактного класса. Изначально, в первой версии ТЗ, система реализует N конкретных типов договора, каждый из которых представлен классом наследником абстрактного.
    Весь код в системе, который должен обрабатывать различные конкретные типы знает только об общем интерфейсе.
    Т.о. нет нужды плодить проверки if / else if / else по type_id, т.к. вся специфичная логика окажется локализованной в специальных классах. Это будет проще в поддержке, поскольку разработчикам не будет нужды беспокоиться о размазанной по программе специфике работы с разными договорами, можно будет мыслить на одном из уровней абстракций: либо конкретного подтипа, либо более общего кода.


    1. dim2r
      18.10.2016 13:33

      >Есть абстрактный тип данных «Договор» в виде интерфейса или абстрактного класса.


      В ООП проблема остается, абстракция — это обобщение. Свойства договора на момент ТЗ фиксированы. Это очевидно. Вопрос — что будет в будущем? Появится новый тип договора и заказчик не гарантирует, что он будет попадать под старые свойства. Приведенный метод сразу будет сигнализировать во всех местах, где нужно обрабатывать новый тип. Как такое можно сделать на ООП — вопрос открытый? Какие есть идеи?


      1. samizdam
        18.10.2016 13:41

        Новый тип договора — новый тип в коде.
        Меняются свойства — меняется код. Концепция Domain driven design. DDD.
        Код должен быть покрыт тестами. Меняются требования — находим тесты их покрывающие, адаптируем к изменениям, убеждаемся, что тесты упали. Адаптируем код для прохождения тестов в условиях новых требований. TDD методология разработки.


        1. dim2r
          18.10.2016 13:51

          тесты и ООП — это разные вещи, друг друга не исключают


          1. samizdam
            18.10.2016 14:28

            А разве кто-то утверждает что исключают?

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

            Мне не совсем понятна мотивация для использования Вашего подхода. В многих языках есть конструкция утверждений (assert), по логике в приведённом псевдокоде стоило бы использовать её.

            Только зачем, если проблема в сообществе DDD давно решена более легкими в поддержке и изящными способами?


            1. dim2r
              18.10.2016 15:23

              >В многих языках есть конструкция утверждений (assert), по логике в приведённом псевдокоде стоило бы использовать её


              Главное, что бы принцип был понятен, а использовать assert или еще что-то другое — не важно. От перемены названия мало что меняется.

              >Только зачем, если проблема в сообществе DDD давно решена более легкими в поддержке и изящными способами?

              приведите пример


              1. samizdam
                18.10.2016 15:29

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


                1. dim2r
                  18.10.2016 15:35

                  Я про другое — если Вы в базу вносите новый тип договора, то как будет реагировать старая программа? Будет тихо с ним работать или всё таки возмутится? Сможете ли вы сразу определить где вносить правки для обработки нового типа?


                  1. samizdam
                    18.10.2016 15:47
                    +2

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

                    Если некоторые данные влияют на логику их обработки, значит это уже не просто данные, а часть кода. Помочь могут перечислимые типы, как писал ниже i360u.
                    Я вижу одно локализованное место для их использования: в коде инстанцирующем конкретные экземпляры объектов (репозиторий / фабрика), которые сопоставляют данные с подходящей реализацией.
                    Различия стоит локализовать в конкретных типах, а не размазывать по коду приложения. Иначе это будет напоминать ситуацию описанную в недавней статье: https://habrahabr.ru/post/312792/


                    1. dim2r
                      18.10.2016 15:57

                      >Вы предлагаете хардкодить в логике данные

                      Нет не предлагаю хардкодить.
                      Я описал принцип и максимально примитивно его продемострировал.
                      Собирался написать продолжение кому и как вести эти списки.


                    1. dim2r
                      18.10.2016 16:09

                      >Такой путь к хорошему не приведёт, т.к. придётся менять каждый раз менять исходный код при изменении данных.

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


                    1. dim2r
                      18.10.2016 16:21

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

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

                      if type_id in (1,2,3) then
                       return new class instance;
                      else
                       throw error;
                      end if;
                      


                      1. samizdam
                        18.10.2016 16:41

                        interface Contract {}
                        
                        class ContractA implements Contract{}
                        
                        class ContractB implements Contract{}
                        
                        class Contract_100500 implements Contract{}
                        
                        class ContractRepository() {
                          
                          enum ContractType {
                             A,
                             B, 
                             _100500
                          }
                        
                        public Contract getById(int id) {
                             // вот здесь по хорошему _единственное_ подходящее место
                             // для свитча по перечислению имеющихся типов
                             // алгоритм инстанцирования сводиться к 
                             // 1. пойти в хранилище, взять строку по ID,
                             // 2. исходя из полученных данных инстанцировать нужную реализацию. 
                          }
                        }
                        
                        


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


                        1. dim2r
                          18.10.2016 17:06

                          с простым случаем разобрались наконец


                          1. Fortop
                            19.10.2016 11:36
                            +1

                            Стойкое ощущение от вашего диалога, что вам нужно писать материал по теме, и вы таким образом его собираете…

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


                            1. dim2r
                              19.10.2016 12:16

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


                              1. Fortop
                                19.10.2016 12:24

                                Это возникает в большинстве проектов занимающих больше нескольких человеко-лет.
                                И развивающихся в процессе своей жизни.

                                В общем предлагаю развить и закончить вашу мысль.
                                Поскольку в таком виде это скорее как антипаттерн для средних и больших проектов (а таковыми считаются, насколько я помню, проекты более 3-5 человеко-лет для средних и свыше 10-15 для больших)


                                1. dim2r
                                  19.10.2016 12:42

                                  В общем предлагаю развить и закончить вашу мысль.

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

                                  Поскольку в таком виде это скорее как антипаттерн для средних и больших проектов

                                  В моем проекте объем примерно 20 лет * 100 чел. Мне доступно примерно 2 Гб кода, примерно 20 млн строк кода. Сколько кода всего в системе сказать не могу. Такие дела


            1. dim2r
              18.10.2016 15:28

              «Любую проблему можно решить ещё одним уровнем абстракции. Кроме излишней абстракции.».

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


              1. samizdam
                18.10.2016 15:53

                Зато Вы, судя по предлагаемому решению сугубо за хардкод айдишников с дублированием.

                Спасибо за предложение, мне вполне хватает исходников, и на работе и дома.

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


                1. dim2r
                  18.10.2016 16:25

                  >Зато Вы, судя по предлагаемому решению сугубо за хардкод айдишников с дублированием

                  Не я против, Вы придираетесь. Чем сильнее придираетесь, тем лучше поймете мысль. Хардкод исключительно для демонстрации


        1. dim2r
          23.10.2016 22:39

          >Концепция Domain driven design. DDD.

          Кстати, не все так хорошо с DDD.
          Цитатата из https://habrahabr.ru/post/313110/
          «DDD Работает хорошо в устоявшихся бизнес-процессах»

          Я-то поднял проблему изменяющихся бизнес-процессов. С устоявшимися все понятно и так.


      1. potan
        19.10.2016 15:03

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


        1. dim2r
          19.10.2016 16:04

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

          Если вы знаете что переделывать. А если вам досталось от предыдущих разработчиков сотни пакетов, большинство которых порядка 10 тыс строк кода, процедуры со 120ю параметрами и многое другое, то разобраться сразу затруднительно куда вставлять обработку нового типа.

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


          1. potan
            19.10.2016 16:10

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


            1. dim2r
              19.10.2016 16:43

              Специфика больших проектов в том, что есть зоопарк инструментов, используются старые технологии вперемешку с новыми, никто не видит полной картины и тд и тп. Зачастую непонятен стек вызова. Бывает такое: Нажимаешь на кнопку, она дает ошибку. Начинаешь разбираться, открываешь проект. В проекте кнопки нет. Через день понятно, что она рисуется через WinAPI. Далее она подгружает dll специальным загрузчиком с сервера. Там вызывается COM объект. COM открывает форму, в которой все компоненты получают данные через HTTPS от объектов на сервере. Объекты на сервере вызывают движок ActiveScript, который берет скрипты из базы данных, которые сами берут данные из хранимых процедур, которые возвращают refcursor. На третий день нашел где ошибка, поправил одну строчку.

              Как это можно загрузить в диаграмму — непонятно.


  1. i360u
    18.10.2016 13:16

    Перечисляемые типы вроде как для этого и созданы? И всякие велосипеды для их эмуляции там, где они "by design" не предусмотрены? И это, вроде как, для всех, кто хоть как-то работает со структурами данных обычная практика? Или я неправильно все понял?


    1. dim2r
      18.10.2016 14:00

      >И это, вроде как, для всех, кто хоть как-то работает со структурами данных обычная практика?

      Выдавать ошибку, когда встретился незнакомый тип, «by design» не обеспечивает. По крайней мере на уровне языков такого не встречал.


      1. i360u
        18.10.2016 14:25

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


        1. dim2r
          18.10.2016 14:39

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

          if  Is_in_list(type_id, "список типов, ТЗ от 01.01.2016") then
          do something;
          end if;
          


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

          «При обработке 'список типов, ТЗ от 01.01.2016' возникло исключение в таком-то куске кода. Требуется либо добавить новый тип в список, либо внести изменения в код для особой обработки этого типа»


          1. i360u
            18.10.2016 14:55

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


            1. dim2r
              18.10.2016 15:06

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


              1. Fortop
                19.10.2016 11:42
                +1

                Список договоров в модуле операциониста по работе с юр. и такого же операциониста с физ.лицами отличаются.

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

                При этом все они являются регламентированными


            1. dim2r
              18.10.2016 15:12

              >но это же довольно банальное умозаключение

              да банально, не спорю,

              Есть анекдот от Мамонова про старого гитариста.Выходит молодой гитарист и начинает играть и левой рукой и правой и вверх тормашками и за спиной и над головой. Выходит старый именитый гитарист, сел на стульчик и начинает на трех аккордах играть. Его спрашивают — «чего ж ты такой примитив гонишь? вон видишь молодой как скачет». «Вы понимаете», спокойно отвечает старый — «он еще ищет, а я уже нашел».


  1. Scf
    18.10.2016 23:32

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


    У меня на прошлой работе был как раз такой пример — когда на каждый тип договора аналитик писал ТЗ с табличкой что куда сохранять и как, тестировщик писал автотесты, а мы имплементили согласно ТЗ. В итоге у нас было очень мало багов… и очень длинный цикл разработки. В то время как заказчик хотел "сделайте как у типа 123, но с такими-то изменениями". И пусть даже там будут баги, зато эти десятки новых типов будут добавлены за разумное время.


    1. dim2r
      19.10.2016 08:32

      Было бы интересно узнать ваш опыт.

      Возможно истина где-то посередине. Программа как-то сама должна фиксировать списки типов на момент её написания и выдавать ошибки, не всегда, а только когда, к примеру, тестер захочет протестировать в строгом режиме.


      1. Fortop
        19.10.2016 11:55

        Вам уже предложили рабочее решение этого вопроса.

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

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


        1. dim2r
          19.10.2016 12:29

          Вам уже предложили рабочее решение этого вопроса.

          Извините, но предложенный шаблон не решает проблему, которую я поднял без кода, который я привел.

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


          1. Fortop
            19.10.2016 12:35

            Она и не будет решаться без кода.

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

            Вы можете это запрограммировать и сделать конфигурируемым… Но в сложных проектах это потребует прикладников внедренцев, как в тех же 1С, SAP.

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


            1. dim2r
              19.10.2016 12:47

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

              Хорошо, когда вы знаете что дописывать. В моем проекте из-за большого объема заранее неизвестно что надо дописывать.


              1. Fortop
                19.10.2016 12:58

                Это не соответствует действительности.

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

                Во всех остальных случаях ваша модель должна наследовать и реализовывать конкретный общий интерфейс


                1. dim2r
                  19.10.2016 13:26

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

                  Имеется 2 Гб кода, котрый находится в постоянном развитии. На некоторые модули по 10 человек очереди. Тут нужны навыки человека дождя. :):):)


                  1. Fortop
                    19.10.2016 13:36

                    Я вас огорчу.

                    Редко поведение вашей прикладной модели отличается от уже реализованных настолько, что требуется изменить все 2 Гб кода (возможно удивлю, но небольшой проект на node.js может подтянуть в себя 0.5 Гб зависимостей в коде).
                    Поэтому в рамках вашей задачи по наращиванию системы не новым, а модификацей уже существующего функционала вам редко потребуется взаимодействовать с кодом более 10-20 тысяч строк.
                    В противном случае вам лучше произвести декомпозицию задачи.

                    Что касается очереди…
                    То современные системы контроля версий позволяют вести параллельную разработку над одним модулем (git/mercurial).

                    Намного больше сложностей у вас возникает в случае монолитных систем.


                    1. dim2r
                      19.10.2016 13:52

                      Извините, я не огорчусь, ибо огорчаться нечему. Наоборот, даже интересно пообшаться со знающими людьми. Чем критичнее человек настроен, тем лучше воспринимает сказанное. К сожалению, не могу раскрывать детали происходящего на проекте, а то бы можно было бы обменяться более плодотворными идеями. Удачи


                      1. Fortop
                        19.10.2016 13:56

                        В проекте на 100 человек, если он ещё не развалился, уже есть знающие люди.

                        Пользуйтесь внутренней экспертизой.
                        Минимум 3-5 человек адекватного уровня и опыта у вас должны быть


                        1. dim2r
                          21.10.2016 12:03

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