Есть много людей, которые поделились своими версиями реализации вариантов использования, каждый из которых считает это либо улучшением, либо правильным способом создания варианта использования в Android.
Это отличные статьи с ценными идеями, и я настоятельно рекомендую прочитать их, чтобы понять различные точки зрения на реализацию вариантов использования.
Теперь вы можете задаться вопросом, зачем мне создавать свою собственную версию? Что ж, причина проста. У каждого свой уникальный опыт и подходы к решению проблем. Делясь своей версией, я не обесцениваю идеи других. Вместо этого я предлагаю свою точку зрения на то, как я вижу проблему и решение, которое лучше всего работает для меня. Вы можете найти в ней что-то родственное или извлечь из нее новые идеи, и в этом и заключается цель обмена — внести свой вклад в коллективные знания и поощрить различные точки зрения в сообществе разработчиков программного обеспечения.
Эта статья соответствует принципам серии Fluent and Fun Clean Architecture Series, которую я буду отстаивать. Если у вас еще не было возможности прочитать ее, не беспокойтесь — это не обязательное условие для понимания этой статьи. высокоуровневое объяснение того, почему я воссоздаю свой вариант использования.
Во-первых, что такое вариант использования?
В разработке программного обеспечения в целом вариант использования — это описание конкретного действия или взаимодействия, которое система или приложение выполняет для достижения определенной цели для субъекта (пользователя или другой системы). В нем описываются «шаги» и взаимодействия между различными компонентами, чтобы продемонстрировать, как конкретная функциональность используется в системе. Варианты использования часто используются для сбора «функциональных требований» и определения поведения системы с точки зрения ее пользователей.
В контексте чистой архитектуры термин «вариант использования» относится к конкретному архитектурному компоненту, представляющему бизнес-операцию или задачу, которую выполняет приложение. необходимо выполнить. Он является частью уровня предметной области и действует как посредник между уровнем представления (UI) и уровнем предметной области. Вариант использования отвечает за организацию потока данных и бизнес-логики для достижения желаемого результата.
Таким образом, общий вариант использования при разработке программного обеспечения описывает функциональность с точки зрения пользователя, тогда как вариант использования с чистой архитектуройпредставляет конкретную бизнес-операцию в уровень предметной области, придерживаясь принципов разделения задач и модульности.
Итак, что такое UseCase в «Свободной и увлекательной чистой архитектуре»?
В архитектуре Fluent and Fun Clean вариант использования служит более комплексной цели по сравнению с традиционными вариантами использования. Вместо того чтобы просто описывать функциональность с точки зрения пользователя, мы подходим к ней с точки зрения приложения при выполнении события или действие.
Это означает, что вариант использования не только описывает действия пользователя, но и представляет шаги, необходимые для достижения определенного результата при запуске события. Объединяяэти точки зрения, мы создаем выразительные и удобочитаемые варианты использования, соответствующие требованиям приложения.
Эта расширенная возможность позволяет нам разрабатывать гибкую систему с инкапсулированной бизнес-логикой, независимой от пользовательского интерфейса и доступа к данным. Это повышает модульность и удобство сопровождения, упрощая адаптацию и улучшение программного обеспечения по мере необходимости. Сосредоточив внимание на перспективе приложения и подробно описав шаги для обработки событий, мы более глубоко понимаем поведение системы, что приводит к более эффективному и адаптивная разработка программного обеспечения.
Как создать вариант использования в беглой и увлекательной чистой архитектуре?
Прежде чем мы углубимся в вариант использования Fluent and Fun Clean Architecture, давайте сначала разберемся, как реализовать его в Clean Architecture.
Для лучшего понимания рассмотрим простой пример варианта использования в приложении электронной коммерции:
Случай использования: Разместить заказ
Действие: Клиент
Описание. Этот вариант использования представляет собой процесс размещения клиентом заказа на продукт в приложении электронной коммерции.
Требования:
- Клиент должен авторизоваться.
- Корзина не пуста, чтобы можно было оформить заказ.
- Сумма денег в кошельке покупателя не должна быть меньше суммы заказанного товара.
- Если все три соблюдены, обновите товарный запас.
- Очистите корзину в приложении после завершения оформления заказа.
Чтобы реализовать это в чистой архитектуре, вы обычно следуете структуре кода, подобной той, что показана ниже.
class PlaceOrderUseCase( private val userRepository: UserRepository, private val productRepository: ProductRepository ) { operator fun invoke(order: Order) { if (userRepository.isLoggedIn()) { val cart = userRepository.getCart() if (cart.isNotEmpty()) { if (userRepository.hasEnoughFunds(order.getTotalPrice())) { productRepository.updateProductStock(order) userRepository.clearCart() } else { throw InsufficientFundsException( "Not enough funds in the wallet." ) } } else { throw EmptyCartException("The cart is empty.") } } else { throw NotLoggedInException("User is not logged in.") } } }
Теперь давайте разберем его шаг за шагом, чтобы создать вариант использования:
- Создайте класс с именем, состоящим из глагола в настоящем времени + существительного/что (необязательно) + UseCase.
- Определите необходимые параметры, которые могут быть репозиториями или другими вариантами использования, в зависимости от требований вашего приложения.
- В Kotlin вы можете сделать экземпляры класса Use Case вызываемыми как функции, определив функцию
invoke()
с модификаторомoperator
.
Для получения дополнительной информации вы можете обратиться к официальной документации разработчиков Android, где вы можете узнать, как они определяют свой доменный уровень и варианты использования, что имеет сходство с нашим подходом выше.
В контексте Fluent and Fun Clean Architecture цель состоит в том, чтобы добиться аналогичной реализации, как описано ниже.
OrderUseCase.kt fun OrderRepository.placeOrder(order: Order) { whenUserLoggedIn { whenCartNotEmpty { withSufficientFunds { updateProductStock(order) clearCart() } } } }
Основная цель состоит в том, чтобы предоставить четкое и краткое описание необходимых шагов при размещении заказа. В следующем фрагменте кода вы заметите, что он читается как естественный язык, что делает вариант использования понятным. Перед размещением заказа необходимо пройти несколько проверок.
Вот разбивка реализации:
- Вместо использования класса мы создали файл с именем «OrderUseCase».
- Имя файла следует соглашению существительное/что (необязательно) + UseCase.
- Класс не задействован; вместо этого мы использовали функцию расширения верхнего уровня или обычную функцию верхнего уровня.
- Сама функция представляет вариант использования.
- Имя функции служит основным вариантом использования для вызова из уровня представления.
Почему я предпочитаю такой вариант использования?
- Читаемость и выразительность. Благодаря использованию цепочки вызовов функций с осмысленными именами (
whenUserLoggedIn
,whenCartNotEmpty
,withSufficientFunds
) код становится более читабельным и выразительным. Каждый шаг процесса четко очерчен, что облегчает понимание потока варианта использования. - Упрощенный поток управления. Цепочка вызовов функций соответствует естественному потоку условий, которые необходимо выполнить для размещения заказа. Это упрощает поток управления и делает логику более простой.
- Модульность: код разделяет задачи на разные функции (
whenUserLoggedIn
,whenCartNotEmpty
,withSufficientFunds
), заставляя каждую функцию обрабатывать определенную проверку или условие. Это способствует модульности и упрощает изменение или добавление новых проверок, не влияя на весь вариант использования. - Краткость: в коде нет необходимости в отдельном классе прецедентов с шаблонным кодом. Он сжимает логику в краткую и сфокусированную функцию расширения.
- Свободный интерфейс. Использование ключевого слова
when
в именах функций (whenUserLoggedIn
,whenCartNotEmpty
) придает коду плавный стиль интерфейса, повышая удобочитаемость и делая его более похожим на естественный язык. - Ясность намерений. Разбивка логики вариантов использования на отдельные функции позволяет разработчику четко выражать свои намерения на каждом этапе процесса. Становится очевидным, что представляет собой каждое условие в контексте размещения заказа.
В целом, мы предпочитаем этот подход, потому что он предлагает более лаконичный, выразительный и модульный способ определения логики варианта использования. Это сокращает шаблонный код и помогает разработчикам сосредоточиться на конкретных шагах и условиях, необходимых для размещения заказа. Кроме того, его можно рассматривать как пример того, как концепции функционального программирования, такие как цепочки и плавные интерфейсы, могут применяться для разработки более читаемого и выразительного кода.
Почему вам не нужен класс для реализации варианта использования?
Это правильный вопрос. Прежде чем дать ответ, давайте начнем с определения того, что такое класс в программировании.
- Классы используются для определения чертежей длясоздания объектов. Вы можете создать несколько экземпляров (объектов) класса с различным состоянием и поведение.
- Классы могут иметь свойства, функции-члены и конструкторы, что позволяет создавать экземпляры с различными инициализациями и состояниями.
- Если вам нужно создать несколько экземпляров концепции(например, нескольких пользователей, продуктов и т. д.), вы обычно используете класс.
Что такое состояние и поведение в классе?
- Состояние представляет текущие данные или свойства каждого объекта. Он представлен переменными экземпляра (полями) внутри класса, и каждый объект, созданный из класса, имеет свой собственный набор этих переменных. Например, в классе Car атрибуты состояния могут включать цвет, марку, модель, год выпуска и уровень топлива, причем каждый экземпляр имеет свои определенные значения.
class Car(private val color: String, private val make: String, private val model: String, private val year: Int) { private var fuelLevel: Double = 0.0 }
- Поведение в классе определяет действия или операции, которые могут выполнять объекты. Он представлен методами внутри класса. Эти методы определяют, как объекты взаимодействуют с другими и внешним миром. Например, в классе Car у нас могут быть такие методы, как start(), Accel(), Brake(),иrefuel() для представления различных вариантов поведения объекта автомобиля в зависимости от его состояния.
class Car { private var fuelLevel: Double = 0.0 // Behavior (methods) fun start() { println("Car has started.") } fun accelerate() { println("Car is accelerating.") } fun brake() { println("Car is braking.") } fun refuel(amount: Double) { fuelLevel += amount println("Car has been refueled with $amount gallons.") } }
Отвечая на вопрос:
Как мы видим, классы действительно мощная концепция в программировании. Однако в некоторых случаях использования в Kotlin мы можем не полностью использовать возможности класса, если используем его только для вызова одного поведения или функции.
В таких сценариях выбор функции вместо класса обеспечивает более простой и лаконичный подход. Функция позволяет нам напрямую определить логику варианта использования без введения ненужного синтаксиса и структуры, связанных с классами. Он также согласуется с принципами функционального программирования, побуждая нас разрабатывать сценарии использования в виде чистых функций, которые предсказуемы, тестируемы и менее подвержены побочным эффектам.
Чтобы проиллюстрировать это положение, давайте рассмотрим простую аналогию. Воспринимайте автомобиль как класс и прогулку как функцию. Если вам нужно добраться только до места, которое находится в двух-трех минутах езды, использование мощного автомобиля с музыкой, GPS и кондиционером может оказаться излишним. В этом случае у вас есть возможность идти пешком, что является более простым и прямым подходом.
Точно так же представьте Телефон как класс и разговор как функцию. Если вы хотите что-то сказать кому-то в той же комнате, использование мощного телефона с различными функциями может не понадобиться. Вы можете поговорить с этим человеком напрямую, что является более простым способом достижения вашей цели.
Ключевым выводом здесь является то, что существуют разные способы выполнения задач, и иногда функциональный подход может быть более подходящим и эффективным. Рассматривая сначала функциональный подход, мы можем сосредоточиться на простоте, удобочитаемости и выразительности кода. Очень важно выбрать правильный инструмент для работы и использовать соответствующие концепции в разработке программного обеспечения. Использование концепций функционального программирования в Kotlin может привести к более чистому и удобному в сопровождении коду, что в конечном итоге улучшит процесс разработки.
Заключение
В заключение, в контексте Fluent and Fun Clean Architecture мы изучили другой подход к реализации вариантов использования, который предлагает преимущества с точки зрения удобочитаемости, выразительности и модульности. Используя функции расширения верхнего уровня или обычные функции верхнего уровня, мы можем создавать варианты использования, которые читаются как естественный язык, делая логику мгновенно понятной и легкой для понимания.
Отдавая предпочтение функциям, а не классам для вариантов использования, мы упрощаем поток управления и избегаем ненужного стандартного кода, делая кодовую базу более лаконичной и целенаправленной. Этот функциональный подход согласуется с принципами Fluent and Fun Clean Architecture, продвигая более выразительную и адаптируемую кодовую базу.
Однако важно отметить, что выбор между использованием классов или функций для вариантов использования зависит от конкретных требований и сложности приложения. Для более обширных вариантов использования, включающих управление состоянием и несколько экземпляров, классы по-прежнему могут быть ценным выбором.
В этой статье лишь поверхностно рассмотрены различные возможности воссоздания вариантов использования. В будущих статьях мы рассмотрим дополнительные методы и предоставим больше примеров творческих реализаций вариантов использования.
Следите за новостями и примерами того, как Fluent and Fun Clean Architecture может изменить наш подход к сценариям использования и разработке программного обеспечения в целом.