Плавание через планирование

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

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

Купание в морях Схемы

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

Первой проблемой, которую мы обнаружили, было ограничение внешнего ключа. Мы были ограничены использованием PostgreSQL для этого проекта, но я бы все равно выбрал именно его. Мне нравится использовать SQLite для однопользовательских настольных приложений, а иногда и для серверов разработки, потому что его очень легко настроить, но для такого продукта требуется более надежный вариант. Внешний ключ — это свойство объектов в одной таблице, которое указывает на объект в другой таблице. Иногда это просто обрабатывается как ссылка. Например, в нашей таблице workOrder у нас есть workOrder.company указывающий на company.id . Эти отношения представлены на диаграмме стрелками.

В Postgres, как и во многих реляционных базах данных, такая ссылка может быть ограничена внешним ключом, что требует, чтобы свойство указывало на объект в другой таблице. Если это null или объект не существует, выдается ошибка. Это также сбивает с толку, когда объект, на который ссылаются, удаляется, если вы не скажете ему, что делать.

Например, мой первоначальный код миграции для добавления role и company в таблицу profiles (пользователи) был таким:

exports.up = (knex) => {  
  return knex.schema.table('profiles', function (table) {    
    table.integer('role').unsigned();    
    table.foreign('role').references('roles.id');    
    table.integer('company').unsigned();    
    table.foreign('company').references('companies.id');
  });
};

Этот маленький .foreign() делает это свойство ограниченным внешним ключом, и в других таблицах было несколько других. Это вызвало у нас две проблемы. Во-первых, когда мы попытались удалить объект, на который указывает ссылка, база данных выдала ошибку и не удалила объект. Мы могли бы обойти это, добавив .onDelete('CASCADE') к ссылке (потому что мы сообщали базе данных, что делать, когда объект был удален). Итак, я сделал это, но это не решило нашу вторую проблему: когда мы создавали или удаляли связанные объекты, мы должны были следить за порядком, в котором объекты добавлялись или удалялись.

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

Восхождение на горы слияний

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

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

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

Понравилось это маленькое приключение? Рассмотрите возможность передачи DOGE DL4pRWvnE4voqRWDFT6jH2exgQexeU5cB9.