0 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

JAVA-приложения: ломая барьеры ОС

Блог только про Java

Учимся программировать на Java с нуля

Главное меню

Класс CyclicBarrier, примеры реализации кода в Java

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

Для этой цели в параллельном API предоставляется класс CyclicBarrier. Он позволяет определить объект синхронизации, который приостанавливается до тех пор, пока определенное количество потоков исполнения не достигнет некоторой барьерной точки.

В классе CyclicBarrier определены следующие конструкторы:

где параметр количество_потоков определяет число потоков, которые должны достигнуть некоторого барьера до того, как их исполнение будет продолжено.

Во второй форме конструктора параметр действие определяет поток, который будет исполняться по достижении барьера.

Общая процедура применения класса CyclicBarrier следующая. Прежде всего нужно создать объект класса CyclicBarrier, указав количество ожидающих потоков исполнения.

А когда каждый поток исполнения достигнет барьера, следует вызвать метод await() для данного объекта. В итоге исполнение потока будет приостановлено до тех пор, пока метод await() не будет вызван во всех осталь­ных потоках исполнения.

Как только указанное количество потоков исполнения достигнет барьера, произойдет возврат из метода await(), и выполнение будет возобновлено. А если дополнительно указать какое-нибудь действие, то будет выполнен соответствующий поток.

У метода await() имеются следующие общие формы:

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

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

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

Пользуюсь случаем хочу спросить аудиторию про один плагин WordPress. Дело в том, что желаю делать рассылку с помощью плагина CodeCanyon Mailster. Есть ли у вас опыт работы с ним и стоит ли игра свеч?

В приведенном ниже примере программы демонстрируется применение клас­са CyclicBarrier. Эта программа ожидает до тех пор, пока все три потока достиг­нут барьерной точки. Как только это произойдет, будет выполнен поток, опреде­ляемый действием типа BarAction.

Компьютерная программа Переводчик Google приложение для Android — отзыв

Приложение, ломающее языковой барьер

Google Переводчик от Google LLC — это одно из приложений которое я устанавливаю первым, переходит из телефона в телефон.

Доступно 5 режимов ввода переводимого текста

  1. С помощью клавиатуры
  2. Фото текста

Доступно 103 языка + определяет язык автоматически, но если пользоваться режимами перевода поддерживаемых языков становится меньше:

Перевод офлайн. Переводите на 59 языков и обратно без подключения к Интернету.

Быстрый перевод камерой. Мгновенный перевод любых надписей с 38 языков.

Режим камеры. Чтобы перевести текст, достаточно сфотографировать его. Поддерживаются 37 языков.

Режим разговора. Автоматический перевод речи с 32 языков и обратно.

Рукописный ввод. Напишите текст от руки и переведите его на любой из 93 языков.

Можно переводить SMS-сообщения,

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

JAVA-приложения: ломая барьеры ОС

Узнайте, какие инструменты ВКонтакте помогут сохранить привычный ритм жизни, когда нужно оставаться дома.Посмотреть

Центр социальных технологий «Ломая барьеры»

Информация

Описание: Деятельность Центра социальных технолоий «Ломая барьеры» направлена на улучшение качества жизни детей с инвалидностью и преодоление общественных стереотипов отношения к инвалидам

Объединение и помощь в объединении усилий и ресурсов общества, бизнеса и власти для решения социальных проблем и развития инклюзии. Сайт: http://ломаябарьеры.рф/

Другое

Действия

Не ограничивайте себя во время самоизоляции!

Узнайте, какие инструменты ВКонтакте помогут сохранить привычный ритм жизни, когда нужно оставаться дома.Посмотреть

248 записей

Центр социальных технологий «Ломая барьеры» совместно с экспертами и специалистами Центра на постоянной основе проводит полезные прямые эфиры.

Темы эфиров разнообразны: от занятий арт-терапией до советов различных специалистов. Показать полностью…
Во время прямых эфиров можно получить онлайн-консультации.

Прямые эфиры проводят:
— Лена Калашникова-Сайфуллина учитель-логопед;
— Светлана Шишкина учитель;
— Регина Азанова практикующий психолог;
— Дилара Валеева педагог-психолог высшей категории, семейный психолог, системный психолог, песочный терапевт, сказкотерапевт;
— Аля Хабирова директор Центра «Ломая барьеры»

Расписание прямых эфиров размещено в группе https://vk.com/socialrb02.

Записи всех прямых эфиров можно просмотреть в разделе «Видео»

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

Прямые эфиры продиктованы сложившимися условиями самоизоляции.

Многопоточное программирование в Java 8. Часть вторая. Синхронизация доступа к изменяемым объектам

Многопоточное программирование в Java 8. Часть вторая. Синхронизация доступа к изменяемым объектам

    Переводы , 21 сентября 2016 в 18:56

Добро пожаловать во вторую часть руководства по параллельному программированию в Java 8. В предыдущей части мы рассматривали, как выполнять код параллельно с помощью потоков, задач и сервисов исполнителей. Сегодня мы разберём, как синхронизировать доступ к изменяемым объектам с помощью ключевого слова synchronized , блокировок и семафоров.

Большинство принципов, которые описаны в этой статье, справедливы и для более старых версий Java. Тем не менее, я не задавался проблемами совместимости, и примеры содержат как лямбды, так и новые возможности многопоточности. Если вы не очень хорошо знакомы с лямбда-выражениями, то вам стоит сперва прочитать мой туториал по Java 8.

Для простоты примеров я использую в них два метода-помощника: sleep(секунды) и stop(сервис-исполнитель) . Их реализации я выложил на GitHub, если кому-то интересно.

Синхронизация

Мы уже узнали, как выполнять код параллельно с помощью сервисов-исполнителя (ExecutorService). Во время написания многопоточной программы нужно уделять особое внимание работе с общими для потоков изменяемыми объектами. Давайте представим, что мы хотим увеличить такую переменную на единицу.

Мы создаём поле count и метод increment() , который увеличивает count на единицу:

Если мы будем вызывать этот метод одновременно из двух потоков, у нас возникнут серьёзные проблемы:

Вместо ожидаемого постоянного результата 10000 мы будем каждый раз получать разные числа. Причина этого — использование изменяемой переменной несколькими потоками без синхронизации, что вызывает состояние гонки (race condition).

15 июня – 9 июля , онлайн, от 13 000 до 52 000 ₽

Увеличение числа на единицу происходит в три шага: (1) считать значение переменной, (2) увеличить это значение на единицу и (3) записать назад новое значение. Если два потока будут одновременно выполнять эти шаги, то вполне вероятно, что они могут выполнить первый шаг одновременно, считав одно и то же значение. Затем они запишут в переменную одно и то же значение, и вместо увеличения на 2 получится увеличение на единицу. Поэтому конечное значение и получается меньше ожидаемого.

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

Тогда, после выполнения метода 10000 раз, мы всегда будем получать значение 10000, и никакой гонки состояний возникать не будет:

Это ключевое слово можно применять не только к методам, но и к отдельным их блокам:

Под капотом Java использует так называемый монитор (monitor lock, intrinsic lock) для обеспечения синхронизации. Этот монитор привязан к объекту, поэтому синхронизированные методы используют один и тот же монитор соответствующего объекта. Все неявные мониторы устроены реентерабельно (reentrant), т.е. таким образом, что поток может без проблем вызывать блокировку одного и того же объекта, исключая взаимную блокировку (например, когда синхронизированный метод вызывает другой синхронизированный метод на том же объекте).

Блокировки

Кроме использования блокировок неявно (с помощью ключевого слова synchronized ), Concrurrency API предлагает много способов их явного использования, определённых интерфейсом Lock . С помощью явных блокировок можно настроить работу программы гораздо тоньше и тем самым сделать её эффективнее.

Стандартный JDK предоставляет множество реализаций Lock , которые мы сейчас и рассмотрим.

ReentrantLock

Класс ReentrantLock реализует то же поведение, что и обычные неявные блокировки. Давайте попробуем переписать наш пример с увеличением на единицу с помощью него:

Блокировка осуществляется с помощью метода lock() , а освобождаются ресурсы помощью метода unlock() . Очень важно оборачивать код в try<>finally<> , чтобы ресурсы освободились даже в случае выброса исключения. Код, представленный выше, так же потокобезопасен, как и его аналог с synchronized . Если один поток вызвал lock() , и другой поток пытается получить доступ к методу до вызова unlock() , то второй поток будет простаивать до тех пор, пока метод не освободится. Только один поток может удерживать блокировку в каждый момент времени.

Для большего контроля явные блокировки поддерживают множество специальных методов:

Пока первый поток удерживает блокировку, второй выведет следующую информацию:

Locked: true
Held by me: false
Lock acquired: false

Метод tryLock() , в отличие от обычного lock() не останавливает текущий поток в случае, если ресурс уже занят. Он возвращает булевый результат, который стоит проверить перед тем, как пытаться производить какие-то действия с общими объектами (истина обозначает, что контроль над ресурсами захватить удалось).

ReadWriteLock

Интерфейс ReadWriteLock предлагает другой тип блокировок — отдельную для чтения, и отдельную для записи. Этот интерфейс был добавлен из соображения, что считывать данные (любому количеству потоков) безопасно до тех пор, пока ни один из них не изменяет переменную. Таки образом, блокировку для чтения (read-lock) может удерживать любое количество потоков до тех пор, пока не удерживает блокировка для записи (write-lock). Такой подход может увеличить производительность в случае, когда чтение используется гораздо чаще, чем запись.

В примере выше мы можем видеть, как поток блокирует ресурсы для записи, после чего ждёт одну секунду, записывает данные в HashMap и освобождает ресурсы. Предположим, что в это же время были созданы ещё два потока, которые хотят получить из хэш-таблицы значение:

Если вы попробуете запустить этот пример, то заметите, что оба потока, созданные для чтения, будут простаивать секунду, ожидая завершения работы потока для записи. После снятия блокировки они выполнятся параллельно, и одновременно запишут результат в консоль. Им не нужно ждать завершения работы друг друга, потому что выполнять одновременное чтение вполне безопасно (до тех пор, пока ни один поток не работает параллельно на запись).

StampedLock

В Java 8 появился новый тип блокировок — StampedLock . Так же, как и в предыдущих примерах, он поддерживает разделение на readLock() и writeLock() . Однако, в отличие от ReadWriteLock , метод блокировки StampedLock возвращает “штамп” — значение типа long . Этот штамп может использоваться в дальнейшем как для высвобождения ресурсов, так и для проверки состояния блокировки. Вдобавок, у этого класса есть методы, для реализации “оптимистичной” блокировки. Но обо всём по порядку.

Вот таким образом следовало бы переписать наш предыдущий пример под использование StampedLock :

Работать этот код будет точно так же, как и его брат-близнец с ReadWriteLock . Тут, правда, стоит упомянуть, что в StampedLock не реализована реентерантность. Поэтому особое внимание нужно уделять тому, чтобы не попасть в ситуацию взаимной блокировки (deadlock).

В следующем примере демонстрируется “оптимистичная блокировка”:

Оптимистичная блокировка для чтения, вызываемая с помощью метода tryOptimisticRead() , отличается тем, что она всегда будет возвращать “штамп” не блокируя текущий поток, вне зависимости от того, занят ли ресурс, к которому она обратилась. В случае, если ресурс был заблокирован блокировкой для записи, возвращённый штамп будет равняться нулю. В любой момент можно проверить, является ли блокировка валидной с помощью lock.validate(stamp) . Для приведённого выше кода результат будет таким:

Optimistic Lock Valid: true
Write Lock acquired
Optimistic Lock Valid: false
Write done
Optimistic Lock Valid: false

Оптимистичная блокировка является валидной с того момента, как ей удалось захватить ресурс. В отличии от обычных блокировок для чтения, оптимистичная не запрещает другим потокам блокировать ресурс для записи. Что же происходит в коде выше? После захвата ресурса блокировка является валидной и оптимистичный поток отправляется спать. В это время другой поток блокирует ресурсы для записи, не дожидаясь окончания работы чтения. Начиная с этого момента, оптимистичная блокировка перестаёт быть валидной (даже после окончания записи).

Таким образом, при использовании оптимистичных блокировок вам нужно постоянно следить за их валидностью (проверять её нужно уже после того, как выполнены все необходимые операции).

Иногда может быть полезным преобразовать блокировку для чтения в блокировку для записи не высвобождая ресурсы. В StampedLock это можно сделать с помощью метода tryConvertToWriteLock() , как в этом примере:

В этом примере мы хотим прочитать значение переменной count и вывести его в консоль. Однако, если значение равно нулю, мы хотим изменить его на 23. Для этого нужно выполнить преобразования из readLock во writeLock, чтобы не помешать другим потокам обрабатывать переменную. В случае, если вы вызвали tryConvertToWriteLock() в тот момент, когда ресурс занят для записи другим потоком, текущий поток остановлен не будет, однако метод вернёт нулевое значение. В таком случае можно вызвать writeLock() вручную.

Семафоры

Семафоры — отличный способ ограничить количество потоков, которые одновременно работают над одним и тем же ресурсом:

В этом примере сервис-исполнитель может потенциально запустить все 10 вызываемых потоков, однако мы создали семафор, который ограничивает количество одновременно выполняемых потоков до пяти. Снова напомню, что важно освобождать ресурсы именно в блоке finally<> на случай выброса исключений. Для приведённого выше кода вывод будет следующим:

Semaphore acquired
Semaphore acquired
Semaphore acquired
Semaphore acquired
Semaphore acquired
Could not acquire semaphore
Could not acquire semaphore
Could not acquire semaphore
Could not acquire semaphore
Could not acquire semaphore

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

Надеюсь, вам понравилась статья. Если у вас возникли какие-либо вопросы, вы можете задать их в твиттере.

Введение в разработку мобильных приложений

1.2 Устройство платформы Android

Платформа Android объединяет операционную систему, построенную на основе ядра ОС Linux, промежуточное программное обеспечение и встроенные мобильные приложения. Разработка и развитие мобильной платформы Android выполняется в рамках проекта AOSP (Android Open Source Project) под управлением OHA (Open Handset Alliance), руководит всем процессом поисковый гигант Google.

Android поддерживает фоновое выполнение задач; предоставляет богатую библиотеку элементов пользовательского интерфейса; поддерживает 2D и 3D графику, используя OpenGL стандарт; поддерживает доступ к файловой системе и встроенной базе данных SQLite.

С точки зрения архитектуры, система Android представляет собой полный программный стек, в котором можно выделить следующие уровни:

  • Базовый уровень (Linux Kernel) — уровень абстракции между аппаратным уровнем и программным стеком;
  • Набор библиотек и среда исполнения (Libraries & Android Runtime) обеспечивает важнейший базовый функционал для приложений, содержит виртуальную машину Dalvik и базовые библиотеки Java необходимые для запуска Android приложений;
  • Уровень каркаса приложений (Application Framework) обеспечивает разработчикам доступ к API, предоставляемым компонентами системы уровня библиотек;
  • Уровень приложений (Applications) — набор предустановленных базовых приложений.

Наглядное изображение архитектуры на рисунке 1.1.

Рассмотрим компоненты платформы более подробно.

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

Уровнем выше располагается набор библиотек и среда исполнения. Библиотеки реализуют следующие функции:

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

Библиотеки реализованы на С/С++ и скомпилированы под конкретное аппаратное обеспечение устройства, вместе с которым они и поставляются производителем в предустановленном виде.

Рассмотрим некоторые библиотеки:

Среда исполнения включает в себя библиотеки ядра, обеспечивающие большую часть низкоуровневой функциональности, доступной библиотекам ядра языка Java, и виртуальную машину Dalvik, позволяющую запускать приложения. Каждое приложение запускается в своем экземпляре виртуальной машины, тем самым обеспечивается изоляция работающих приложений от ОС и друг от друга. Для исполнения на виртуальной машине Dalvik Java-классы компилируются в исполняемые файлы с расширением .dex с помощью инструмента dx, входящего в состав Android SDK. DEX (Dalvik EXecutable) — формат исполняемых файлов для виртуальной машины Dalvik, оптимизированный для использования минимального объема памяти. При использовании IDE Eclipse и плагина ADT (Android Development Tools) компиляция классов Java в формат .dex происходит автоматически.

Архитектура Android Runtime такова, что работа программ осуществляется строго в рамках окружения виртуальной машины, что позволяет защитить ядро ОС от возможного вреда со стороны других ее составляющих. Поэтому код с ошибками или вредоносное ПО не смогут испортить Android и устройство на его базе, когда сработают.

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

  • богатый и расширяемый набор представлений (Views), который может быть использован для создания визуальных компонентов приложений, например, списков, текстовых полей, таблиц, кнопок или даже встроенного web-браузера;
  • контент-провайдеры (Content Providers), управляющие данными, которые одни приложения открывают для других, чтобы те могли их использовать для своей работы;
  • менеджер ресурсов (Resource Manager), обеспечивающий доступ к ресурсам без функциональности (не несущим кода), например, к строковым данным, графике, файлам и другим;
  • менеджер оповещений (Notification Manager), позволяющий приложениям отображать собственные уведомления для пользователя в строке состояния;
  • менеджер действий (Activity Manager), управляющий жизненными циклами приложений, сохраняющий историю работы с действиями, предоставляющий систему навигации по действиям;
  • менеджер местоположения (Location Manager), позволяющий приложениям периодически получать обновленные данные о текущем географическом положении устройства.

Application Framework предоставляет в распоряжение приложений в ОС Android вспомогательный функционал, благодаря чему реализуется принцип многократного использования компонентов приложений и ОС. Естественно, в рамках политики безопасности.

И, наконец, самый высокий, самый близкий к пользователю уровень приложений. Именно на этом уровне пользователь взаимодействует со своим устройством, управляемым ОС Android. Здесь представлен набор базовых приложений, который предустановлен на ОС Android. Например, браузер, почтовый клиент, программа для отправки SMS, карты, календарь, менеджер контактов и др. Список интегрированных приложений может меняться в зависимости от модели устройства и версии Android. К этому уровню также относятся все пользовательские приложения.

Разработчик обычно взаимодействует с двумя верхними уровнями архитектуры Android для создания новых приложений. Библиотеки, система исполнения и ядро Linux скрыты за каркасом приложений.

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

Для пополнения коллекции приложений своего мобильного устройства пользователь может воспользоваться приложением Google Play, которое позволяет покупать и устанавливать приложения с сервиса Google Play. Разработчики, в свою очередь, могут выкладывать свои приложения в этот сервис, Google Play отслеживает появление обновлений приложения, сообщает пользователям этого приложения об обновлении и предлагает установить его. Также Google Play предоставляет разработчикам доступ к услугам и библиотекам, например, доступ к использованию и отображению Google Maps.

Для установки приложения на устройствах с ОС Android создается файл с расширением *.apk (Android package), который содержит исполняемые файлы, а также вспомогательные компоненты, например, файлы с данными и файлы ресурсов. После установки на устройство каждое приложение «живет» в своем собственном изолированном экземпляре виртуальной машины Dalvik.

Многоуровневая архитектура в проекте на Java (Часть 1)

В настоящее время в разработке ПО достаточно часто применяется многоуровневая архитектура или многослойная архитектура (n-tier architecture), в рамках которой компоненты проекта разделяются на уровни (или слои). Классическое приложение с многоуровневой архитектурой, чаще всего, состоит из 3 или 4 уровней, хотя их может быть и больше, учитывая возможность разделения некоторых уровней на подуровни. Одним из примеров многоуровневой архитектуры является предметно-ориентированное проектирование (Domain-driven Design, DDD), где основное внимание сконцентрировано на предметном уровне.

В проектах с многоуровневой архитектурой можно выделить четыре уровня (или слоя):

  • Слой представления, с которым взаимодействует пользователь или клиентский сервис. Реализацией слоя представления может быть, например, графический пользовательский интерфейс или веб-страница.
  • Сервисный слой, реализующий взаимодействие между слоями представления и бизнес-логики. Примерами реализаций сервисного слоя являются контроллеры, веб-сервисы и слушатели очередей сообщений.
  • Слой бизнес-логики, в котором реализуется основная логика проекта. Компоненты, реализующие бизнес-логику, обрабатывают запросы, поступающие от компонентов сервисного слоя, а так же используют компоненты слоя доступа к данным для обращения к источникам данных.
  • Слой доступа к данным — набор компонентов для доступа к хранимым данным. В качестве источников данных могут выступать различного рода базы данных, SOAP и REST-сервисы, файлы на файловой системе и т.д.

Направление зависимостей между слоями идёт от слоя представления к слою доступа к данным. В идеальной ситуации каждый слой зависит только от следующего слоя: слой представления зависит от сервисного слоя (например, представление зависит от контроллера), сервисный слой зависит от слоя бизнес-логики (например, контроллер зависит от бизнес-сервиса), а слой бизнес-логики — от слоя доступа к данным (например, бизнес-сервис зависит от репозитория). При этом компоненты бизнес-слоя могут зависеть от других компонентов бизнес-слоя, тогда как в других слоях аналогичные зависимости нежелательны (например, зависимость одного репозитория от другого). Так же нежелательны зависимости в обратном направлении (бизнес-слой не должен зависеть от сервисного слоя) и зависимости между слоями, не являющимися соседними (сервисный слой не должен зависеть от слоя доступа к данным, например).

На практике иногда приходится сталкиваться с примерами, когда бизнес-логика частично или полностью находится в контроллере, а иногда встречаются и вовсе случаи обращения компонентов слоя представления к слою доступа к данным. Несоблюдение разделения кода между слоями непременно приводит к путанице, замедляет процесс разработки и развития проекта и делает процесс поддержки проекта трудоёмким и дорогим.

Допустим, у нас есть код, реализующий бизнес-логику приложения, который находится в контроллере. Что если нам требуется разработать SOAP-сервис, реализующий ту же функциональность? Мы можем скопировать существующий код в SOAP-сервис и внести в него изменения по мере необходимости. Будет ли ли такой подход работать? Да! Вызовет ли такой подход проблемы? Тоже да! В процессе жизненного цикла проекта требования к нему имеют свойство меняться, что ведёт к неизбежным изменениям и в коде. Но при таком подходе нам придётся изменить код и в контроллере, и в SOAP-сервисе, а также внести изменения в их тесты (вы же тестируете свой код?). Но граздо правильнее будет вынести общий код, реализующий бизнес-логику, в компонент слоя бизнес-логики. В этом случае в контроллере и SOAP-сервисе останется код, преобразующий запрос к общему виду, понятному компоненту бизнес-логики.

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

К слову сказать, очень хорошей практикой является применение UML, в данном конкретном случае — диаграммы классов. Из собственной практики помню случай, когда я решил для почти готового проекта составить диаграмму классов, результатом чего стал рефакторинг, уменьшивший количество кода примерно на 20%. Составление диаграммы классов на ранних этапах разработки позволяет уменьшить дублирование кода, сделать структуру классов и зависимости между ними более понятными.

В так полюбившейся мне книге Роберта Марина «Чистая архитектура» автор пропагандирует идею независимости (или минимизации зависимости) архитектуры приложения от внешних факторов: фреймворков, баз данных и прочих сторонних зависимостей. Это говорит не об отказе от использования этих зависимостей (вы же не будете разрабатывать собственный механизм трансляции HTTP-вызовов или хранения данных?), а о минимизации их влияния на архитектуру вашего проекта.

Разработка бизнес-логики

Давайте возьмём в качестве примера разработку блокнота, который пользователь может использовать для работы с заметками. Заметьте, я не указал, что это будет онлайн-сервис или настольное приложение. Для начала определимся с набором типов (классов и интерфейсов), которые нам понадобятся для нашего проекта. Класс-сущность, описывающий заметку — Note, компонент бизнес-логики, реализующий работу с заметками — NoteService, ещё нам потребуется компонент слоя доступа к данным — NoteRepository. Простая реализация NoteService — SimpleNoteService, использует NoteRepository для доступа к источнику данных. Диаграмма классов, описывающая текущую архитектуру, будет достаточно простая:

Теперь можно описать эти типы в коде, написать тесты для SimpleNoteService и реализовать этот класс.

Читать еще:  The Witcher 3: Wild Hunt стала лидером в рейтинге продаж Steam за прошедшую неделю
Ссылка на основную публикацию
Статьи c упоминанием слов:
Adblock
detector