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

Принцип открыто-закрыто

Если вы, как разработчик, никогда не слышали о принципах SOLID, я бы порекомендовал вам ознакомиться с ними немедленно. И открытость-закрытость — один из ее принципов, предполагающий, что любой компонент должен быть открыт для расширения, но закрыт для модификации.

Что это значит? Допустим, у нас есть класс SalaryCalculator, который отвечает за расчет дневной заработной платы сотрудника с использованием почасовой ставки * рабочих часов, и система работала нормально в течение нескольких месяцев, пока компания не решила повысить почасовую ставку сверхурочных рабочих часов в 1,5 раза. Икс.

Некоторые разработчики могут выполнить требование, просто добавив новые начальные значения расчета в SalaryCalculator и изменив формулу на обычную зарплату + зарплату за сверхурочную работу. Он делает то, что мы хотим, просто не так, как хотелось бы.

К чему внезапный пример разработки программного обеспечения?

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

Однако в любом случае система, скорее всего, потребует перекомпиляции и апгрейда.

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

Представьте, что произойдет, если зарплата предоставляется через службу REST, и все, что нужно вашей системе, — это просто GET https://salary-cloud.com/employees/salaries для получения всей необходимой информации. Независимо от того, как эта служба обновляется, ваша система остается, если не меняются входные или выходные данные.

Я до сих пор не знаю, почему вы говорили о SOLID…

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

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

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

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

REST API

Вернемся к GET https://salary-cloud.com/employees/salaries. Подумайте, если мы определим только IEmployeeSalary, который содержит decimal Salary { get; }, мы затем разработаем другой проект API, который реализует этот интерфейс и предоставит IEmployeeSalary[] в указанной выше конечной точке? Может быть, также предоставлять только IEmployeeSalary в https://salary-cloud.com/employees/STAFF_001/salaries/2020-03?

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

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

Да ... тесты

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

Вы меня понимаете, это действительно боль где-то…

НИКТО не любит добавлять тесты для запущенной системы, ни разработчик. Тем не менее, мы представили подход SoA нашим командам в прошлом году, и оказалось, что до сих пор никому не нравится добавлять тесты (ха-ха, вы не ожидали этого, не так ли?), но это сняло некоторые неприятные ощущения, тесты один сервис обычно около 30, если не слишком сложно (и не должно).

Услуги докера

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

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

Вывод



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

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