Привет! Меня зовут Грант, я .Net-разработчик. Знаете вы это или нет, но ваш код можно переиспользовать: будь то модуль, компонент или архитектура. Одни разработчики делают это осознанно, другие на уровне рефлексов. Повторное использование хорошего кода экономит время и другие ресурсы, позволяет применять лучшие практики на проектах, чтобы в итоге эффективнее решать бизнес-задачи.
Мне стало интересно разобраться, когда возможен code reuse, какие проблемы стоит предусмотреть, и какие ресурсы заложить при реализации проектов. Для этого я проанализировал более 30 источников, в том числе иностранных, и вспомнил свой личный опыт на проектах. Разберу классификации механизмов повторного использования и расскажу о своей, покажу примеры разных масштабов: от уровня нескольких операторов до уровня архитектуры.
Этот обзор полезен практически для всех разработчиков. Кто-то столкнется с понятиями идиом или архитектурных тактик, кому-то статья поможет систематизировать имеющиеся знания, кто-то найдет полезные материалы для решения конкретных кейсов при разработке и проектировании программ.
Что такое повторное использование ПО
В процессе разработки существует множество вещей, которые можно использовать повторно: например, документацию, исходный код, объекты, дизайн, архитектуру и даже другое программное обеспечение.
Однако в связи с тем, что под повторным использованием ПО чаще всего понимают повторное использование исходного кода, многие воспринимают его как единственный вариант. Мы разделяем эти понятия, и для ясности приведем такое определение:
Повторное использование программного обеспечения — это процесс создания программных систем на основе существующего программного обеспечения, а не создание их с нуля [1].
Стоит также учесть, что более значительное увеличение производительности (с точки зрения скорости разработки, а не скорости исполнения алгоритмов) будет результатом повторного использования более высоких уровней абстракции.
Мы будем говорить о переиспользовании кода и компонентов с разных уровней масштаба и абстракции, а именно рассмотрим:
уровень кода;
уровень, лежащий непосредственно над уровнем программного кода (программные структуры, из которых состоят модули);
модули;
компоненты, единицы развертывания;
архитектуры.
Три классификации механизмов повторного использования кода
Начнем с классификации, которую предлагает Эрих Гамма [2].
Он выделяет три уровня повторного использования.
Фреймворки находятся на самом высоком уровне. Они определяют ключевые абстракции для решения проблемы.
На среднем уровне — шаблоны проектирования. Они меньше и более абстрактны, чем фреймворки.
На самом низком уровне располагаются классы: библиотеки классов, контейнеры, объединения классов (например, контейнеры или итераторы).
Таким образом, уровень повторного использования повышается, если переходить от классов к шаблонам и, наконец, к фреймворкам.
Еще одна классификация, которая представлена «бандой четырех» [3]:
Между указанными на рисунке механизмами нет стрелок, указывающих отношение иерархии, так как все они применяются в паттернах проектирования и относятся к уровню, который лежит непосредственно над уровнем программного кода.
Наконец, предлагаем нашу классификацию, элементы которой стремятся к некоторому упорядочению, но не всегда содержат строгие границы между собой. Например, некоторые идиомы могут быть как на уровне нескольких операторов, так и на уровне подпрограмм. При ее создании мы опирались на первую классификацию, проведя более подробную декомпозицию блоков, добавив других элементов после обзора механизмов и проведя частичное упорядочивание:
Что не вошло?
В нее мы не включили такие элементы, как чистые функции, «ленивые» функции, функции высшего порядка и прочие, так как они входят в подпрограммы.
Отметим также, что некоторые методы рефакторинга используют механизмы повторного использования для избавления от таких «запахов кода», как дублирование кода или большие классы [4].
Блок «Архитектуры» многогранен, и множество концептов онтологии проектирования архитектуры может включать в себя:
эталонные архитектуры;
архитектурные стили;
архитектурные шаблоны;
шаблоны развертывания;
архитектурные тактики.
Более подробно об архитектурах поговорим в одноименном разделе далее.
Еще одна классификация
Можно также упомянуть классификацию принципов переиспользования дизайна [5]. Здесь собраны принципы за несколько десятилетий, они не зависят от языка и предметной области. Подходы, которые описаны в принципах дизайна, перекликаются с механизмами повторного использования кода, однако, сейчас мы не об этом.
Далее приведем обзор нетривиальных механизмов повторного использования, таких как идиомы, паттерны, библиотеки, фреймворки и архитектуры.
Идиомы
Если про константы, переменные, подпрограммы, классы и структуры мы слышим достаточно часто и переиспользуем их повседневно, то про идиомы мало кто упоминает. Однако мы с ними встречаемся с завидной регулярностью.
В естественных языках идиома — это фраза, которая имеет не буквальное значение. Например, «she has a green thumb» дословно означает, что «у нее зеленый большой палец». А настоящее значение — «она хороший садовод, у нее талант в выращивании растений». Или идиома на русском языке «держать язык за зубами» означает «молчать, хранить тайну».
В искусственных языках идиома — это шаблон решения задачи путем комбинирования встроенных элементов языка. Поэтому идиома зависит от конкретного языка.
Приведем несколько примеров идиом для C#.
«When normalizing strings, it is highly recommended that you use ToUpperInvariant instead of ToLowerInvariant because Microsoft has optimized the code for performing uppercase comparisons»
Используйте паттерн var для сопоставления с любым выражением, включая null, и присвоения его результата новой локальной переменной:
static bool IsAcceptable(int id, int absLimit) =>
SimulateDataFetch(id) is var results
&& results.Min() >= -absLimit
&& results.Max() <= absLimit;
static int[] SimulateDataFetch(int id)
{
var rand = new Random();
return Enumerable
.Range(start: 0, count: 5)
.Select(s => rand.Next(minValue: -10, maxValue: 11))
.ToArray();
}
Вместо большого количества логических операторов “||”
if (myVar == 2 || myVar == 5 || myVar == 10)
DoSomeOperation();
используйте массив соответствующих значений и метод расширения Any<TSource> из пространства имен System.Linq:
var allowedValues = new int[] { 2, 5, 10 };
if (allowedValues.Any(t => myVar == t))
DoSomeOperations();
Вместо множества условных операторов “If” для поиска значения
var someKey = FindKey();
if (someKey == null)
someKey = FindAlternateKey();
if (someKey == null)
someKey = FindDefaultKey();
используйте, например, коллекцию делегатов Func<TResult> из пространства имен System и метод расширения FirstOrDefault<TSource> из пространства имен System.Linq:
var fallback = new List<Func<SomeObject>>
{
FindKey(),
FindAlternateKey(),
FindDefaultKey()
};
var someKey = fallback.FirstOrDefault(t => t != null);
Управление ресурсами с помощью конструкции using
using (StreamReader sr = File.OpenText(path)) {
content = sr.ReadToEnd();
}
Используйте цепочку операторов null-объединения “??” для множественного сравнения с null:
string result = value1 ?? value2 ?? value3 ?? String.Empty;
Или похожий пример, но из веб-разработки:
string partner = Request.QueryString["GoogleId"] ??
Request.QueryString["PartnerId"] ??
Request.QueryString["UserKey"] ??
string.Empty;
При использовании оператора switch вместо вложенного условия if/else в выражении case
switch (myVar)
{
case aCase:
if (someCondition)
{
DoX();
}
else
{
DoY();
}
break;
}
используйте выражение case/when:
switch (myVar)
{
case aCase when someCondition:
DoX();
break;
case aCase:
DoY();
break;
}
Полезные ссылки
Эти и некоторые другие идиомы C# можно найти здесь:
Почти 100 идиом на языке C++ приведено на Wikibooks. И еще множество идиом с фильтрацией по различным языкам программирования.
Идиомы существуют также в тестировании. Например, для того, чтобы обеспечить соблюдение лучших практик при написании тестов с применением Autofixture разработан пакет AutoFixture.Idioms.
Из приведенных примеров и источников (под спойлером выше) видно, что идиомы требуют хороших знаний специфики языка и стандартов. Иногда это связано с синтаксическим сахаром, а иногда просто с устоявшимися правилами.
Однако при всех своих преимуществах у идиом есть и недостатки. Отметим следующие:
Их применение ведет к тому, что разработчикам других языков сложнее понять код;
Лаконичные идиомы не всегда являются эффективным решением.
Расширенная классификация паттернов
Следующие механизмы повторного использования, которые мы рассмотрим — это паттерны.
Обычно имеют в виду 23 паттерна проектирования, которые описаны «бандой четырех» [3].
На следующем рисунке мы привели расширенную классификацию, которая кроме классических паттернов проектирования содержит:
идиомы как низкоуровневые паттерны;
паттерны реализации;
паттерны тестирования;
паттерны анализа;
паттерны параллельного программирования;
архитектурные паттерны.
Про идиомы мы уже говорили ранее, рассмотрим остальные элементы.
Паттерны реализации (Implementation patterns) — совокупность компонентов и других элементов реализации, используемых в структуре модели при написании программного кода.
Они делятся на:
паттерны организации программного кода;
паттерны оптимизации программного кода;
паттерны устойчивости кода;
паттерны разработки графического интерфейса пользователя и другие.
Паттерны тестирования (Test patterns) — особый тип шаблонов, которые могут использоваться на этапе тестирования для уменьшения избыточности, экономии времени и ресурсов и обеспечения эффективного механизма повторного использования для большего покрытия и повышения качества сопровождения одновременно [8].
Паттерны анализа (Analysis patterns) — это группа связанных общих объектов (мета-классов) со стереотипными атрибутами (определениями данных), поведением (сигнатуры методов) и ожидаемыми взаимодействиями, определенными независимо от предметной области [9].
К ним относятся паттерны бизнес-моделирования ARIS (Architecture of Integrated Information Systems). Также каталог таких паттернов представлен в труде Фаулера [10].
Паттерны параллельного программирования (Concurrency and Parallel programming patterns). В настоящее время сложно представить эффективную многопользовательскую программу без конкурентной разработки. Такие паттерны содержат модели успешных решений тех проблем, с которыми разработчики сталкиваются при конкурентной разработке.
При этом полезно отличать понятия конкурентности и ее разновидностей:
Конкурентность — выполнение сразу нескольких действий в одно и то же время;
Многопоточность — форма конкурентности, использующая несколько программных потоков выполнения;
Параллельная обработка — выполнение большого объема работы за счет; распределения ее между несколькими потоками, выполняемыми одновременно;
Асинхронное программирование — разновидность конкурентности, использующая обещания или обратные вызовы для предотвращения создания лишних потоков [11].
Архитектурные паттерны (Architectural patterns) — множество предварительно определенных подсистем со спецификацией их ответственности, правил и базовых принципов установления отношений между ними.
К данной категории можно отнести такие паттерны:
многоуровневая архитектура;
каналы и фильтры;
клиент — сервер;
управляемая событиями архитектура;
архитектура на основе микросервисов;
-
модель — представление — контроллер:
MVC;
HMVC (Hierarchical MVC) — расширение MVC с помощью иерархии триад;
MVP — модификация MVC, в которой View больше не следит за обновлениями Model, события проходят через Presenter;
MVVM — модификация MVC с применением концепции «связывания данных».
EBI (Entity-Boundary-Interactor) — альтернатива MVC, при которой основные элементы и поведения, представляемые объектами Interactor и Entity, отделены от входящих и исходящих данных с помощью Boundary.
Что еще можно отнести к архитектурным паттернам
В некотором смысле к архитектурным паттернам можно отнести каталог паттернов для архитектуры корпоративных приложений, которые описаны у Мартина Фаулера [7].
Непосредственно паттерны проектирования активно представлены в платформах разработки. Обычно это происходит в двух формах:
Паттерны применены для решения определенных задач в самой платформе.
Платформа предоставляет нужные механизмы (обычно это соответствующие интерфейсы) для удобной реализации паттернов.
Рассмотрим несколько таких примеров на C#.
Примеры используемых паттернов в платформе:
-
Фабрики/фабричные методы
Microsoft.Extensions.Logging.LoggerFactory
— создает экземплярыMicrosoft.Extensions.Logging.ILogger
на основе заданных поставщиковMicrosoft.AspNetCore.Http.MiddlewareFactory
— реализация IMiddlewareFactory по умолчанию, которая содержит методы для созданияMicrosoft.AspNetCore.Http.IMiddleware
System.Threading.Tasks.TaskFactory
— обеспечивает поддержку для создания и планирования задач System.Threading.Tasks.Task
-
Строитель, builder
System.Text.StringBuilder
— представляет собой изменяемую строкуMicrosoft.AspNetCore.Builder.WebApplicationBuilder
— строитель для веб-приложений и сервисов.
-
Посетитель
System.Linq.Expressions.ExpressionVisitor
— посетитель для деревьев выражений. Его реализация для динамических деревьев выражений —System.Linq.Expressions.DynamicExpressionVisitor
Интерфейсы для реализации паттернов:
Прототип представлен интерфейсом
System.ICloneable.
Для удобства также может быть использован защищенный методSystem.Object.MemberwiseClone,
который возвращает неглубокую копию объекта.Для реализации Итератора можно использовать два интерфейса:
System.Collections.IEnumerable
иSystem.Collections.IEnumerator.
Так же есть их обобщенные версии:System.Collections.Generic.IEnumerable<T>
System.Collections.Generic.IEnumerator<T>.
Наблюдатель представлен интерфейсами
System.IObservable<T>
иSystem.IObserver<T>
. Для любителей реактивных расширений можно вспомнить проSystem.Reactive.Subjects.Subject<T>.
Что не вошло?
Это был далеко не полный перечень, а всего лишь несколько примеров. Отмечу, что в данный пункт мы специально не включили паттерны GRASP (General Responsibility Assignment Software Pattern) — общие шаблоны распределения ответственностей [6]. Хотя слово pattern на момент разработки шаблонов GRASP стало уже популярным, GRASP это скорее принципы (распределения ответственности между классами), а не паттерны.
Библиотеки и фреймворки
Следующий нетривиальный механизм повторного использования по нашей классификации — это библиотеки. Про них обычно все понятно: мы их подключаем к своему приложению и вызываем нужные функции, либо переиспользуем целые библиотечные классы или модули.
В отличие от библиотек фреймворки работают несколько иначе: они определяют каркас, внутри которого мы можем встраивать своё расширение или поведение.
Фреймворки состоят из:
неизменяемой части, которая определяет общий подход (каркас, архитектуру);
изменяемой части, которая связана с конкретной реализацией приложения, его логикой.
Таким примером фреймворков может служить ASP.Net Core. Рассмотрим в нем три примера механизмов, которые содержат неизменяемую и изменяемую части.
Конвейер обработки запросов, в котором компоненты, так называемые middleware, завершают обработку запроса или передают запрос на обработку следующему компоненту. После обработки запроса последним компонентом данные запроса возвращаются к предыдущему компоненту по цепочке. Это то поведение, на которое мы повлиять не можем (неизменяемая часть). Однако мы можем сами определять, какие именно компоненты должны быть в данном конвейере (изменяемая часть).
Реализация шаблона MVC. В нем мы должны создавать контроллеры, имена которых содержат суффикс Controller, или базовый класс контроллера содержит суффикс, или к классу применяется атрибут [Controller]), а файлы представлений, как правило, объединяются в папки с именами соответствующими контроллерам (неизменяемая часть). При таких заданных правилах мы можем создавать произвольные контроллеры и произвольные представления (изменяемая часть).
Встроенный контейнер внедрения зависимостей, который позволяет внедрять зависимости через конструкторы классов и использовать три типа жизненных циклов (неизменяемая часть). При этом то, какие именно сервисы и куда внедрять, определяет сам разработчик (изменяемая часть).
Классификация фреймворков
Рассмотрим классификацию фреймворков, которая учитывает сразу три параметра:
По оси абсцисс указан параметр Диапазон применения, который показывает, какие приложения можно реализовать с помощью данного фреймворка.
По оси ордината отложено два параметра, один из них — Скорость разработки. Тут название говорит само за себя.
Второй параметра по оси ординат — это Управляемость и гибкость, он показывает, какие ограничения накладывает фреймворк.
Подход “No Frameworks” означает писать на чистом языке, без фреймворков. В таком случае мы получаем самый широкий диапазон применения и самую высокую гибкость, но самую низкую скорость разработки, так как придется писать много велосипедов. Конечно, если у вас задача написать эффективный алгоритм или разработать свой фреймворк, то данный подход вам может подойти.
Подход “Narrow-focused Frameworks” — это узкоспециализированные фреймворки, которые помогают писать нам корпоративные приложения. Сюда можно отнести как отдельные ORM фреймворки (EF, Hibernate), так и «фреймворки фреймворков» (Spring или ASP.NET Core). Данный подход обладает все еще высокой гибкостью и достаточно большим диапазоном применения.
Подход “Code Generators/Aggregators” позволяет ускорить разработку на стадии старта проекта. Такие генераторы выстраивают структуру приложений, основанных на узкоспециализированных фреймворках. Например, JHipster генерирует приложение на базе Spring с пользовательским интерфейсом на Angular.
Подход “Full-stack Frameworks” — фреймворки, которые предоставляют готовую инфраструктуру и позволяют создавать такие приложения как ERP, BPMS. Один из представителей такого класса систем это Jmix.
Подход “Low/No Code Frameworks” — это самый быстрый способ создания приложений, но и наименее гибкий, потому что в таких фреймворках вы не контролируете кодовую базу, а можете реализовывать только отдельные кусочки логики. Типичные представители данной группы это конструкторы сайтов, CMS системы (Wordpress, Drupal и другие).
Архитектуры
Архитектура — это способ решения проблем сложной системы путем абстракции реализации от интерфейса и разграничения полномочий между блоками код.
Иоганн Вольфганг Гете писал: «Архитектура — это онемевшая музыка». Действительно, музыка существует в динамике, и точно так же приложение является процессом. У него есть момент запуска, развития и завершения. Архитектура приложения — его срез в любой конкретный момент времени. В любой момент наше приложение как музыкальная тема должно быть четким, ясным, понятным, предсказуемым.
Часто именно работа с архитектурой – это первый шаг к долгосрочному сотрудничеству с заказчиком. Для команды это возможность показать экспертизу, обеспечить доверие и подключить специалистов к дальнейшей разработке. Я и мои коллеги в SimbirSoft занимаемся этими вопросами в Архитектурном комитете. Это группа экспертов, которые прорабатывают и проводят аудит IT-решений, помогают выбрать оптимальный технологический стек для каждого проекта. За несколько лет мы спроектировали уже более 70 крутых продуктов.
Зачем вообще нам нужна архитектура?
Это первый шаг в разработке, который рассказывает, не только как решить проблему, как устроена систем, может рассказать о поведении системы до фактического выполнения.
Помогает оценить потребность в ресурсах области решения.
Помогает обнаружить в системе области, подверженные риску на этапе архитектуры.
Отображает систему с точки зрения компонентов, поэтому если две системы имеют одинаковые компоненты, можно легко повторно использовать компонент для одной системы в другой.
Помогает улучшить качество системы: обеспечить сопровождение, надежность, эффективность, удобство использования.
В начале статьи мы упоминали понятия в сфере проектирования архитектуры, раскроем их:
Эталонная архитектура (reference architectures) — это шаблон обязательных компонентов и технических требований для их реализации. Обычно эталонные архитектуры предоставляют структуру для приложений в определенных областях и могут воплощать разные архитектурные стили, отображаемые на один или несколько архитектурных шаблонов.
Каталоги эталонных архитектур можно найти здесь:
Архитектурный стиль, или тип — это согласованный набор архитектурных ограничений, который устанавливает роли, функции элементов и допустимые взаимосвязи между ними в любой архитектуре, соответствующей этому стилю.
Архитектурные стили определяют способ организации компонентов системы таким образом, чтобы можно было построить целостную систему и удовлетворить требования заказчика. Можно сказать, что архитектурный стиль обладает наивысшим уровнем абстракции.
В таблице ниже приведен перечень архитектурных стилей, которые соответствуют определенным типам приложений:
Тип приложения |
Архитектурный стиль |
Разделяемая память |
Классная доска Дата-центрический Основанный на правилах |
Распределенная система |
Клиент-серверный Пространственно-ориентированная архитектура Одноранговая Архитектура без разделения ресурсов Посредник Передача репрезентативного состояния (REST) Сервис-ориентированный |
Обмен сообщениями |
Событийная Асинхронный обмен сообщениями Издатель-подписчик |
Структурные |
Основанный на компонентах Трубы и фильтры Монолит Многослойная |
Настраиваемые системы |
Плагины Основанный на рефлексиях Микроядерный |
Современные системы |
Архитектура распределенных вычисления Мультитенантный (мультиарендный) стиль Архитектура больших данных |
Далее рассмотрим более узкое понятие, чем архитектурный стиль.
Архитектурный шаблон — это общее и повторяющееся решение часто возникающей проблемы архитектуры приложений в пределах заданного контекста. Более научное определение: абстракция структуры программной системы, состоящая из компонентов и связей между ними.
Архитектурные шаблоны решают проблемы, связанные с архитектурными стилями. Например:
Сколько будет уровней в нашей клиент-серверной архитектур: 1-tier, 2-tier, 3-tier или N-tier?
Какие модули стоит выделить в нашей сервис-ориентированной архитектуре?
На элементы шаблона архитектуры влияют выбранные тактики проектирования, реализующие особенности проектирования и зависящие от них.
Архитектурная тактика — это проектное решение, которое влияет на достижение реакции атрибута качества. Тактика напрямую влияет на реакцию системы на некоторый стимул, придает переносимость одному дизайну, высокую производительность другому и интегрируемость третьему.
Проще говоря, архитектурные тактики применяются для достижения атрибута качества или не функционального требования.
Еще один важный паттерн, который можно переиспользовать — это шаблон развертывания.
Об автоматизации процесса развертывания
Вследствие роста требований к разработке и развитию гибких методологий командам появилась необходимость быстрее и с большей стабильностью выпускать изменения. Инфраструктура и код приложений стали частью единого процесса, которым надо управлять. Для автоматизации процесса развертывания стали использовать инфраструктуру как код (IaC). Развертывание включает в себя шаги, которые называют планом развертывания.
Шаблон развертывания — это несвязанный план развертывания, который определяет этапы выполнения, но не профили и системы. Шаблоны развертывания — это шаблоны, на основе которых можно создавать планы развертывания.
В качестве примеров:
Еще один пример:
В заключение темы архитектуры отметим интересный пример под названием Web Architecture 101, который содержит базовые концепции веб-архитектуры и может быть полезен для веб-разработчиков.
На рисунке представлены основные ее компоненты:
(1) DNS — Система доменных имен;
(2) Балансировщик нагрузки;
(3) Серверы веб-приложений;
(4) Сервера баз данных;
(5) Служба кэширования;
(6a) Очереди и (6b) сервера заданий;
(7) Служба полнотекстового поиска;
(8) Сервисы;
(9a) Data firehose — потоковый интерфейс для приема и обработки данных;
(10) Облачное хранилище (cloud storage);
(9c) Хранилище данных (data warehouse);
(11) CDN (Сеть доставки содержимого).
Итак, пора ответить на два ключевых вопроса: когда возможен code reuse и какие проблемы при этом возникают?
Когда стоит использовать code reuse?
Вы можете повторно использовать код, когда он:
легко расширяется и адаптируется под новое приложение;
при необходимости портируется на другое оборудование;
не содержит дефектов или проблем, которые влияют на надежность, сохранность и защищенность нового приложения;
позволяет переиспользовать свою часть, если такое требуется.
Сложности и проблемы, недостатки и преимущества
Организация и масштаб
По мере увеличения количества проектов и разработчиков становится все труднее повторно использовать программное обеспечение. При этом сложнее сообщать о подробностях и требованиях для переиспользования кода.
Администрирование
Еще увеличение количества проектов и разработчиков затрудняет обмен библиотеками. Каталогизация, архивирование и поиск повторно используемых ресурсов в глобальном масштабе — сложная задача. Такие платформы, как GitHub, могут упростить ее, но все равно создание удобного и масштабируемого репозитория требует времени и усилий.
Офисная политика и психология
Часто бизнес-подразделения стремятся к автономии и конкурируют между собой, и могут попытаться заблокировать повторное использование своих наработок соседями.
Отдельные разработчики могут рассматривать повторное использование кода как подавление их творческих способностей или неуверенность в их технических способностях. Это может привести к сопротивлению.
Дополнительное время
Для поддержки запланированного повторного использования командам нужно уделить дополнительное время на написание документации к своему коду, и протестировать его еще более тщательно, чем код для одного проекта.
Дополнительные ресурсы
Руководителям проектов требуется заранее выделить дополнительные ресурсы с самого начала работ — для разработки, рефакторинга, документирования и тестирования кода. Это вложение с долгосрочными выгодами.
Технические проблемы
Есть четыре основных характеристики программного обеспечения, которые влияют на повторное использование, и при недостаточных усилиях могут обернуться проблемами:
Безопасность. Безопасности можно добиться разными способами, например, ведением списков уязвимостей, внедрение автоматизированных средств проверки.
Надежность. Требуется обеспечить доступность, отказоустойчивость и возможность восстановления.
Эффективность производительности. Этого можно добиться за счет уменьшения времени отклика процессора, мониторинга использования памяти.
Поддерживаемость. Один из способов обеспечить удобство сопровождения кода — обеспечить его соответствие.
Исходя из вышесказанного, можно выделить такие плюсы и минусы:
➕
Сокращение общего времени разработки, так как программистам не нужно начинать все с нуля.
Поскольку разработчики могут использовать существующий код, организациям не нужны дополнительные ресурсы, то есть можно сократить затраты.
При code reuse мы получаем единый источник правды, который предоставляет достоверные, актуальные и пригодные к использованию данные.
Меньше кода — следовательно, меньше вероятность наличия в нем недостатков, проще понимать код.
Если по каким-то причинам нельзя переиспользовать код, то можно распознать его базовую функциональность, а затем создать новый код, который будет делать желаемое, но с рядом преимуществ (например, быстрее, потребляет меньше памяти, совместим с имеющимися элементами системы).
➖
Сторонняя зависимость может быть менее надежной, чем недавно написанный код, соответствующий стандартам безопасности.
Проблема шаблонных решений: готовая библиотека, фреймворк или архитектура могут быть менее эффективны, чем специализированное решение в конкретном случае.
Если при переиспользовании осуществляется доступ к API по всей системе, то это может снизить скорость работы приложения.
Модульная система может оказать негативное влияние на скорость работы системы.
Могут возникнуть проблемы с добавлением желаемых улучшений.
Могут возникнуть проблемы с лицензированием.
Заключение
Итак, когда мы говорим о переиспользовании, то можем затронуть как сам код, так и целую архитектуру. Между ними можно выстроить целую цепочку из паттернов, библиотек, фреймворков и так далее. Чтобы ориентироваться в данных категориях, поможет классификация с подробным обзором наиболее интересных механизмов повторного использования.
Данные механизмы, безусловно, полезны, но не всегда их можно применить, так как есть ограничения бизнеса, безопасности, бюджета, корпоративной культуры. Поэтому выбор и просчет рисков остается за вами.
Множество полезных ссылок для еще более глубокого погружения в тему:
Software Architectural Styles Andrew Midwinter, Mark Mullen, Kevin Wong, Matt Jones
Методика выбора шаблона программной архитектуры на основе анализа параметров качества системы
-
Эталонные решения (reference architectures)
Эталонные архитектуры бессерверных функций
Центр архитектурных решений AWS
-
Архитектурные шаблоны
Самые важные архитектурные шаблоны, которые нужно знать
Основные архитектурные шаблоны построения ПО
Краткий обзор 10 популярных архитектурных шаблонов приложений
-
Шаблоны развертывания
Как использовать шаблоны развертывания Azure Resource Manager (ARM) с Azure CLI
-
Тактики:
Архитектурные тактики шпаргалка
Системы для Больших Данных: конвергенция архитектур
Описание процесса создания архитектуры системы онлайн-трейдинга: подход аналитика хедж-фонда
Realizing and Refining Architectural. Tactics: Availability
Спасибо за внимание!
Полезные материалы о разработке и архитектуре мы также публикуем в наших соцсетях – ВКонтакте и Telegram.