[Разработка веб-сайтов, PHP, Программирование, Go] Strategy Design Pattern
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Всем привет, друзья. Меня зовут Alex, я профессиональный разработчик и создатель программных продуктов в веб индустрии. Много лет изучаю языки, делюсь опытом с другими. Сегодня хочу с вами поговорить про шаблон проектирования Стратегия (Strategy). Постараюсь донести до вас принципы и суть шаблона без воды, и покажу как его применять на практике. В чем суть?Design patter Strategy или шаблон проектирования Стратегия относится к поведенческим шаблонам проектирования. Его задача - выделить схожие алгоритмы, решающие конкретную задачу. Реализация алгоритмов выносится в отдельные классы и предоставляется возможность выбирать алгоритмы во время выполнения программы.Шаблон дает возможность в процессе выполнения выбрать стратегию (алгоритм, инструмент, подход) решения задачи. В чем проблема?Рассмотрим задачи, при решении которых можно применять такой подход. Представьте, что перед вами стоит задача написать веб-портал по поиску недвижимости. MVP (Minimum Viable Product) или минимально работающий продукт был спроектирован и приоритизирован вашей командой Product Manager’ов и на портале должен появиться функционал для покупателей квартир. То есть целевые пользователи вашего продукта в первую очередь - это те, кто ищет себе новое жилье для покупки. Одной из самых востребованных функций должна быть возможность:
- Выбрать область на карте, где покупатель желает приобрести жилье
- И указать ценовой диапазон цен на квартиры для фильтрации.
Первая версия вашего портала отлично справилась с поставленной задачей и пользователи могли без проблем искать, сужая свой поиск квартир по ценовом диапазону и выбранной географической области на карте. Ну и конечно вы хорошо постарались, как разработчик и все правильно сделали на ваш взгляд с точки зрения архитектуры кода, реализовали классы, которые ищет квартиры на продажу в вашей базе. Но тут приходят к вам Product Manager'ы и говорят, что нужно добавить возможность искать и отображать недвижимость, которая сдается в аренду. У нас появляется еще один тип пользователя - арендаторы. Для арендаторов не так важно показывать фильтры по цене, им важно состояние квартиры, поэтому нужно отображать фотографии арендуемых квартир. Следующей версией вашего продукта была значительная доработку текущей архитектуры и добавление нового функционала, чтобы можно было в зависимости от роли пользователя искать разные типы недвижимости и отображать разные элементы интерфейса - для покупателей фильтры по цене и географическое расположение, для арендаторов фотографии квартир. Конечно на этом все не закончилось. В ближайших планах добавить функционал работы юридических лиц, функционал оплаты и бронирования квартир сразу на сайте. Дальше-больше - добавить возможность просматривать историю недвижимости, запрашивать пакет документов для сделки и связь с владельцами, оформление кредита и так далее. Если функционал поиска и фильтрации с квартирами на продажу было довольно легко реализовать, то любые новые изменения вызывали много вопросов и головную боль по архитектуре. Пришлось очень многое менять в коде. Вы понимали, что любое изменение алгоритмов выдачи нужных квартир и элементов для отображения затрагивает основные базовые классы, в которых реализован весь функционал фильтрации. Основной функционал поиска квартир изначально был реализован в одном классе, при добавлении нового функционала этот класс разрастался, вы добавляли новые условия, новые ветвления, новые методы и функции. Изменение такого класса, даже в случае исправление багов, сильно повышает риск сделать новые ошибки. Над данным функционалом работала целая команда разработчиков, любые изменения в итоге проходили долгую обкатку и тестирование, а изменения, добавляемые другими программистами в базовые классы, создавала новые проблемы и конфликты, релизы затягивались. Вы столкнулись со следующими проблемами:
- Основной алгоритм поиска квартир был реализован в одном супер-классе
- Алгоритм выбора и отображения элементов интерфейса был реализован в одном супер-классе
- Изменения в этих классах, сделанные разными программистами, приводили к конфликтам и необходимости регрессивного тестирования
- Релизы продукта затягивались, время на разработку нового функционала увеличилась в несколько раз
- Больше времени стало уходить на разработку, тестирование, появилось множество багов.
Супер-класс с единым методом реализации алгоритма.Какое решение?В данном примере мы имеем несколько алгоритмов для одной функции:
- Поиск квартир с продажей
- Поиск квартир в аренду
- Отображение или нет различных наборов фильтров
- Отображение различных элементов интерфейса - фотографии, кнопки бронирования, кнопки обратной связи и т.д.
Шаблон проектирования Стратегия - решает такую задачу. Он предлагает выделить семейство похожих алгоритмов, вынести их в отдельные классы. Это позволит без проблем изменять нужный алгоритм, расширять его, сводя к минимум конфликты разработки, зависимости от других классов и функционала. Вместо того, чтобы реализовывать алгоритм в едином классе, наш класс будет работать с объектами классов-стратегиями через объект-контекста и в нужным момент делегировать работу нужному объекту. Для смены алгоритма достаточно в нужным момент подставить в контекст нужный объект-стратегию. Чтобы работа нашего класса была одинаковой для разного поведения, у объектов-стратегии должен быть общий интерфейс. Используя такой интерфейс вы делаете независимым наш класс-контекста от классов-стратегий.
Диаграмма классов шаблона StrategyВозвращаясь к нашему примеру с порталом по поиску недвижимости, мы должны вынести алгоритмы поиска недвижимости на продажу и аренду в отдельные классы-стратегии, где реализовать конкретные алгоритмы по поиску разных типов объектов. Аналогичное можно проделать и с классами работы с элементами интерфейса для различных видов пользователей. В классах-стратегиях, реализующих поиск объектов недвижимости, будет определен только один метод doSearch(filters), принимающий в качестве аргумента фильтры, по которым будет совершен поиск конкретных объектов с использованием конкретного алгоритма. Несмотря на то, что каждый класс-стратегия реализует поиск по своему алгоритму, с применением необходимых фильтров (продажа, аренда, загородный дом, жилая, не жилая и т.д.), не исключено, кстати, что они будут работать с разными базами - все это для веб-интерфейса, который отображает список найденных объектов, не имеет никакого значения. После того, как пользователь выбрал интересующий его тип недвижимости в фильтрах на сайте, будет происходить запрос в контроллер на backend, с экшеном получения данных по входящим фильтрам и типам пользователя. Задача контроллера определить класс-стратегию и запросить у класса-контекста данные для отображения, передав ему известный набор фильтров. Класс-контекст в этой схеме - это класс, которые реализует метод поиска квартир по заданным фильтрам. На диаграмме классов выше мы видим, что класс контекста определяет метод getData, и принимает аргументы filters. У него должен быть конструктор, принимающий активный в данный момент объект-стратегии и сеттер setStrategy, устанавливающий активную стратегию. Такой метод пригодится для случая, когда пользователь меняет тип искомого объекта, например, он ищет недвижимость на продажу и хочет снять квартиру. Пример реализацииНиже рассмотрим пример, как решается описанная задача на языке GOlang. Первое что сделаем - определим интерфейс с методом doSearch:
Strategy.goДанный метод определяет общее поведение для конкретных алгоритмов, реализующих разные стратегии. Метод может принимать различные аргументы, позволяющие реализовать ветвления в ваших алгоритмах. В примера я передаю пользовательские фильтры с типом Map.Для реализации конкретных алгоритмов создаем два файла. В каждом файле определяется свой определяемый тип с базовым типом struct, реализующие интерфейс Strategy. Соответственно, в методы, определяемые интерфейсом для каждого алгоритма, будут передаваться пользовательские фильтры. Реализации выглядит следующим образом:
FirstAlgorithm.go
SecondAlgorithm.goПосмотрим на нашу диаграмму классов. Нам осталось реализовать класс-контекста и клиентский код вызова конкретных алгоритмов в нужным момент. Как это сделать? Для создания слоя класса-контекста реализуем исходник, реализующий:
- определяемый тип в базовым типом struct
- функцию initStrategy, инициализирующий стратегию по-умолчанию и пользовательские фильтры
- метод типа struct setStrategy, устанавливающий активную стратегию
- и функция getData, вызывающий конкретную стратегию и возвращаемый данные для показа пользователю.
Context.goПоследний шаг - посмотрим на клиентский код. Сначала инициализируется стратегия по-умолчанию, получаем данные из этой стратегии. Затем выставляем новую активную стратегию и повторно вызываем функцию получения данных getData. Как видим, каждый раз вызывается одна и та же функция файла-контекста (или класса-контекста в диаграмме классов) для получения данных рендеринга, отображаемых в дальнейшем пользователю. Для простоты я вывожу отладочную информацию в консоль, чтобы убедиться, что работают разные алгоритмы при вызовах. Вот код:
Client.goВот вывод такого подхода:First implements strategy map[role:1] Second implements strategy map[role:2] Как видите, мы можем управлять вызовом разных алгоритмов в зависимости от контекста и пользовательских фильтров. Алгоритмы могут создавать ветвления в зависимости от входных фильтров и других параметров, переданных из клиентского кода в методы, реализующие конкретные алгоритмы. Вот такой интересный пример. Объектно-ориентированный подход можно посмотреть. например, в этом курсе. Там показан пример на PHP. Когда применять?Напоследок поговорим когда применяется шаблон Strategy?
- У вас есть множество похожих реализаций отличающихся незначительным поведением. Можно вынести отличающее поведение в классы-стратегии, а повторяющий код свести к единому классу-контекста.
- Ваш алгоритм реализован в супер-классе с множественными условными операторами. Выделите блоки условных операторов в отдельные классы-стратегии, а управление вызовов нужных доверьте классу-контекста.
- Конкретные стратегии позволяют инкапсулировать алгоритмы в своих конкретных классах. Используйте этот подход для снижения зависимостей от других классов.
- В зависимости от ситуации вы можете менять стратегию выполнения задачи в процессе выполнения программы. Например, в зависимости от скорости интернета использовать разные стратегии-поведения, возвращающие разный набор данных для отображения страницы.
Подведем итогДрузья, мы познакомились с поведенческим шаблоном проектирования Strategy. Шаблон используется для выделения схожих алгоритмов, решающих конкретную задачу. Посмотрели с вами реализацию на языке GOlang, ознакомились в возможностями подхода и разобрали когда его лучше применять.Рад был с вами пообщаться, [url=https://www.facebook.com/groups/201365194945690 ]Alex Versus[/url]. Успехов!
===========
Источник:
habr.com
===========
Похожие новости:
- [Программирование, Разработка под iOS, Objective C, Swift] Связанные не явные выражения в Swift 5.4 (перевод)
- [Информационная безопасность, JavaScript, Google Chrome, Браузеры, Microsoft Edge] Уязвимость нулевого дня Google Chrome и Microsoft Edge опубликовали в Twitter
- [Python, Программирование] Шифрование сообщений в RYTHON. От простого к сложному. Шифр Цезаря
- [Разработка веб-сайтов, ReactJS] React Server-Side Rendering (SSR) — руководство новичка (перевод)
- [Программирование, Git, GitHub] Коммиты — это снимки, а не различия (перевод)
- [Программирование, C#] Лучшие практики обработки исключений в C# (перевод)
- [JavaScript, Программирование, Клиентская оптимизация, Математика] Кэширование данных увеличивает скорость даже в неожиданных случаях
- [PHP, API, Dart, Flutter] Ugly API
- [Open source, Программирование, Dart, Flutter] Повышаем качество кода с Dart Code Metrics
- [Хостинг, Разработка веб-сайтов, Читальный зал, История IT] Веб на заре Рунета. Как создавали и где хостили сайты в 90-е
Теги для поиска: #_razrabotka_vebsajtov (Разработка веб-сайтов), #_php, #_programmirovanie (Программирование), #_go, #_go, #_golang, #_php, #_design_patterns, #_design_pattern, #_shablony_proektirovanija (шаблоны проектирования), #_strategy_pattern, #_strategija (стратегия), #_arhitektura_prilozhenij (архитектура приложений), #_arhitektura (архитектура), #_razrabotka_vebsajtov (
Разработка веб-сайтов
), #_php, #_programmirovanie (
Программирование
), #_go
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 12:31
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Всем привет, друзья. Меня зовут Alex, я профессиональный разработчик и создатель программных продуктов в веб индустрии. Много лет изучаю языки, делюсь опытом с другими. Сегодня хочу с вами поговорить про шаблон проектирования Стратегия (Strategy). Постараюсь донести до вас принципы и суть шаблона без воды, и покажу как его применять на практике. В чем суть?Design patter Strategy или шаблон проектирования Стратегия относится к поведенческим шаблонам проектирования. Его задача - выделить схожие алгоритмы, решающие конкретную задачу. Реализация алгоритмов выносится в отдельные классы и предоставляется возможность выбирать алгоритмы во время выполнения программы.Шаблон дает возможность в процессе выполнения выбрать стратегию (алгоритм, инструмент, подход) решения задачи. В чем проблема?Рассмотрим задачи, при решении которых можно применять такой подход. Представьте, что перед вами стоит задача написать веб-портал по поиску недвижимости. MVP (Minimum Viable Product) или минимально работающий продукт был спроектирован и приоритизирован вашей командой Product Manager’ов и на портале должен появиться функционал для покупателей квартир. То есть целевые пользователи вашего продукта в первую очередь - это те, кто ищет себе новое жилье для покупки. Одной из самых востребованных функций должна быть возможность:
Супер-класс с единым методом реализации алгоритма.Какое решение?В данном примере мы имеем несколько алгоритмов для одной функции:
Диаграмма классов шаблона StrategyВозвращаясь к нашему примеру с порталом по поиску недвижимости, мы должны вынести алгоритмы поиска недвижимости на продажу и аренду в отдельные классы-стратегии, где реализовать конкретные алгоритмы по поиску разных типов объектов. Аналогичное можно проделать и с классами работы с элементами интерфейса для различных видов пользователей. В классах-стратегиях, реализующих поиск объектов недвижимости, будет определен только один метод doSearch(filters), принимающий в качестве аргумента фильтры, по которым будет совершен поиск конкретных объектов с использованием конкретного алгоритма. Несмотря на то, что каждый класс-стратегия реализует поиск по своему алгоритму, с применением необходимых фильтров (продажа, аренда, загородный дом, жилая, не жилая и т.д.), не исключено, кстати, что они будут работать с разными базами - все это для веб-интерфейса, который отображает список найденных объектов, не имеет никакого значения. После того, как пользователь выбрал интересующий его тип недвижимости в фильтрах на сайте, будет происходить запрос в контроллер на backend, с экшеном получения данных по входящим фильтрам и типам пользователя. Задача контроллера определить класс-стратегию и запросить у класса-контекста данные для отображения, передав ему известный набор фильтров. Класс-контекст в этой схеме - это класс, которые реализует метод поиска квартир по заданным фильтрам. На диаграмме классов выше мы видим, что класс контекста определяет метод getData, и принимает аргументы filters. У него должен быть конструктор, принимающий активный в данный момент объект-стратегии и сеттер setStrategy, устанавливающий активную стратегию. Такой метод пригодится для случая, когда пользователь меняет тип искомого объекта, например, он ищет недвижимость на продажу и хочет снять квартиру. Пример реализацииНиже рассмотрим пример, как решается описанная задача на языке GOlang. Первое что сделаем - определим интерфейс с методом doSearch: Strategy.goДанный метод определяет общее поведение для конкретных алгоритмов, реализующих разные стратегии. Метод может принимать различные аргументы, позволяющие реализовать ветвления в ваших алгоритмах. В примера я передаю пользовательские фильтры с типом Map.Для реализации конкретных алгоритмов создаем два файла. В каждом файле определяется свой определяемый тип с базовым типом struct, реализующие интерфейс Strategy. Соответственно, в методы, определяемые интерфейсом для каждого алгоритма, будут передаваться пользовательские фильтры. Реализации выглядит следующим образом: FirstAlgorithm.go SecondAlgorithm.goПосмотрим на нашу диаграмму классов. Нам осталось реализовать класс-контекста и клиентский код вызова конкретных алгоритмов в нужным момент. Как это сделать? Для создания слоя класса-контекста реализуем исходник, реализующий:
Context.goПоследний шаг - посмотрим на клиентский код. Сначала инициализируется стратегия по-умолчанию, получаем данные из этой стратегии. Затем выставляем новую активную стратегию и повторно вызываем функцию получения данных getData. Как видим, каждый раз вызывается одна и та же функция файла-контекста (или класса-контекста в диаграмме классов) для получения данных рендеринга, отображаемых в дальнейшем пользователю. Для простоты я вывожу отладочную информацию в консоль, чтобы убедиться, что работают разные алгоритмы при вызовах. Вот код: Client.goВот вывод такого подхода:First implements strategy map[role:1] Second implements strategy map[role:2] Как видите, мы можем управлять вызовом разных алгоритмов в зависимости от контекста и пользовательских фильтров. Алгоритмы могут создавать ветвления в зависимости от входных фильтров и других параметров, переданных из клиентского кода в методы, реализующие конкретные алгоритмы. Вот такой интересный пример. Объектно-ориентированный подход можно посмотреть. например, в этом курсе. Там показан пример на PHP. Когда применять?Напоследок поговорим когда применяется шаблон Strategy?
=========== Источник: habr.com =========== Похожие новости:
Разработка веб-сайтов ), #_php, #_programmirovanie ( Программирование ), #_go |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 12:31
Часовой пояс: UTC + 5