Что такое презентер android
Перейти к содержимому

Что такое презентер android

  • автор:

Что такое MVP?

MVP (Model-View-Presenter) – это шаблон проектирования, который используется для разработки пользовательского интерфейса в приложении.
MVP разделяет ответственность за бизнес логику и логику отображения.

MVP состоит из следующих частей:

• Model представляет собой данные, которые необходимо показать пользователю. В большинстве Android-приложений моделью выступает слой, отвечающий за получение данных с бэкэнда.

• View – это класс, отвечающий за отображение данных. В Android-приложениях View – это обычно Activity или Fragment .
Кроме того View слушает пользовательские ивенты и делегирует их обработку в Presenter.
Например View может иметь такой код:

loginButton.setOnClickListener

• Presenter – это класс, который имеет ссылки и на View, и на Model, и расположен между ними. Presenter отвечает за обработку ивентов, приходящих из View, получение данных из Model и обновление View c полученными данными.
В Android-приложениях хорошей практикой считается делать Presenter независимым от Android SDK. Другими словами Presenter не имеет доступа к Android классам напрямую и может быть использован в plain java приложении.

MVP в Android для самых маленьких

MVP в Android для самых маленьких - 1

Когда я начинал свой путь Android-разработчика, слова «Архитектура мобильного приложения» вызывали у меня глубокое недоумение, гугл и статьи на Хабре вгоняли в ещё большую депрессию — смотрю в книгу, вижу фигу. Думаю, если ты читаешь эту статью, то уже не раз изучал эту картинку и пытался понять, что происходит: Проблема понимания архитектурного подхода в мобильной разработке, на мой взгляд, кроется в абстрактности самой архитектуры. У каждого разработчика своё видение того, как правильно реализовать тот или иной паттерн. Более-менее приличные примеры реализации MVP нашлись в англоязычном секторе интернета, что не удивительно. Кратенько разберём, что есть что, и перейдём к примеру. Model — уровень данных. Не люблю использовать термин «бизнес логика», поэтому в своих приложениях я называю его Repository и он общается с базой данных и сетью. View — уровень отображения. Это будет Activity, Fragment или Custom View, если вы не любите плясок с бубном и взаимодействия с жизненным циклом. Напомню, что изначально все Android приложения подчинены структуре MVC, где Controller это Activity или Fragment. Presenter — прослойка между View и Model. View передаёт ему происходящие события, презентер обрабатывает их, при необходимости обращается к Model и возращает View данные на отрисовку. Применительно к Android и конкретному примеру, выделю важную часть — Contract. Это интерфейс, который описывает все взаимодействия между вышеперечисленными компонентами. Резюмируя теоретическую часть:

  • View знает о Presenter;
  • Presenter знает о View и Model (Repository);
  • Model сама по себе;
  • Contract регулирует взаимодействия между ними.

Собственно, сам пример, для простоты эксперимента будем по нажатию на кнопку загружать строку из БД и отображать в TextView. Например, БД содержит список лучших ресторанов города. Начнем с контракта: Создадим интерфейс MainContract :

 public interface MainContract < interface View < void showText(); >interface Presenter < void onButtonWasClicked(); void onDestroy(); >interface Repository < String loadMessage(); >> 

Пока что мы просто выделяем 3 компонента нашего будущего приложения и что они будут делать. Далее опишем Repository:

 public class MainRepository implements MainContract.Repository < private static final String TAG = "MainRepository"; @Override public String loadMessage() < Log.d(TAG, "loadMessage()"); /** Здесь обращаемся к БД или сети. * Я специально ничего не пишу, чтобы не загромождать пример * DBHelper'ами и прочими не относяшимеся к теме объектами. * Поэтому я буду возвращать строку Сосисочная =) */ return "Сосисочная у Лёхи»; >> 

С ним всё понятно, просто загрузка — выгрузка данных. Далее на очереди Presenter:

 public class MainPresenter implements MainContract.Presenter < private static final String TAG = "MainPresenter"; //Компоненты MVP приложения private MainContract.View mView; private MainContract.Repository mRepository; //Сообщение private String message; //Обрати внимание на аргументы конструктора - мы передаем экземпляр View, а Repository просто создаём конструктором. public MainPresenter(MainContract.View mView) < this.mView = mView; this.mRepository = new MainRepository(); Log.d(TAG, "Constructor"); >//View сообщает, что кнопка была нажата @Override public void onButtonWasClicked() < message = mRepository.loadMessage(); mView.showText(message); Log.d(TAG, "onButtonWasClicked()"); >@Override public void onDestroy() < /** * Если бы мы работали например с RxJava, в этом классе стоило бы отписываться от подписок * Кроме того, при работе с другими методами асинхронного андроида,здесь мы боремся с утечкой контекста */ Log.d(TAG, "onDestroy()"); >> 

Помнишь, я писал про пляски с бубном и жизненный цикл? Presenter живёт до тех пор пока живёт его View, при разработки сложных пользовательских сценариев, советую дублировать все колбеки View в Presenter’e и вызывать их в соответствующие моменты, дублируя ЖЦ Activity/Fragment, чтобы вовремя понять что нужно сделать с теми данными, которые висят в данный момент в «прослойке». И наконец, View:

 public class MainActivity extends AppCompatActivity implements MainContract.View < private static final String TAG = "MainActivity"; private MainContract.Presenter mPresenter; private Button mButton; private TextView myTv; @Override protected void onCreate(Bundle savedInstanceState) < super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //Создаём Presenter и в аргументе передаём ему this - эта Activity расширяет интерфейс MainContract.View mPresenter = new MainPresenter(this); myTv = (TextView) findViewById(R.id.text_view); mButton = (Button) findViewById(R.id.button); mButton.setOnClickListener(new View.OnClickListener() < @Override public void onClick(View v) < mPresenter.onButtonWasClicked(); >>); Log.d(TAG, "onCreate()"); > @Override public void showText(String message) < myTv.setText(message); Log.d(TAG, "showMessage()"); >//Вызываем у Presenter метод onDestroy, чтобы избежать утечек контекста и прочих неприятностей. @Override public void onDestroy() < super.onDestroy(); mPresenter.onDestroy(); Log.d(TAG, "onDestroy()"); >> 
  • Activity, она же View, в методе onCreate() создаёт экзмпляр Presenter и передаёт ему в конструктор себя.
  • Presenter при создании явно получает View и создаёт экзмепляр Repository (его, кстати, можно сделать Singleton)
  • При нажатии на кнопку, View стучится презентеру и сообщает: «Кнопка была нажата».
  • Presenter обращается к Repository: «Загрузи мне вот эту шнягу».
  • Repository грузит и отдаёт «шнягу» Presenter’у.
  • Presenter обращается к View: «Вот тебе данные, отрисуй»

Model-View-Presenter — компромисс и универсальный рецепт

image

Аббревиатуру MVP можно интерпретировать по разному, но в статье речь пойдет не о спорте.

В сети есть большое количество статей по архитектурным паттернам для iOS и Android разработчиков, и по MVP в частности. Иногда паттерн рассматривается в контексте обеих платформ. Кто-то выбирает данный паттерн для улучшения тестируемости своего кода, кто-то использует его в основном для разделения кода представления от модели. Также встречаются решения, которые используют MVP для унифицирования кода платформ, при условии что разработчики в компании владеют данными технологиями. Но общих слов и выводов иногда недостаточно для разработчика-прагматика. При проектировании коммерческих приложений неизбежно возникает множество деталей, которые общая архитектурная концепция не может раскрыть, и нельзя сказать, что есть единственное каноническое решение.

В статье я постараюсь описать ситуации, с которыми очень часто сталкиваются мобильные разработчики на реальных проектах, и когда действительно стоит задуматься о переходе на архитектурный паттерн более сложный чем “One UIViewController (Activity) to rule them all”. Или лучше сказать, когда нам это будет выгодно. Далее речь пойдет о компромиссе между временем и сложностью разработки в реалиях “обычных” проектов, которые в основном приходят на оценку и разработку.

Введение

Большинство мобильных проектов для нативных SDK сейчас являются клиент-серверными приложениями. В свою очередь такие приложения по сложности системы и времени жизни могут сильно отличаться. Есть приложения “однодневки” для работы в рамках одного мероприятия или ежегодного праздника, после которого они никому не нужны. Есть и серьезные проекты, требующие большого процента покрытия кода тестами, для обеспечения стабильной работы при внесении изменений разными участниками команды.

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

  • количество экранов: 5-20 штук, либо столько экранов должно быть в первой версии;
  • приложение должно быть спроектировано под две основные мобильные платформы: iOS и Android;
  • присутствует авторизация;
  • есть система кэширования с использованием как правило локальной базы данных;
  • делаются не только GET, но и POST, PUT, DELETE запросы, причем эти запросы вносят изменения в закэшированные данные, скачанные на предыдущем этапе;
  • приложение будет расширяться.
Сравнение MVP с паттернами по умолчанию

Рассмотрим самый простой паттерн, а именно iOS MVC с пассивной моделью, который является по сути жесткой связкой слоев представления и модели, где вся логика находится в UIViewController-е. Аналогичный подход получается и на Android-е, если вы пишите свои проекты по руководству из видеоуроков для начинающих или с большинства обучающих сайтов.

image

Если сравнить его с MVP, то основным отличием является класс Presenter, в который мы выносим логику обработки событий, форматирования данных и управления View. Под View мы будем понимать слой, включающий дочерние классы UIViewController, Activity или Fragment и их связку с классами всевозможных контролов. Таким образом мы “разгружаем” классы аналогичные UIViewController от тех обязанностей, которыми они не должны заниматься, оставляя внутри только код инициализации представлений и анимаций.

image

Как это часто бывает, в течение разработки первой версии приложения дополнительно добавляются функциональности, связанные с недостаточной проработкой ТЗ. Иногда изменения настолько радикальны, что приходится переписывать бОльшую часть уже проделанной работы. Наиболее часто встречается ситуация, когда просят добавить дополнительное поле к сущности и отобразить отформатированную информацию. Проследим какие классы мы изменим в проекте при добавление нового UI-элемента, отображающего отформатированную дату:

image

  • используя MVC с пассивной моделью:

image

  • используя MVP:

Очевидно, что мы усложнили систему введением паттерна MVP, так как количество классов, которые подверглись изменению при простом добавлении нового свойства сущности у нас возросло. Отдельно стоит отметить, что при реализации MVP создают отдельный интерфейс для View и пытаются сделать так, чтобы в Presenter-е находилось как можно меньше кода, связанного с платформой и не было прямых ссылок на конкретных наследников UIViewController, Activity или Fragment, потому что иначе будет соблазн написать код представления непосредственно в Presenter-е.

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

В поиске компромисса

Встает логичный вопрос, а зачем же все усложнять?

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

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

image

Не стоит путать модель представления в данной статье с ViewModel из MVVM, название лишь указывает на сущность, хранящую отформатированную и готовую к показу во View информацию.

При использовании обычного подхода мы, скорее всего, разместили бы код составления модели для ячейки в наследнике UIViewController-е или Activity (Fragment-е), что повлекло за собой увеличение кода в классе, в котором и так намешано немало, связанного с функционированием представления.

Написание “полезных” интеграционных тестов также становится возможным с вводом MVP, где основным объектом тестирования выступает Presenter. Конечно, используя только юнит-тестирование, можно протестировать используемые в приложении компоненты, которые являются God-объектами и наследниками UIViewController или Activity (Fragment), но это будет не вполне эффективно.

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

image

Небольшие уточнения к диаграмме:

    Для Android не актуально хранение ссылки на Presenter непосредственно в Activity, поэтому на практике у нас используется Retained Fragment и базовые классы для Activity и обычного Fragment-а, в которых описана логика инициализации и получения уже созданного ранее Presenter-а.

Много кода

public abstract class BasePresenterActivity extends AppCompatActivity < private static final String PRESENTER_FRAGMENT_TAG = "presenter_fragment_tag"; private P mPresenter; @Override protected void onCreate(@Nullable Bundle savedInstanceState) < super.onCreate(savedInstanceState); getPresenter().bindView(this); >@Override protected void onPause() < super.onPause(); if (isFinishing()) < PresenterFragment presenterFragment = (PresenterFragment) getSupportFragmentManager() .findFragmentByTag(PRESENTER_FRAGMENT_TAG); if (presenterFragment != null) < getSupportFragmentManager().beginTransaction().remove(presenterFragment).commit(); >> > @Override protected void onDestroy() < if (!isFinishing() && mPresenter != null) < mPresenter.unbindView(); >super.onDestroy(); > protected P getPresenter() < if (mPresenter != null) < return mPresenter; >PresenterFragment fragment = getPresenterFragment(); if (fragment.isPresenterSet()) < mPresenter = fragment.getPresenter(); >else < mPresenter = createPresenter(); fragment.setPresenter(mPresenter); >return mPresenter; > protected abstract P createPresenter(); private PresenterFragment getPresenterFragment() < PresenterFragment presenterFragment = (PresenterFragment) getSupportFragmentManager() .findFragmentByTag(PRESENTER_FRAGMENT_TAG); if (presenterFragment == null) < presenterFragment = new PresenterFragment(); getSupportFragmentManager() .beginTransaction() .add(presenterFragment, PRESENTER_FRAGMENT_TAG) .commit(); >return presenterFragment; > > 
public class PresenterFragment extends Fragment < private BasePresenter mPresenter; @Override public void onCreate(@Nullable Bundle savedInstanceState) < super.onCreate(savedInstanceState); setRetainInstance(true); >public P getPresenter() < return (P) mPresenter; >public void setPresenter(P presenter) < mPresenter = presenter; >public boolean isPresenterSet() < return mPresenter != null; >> 
public abstract class BasePresenter  < protected V mView; public void bindView(V view) < mView = view; >public void unbindView() < mView = null; >> 

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

Диаграмма разбиения сервиса на несколько подсервисов для Android

image

Если у вас не более 20-25 API методов, то код остается читаемым в рамках одного файла, при условии правильного форматирования и комментирования. Для первой версии продукта можно описывать всю логику получения и отправки данных в пределах одного класса. Но не стоит увлекаться, так как технический долг со временем будет увеличиваться.

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

Без документации, я бы все таки остановил разработку на этапе создания дизайна экранов и выводом тестовых данных на основе моделей представления. В этом случае вы также получите более менее функциональный интерфейс пригодный для демо, но самое главное вы не потратите много времени на изменение сущностей для подгонки их под реальное API, так как Presenter выступит в роли адаптера, в котором будет осуществляться преобразование данных от сервиса в форматированные данные модели представления.

Универсальность

Другим плюсом использования паттерна MVP является его универсальность для iOS и Android. Если у вас большое количество проектов разрабатывается под обе платформы, то логика Presenter-а будет универсальной, и если разработка приложений происходит по очереди, то адаптация на другой платформе будет проходить быстрее и предсказуемее, так как код логики в Presenter-е практически одинаковый. Более того, на этапе начала работы по адаптации для другой платформы уже будут готовые тест-кейсы. Конечно, если вы удосужились потратить время и написать их.

Следующим преимуществом использования паттерна MVP является разделение ресурсов разработчиков под разные платформы. Например, iOS синьор может написать часть кода под Android на уровне джуниора или мидла и быть при этом полезным, чтобы не пришлось за ним все переделывать. Сам я не сторонник “универсальных солдат”, так как лучше знать одну технологию хорошо, чем несколько на уровне джуниора или мидла. Практикующих старших разработчиков (не тимлидов или технических директоров) под обе платформы я не встречал, но не буду спорить, что такие профессионалы существуют. Основная причина дефицита таких людей, на мой взгляд, заключается в том, что в наше время очень тяжело уследить за развитием обеих технологий. Даже при условии того, что iOS и Android заимствуют некоторые конструкции друг у друга, под капотом реализация все равно разная. Но для небольших команд и “обычных” проектов подход с использованием непрофильного разработчика является вполне адекватным. Многие iOS программисты хотели бы попробовать себя в Android и наоборот. Можно отдать такому “легионеру” написать часть кода, связанного с Model или Presenter. Также будет неплохо, если человек сможет написать простой UI. Но задачи со сложными UI элементами с анимацией, оптимизацией, профилированием и многопоточностью, за исключением вызовов API сервиса, конечно, должен решать уже более опытный профильный разработчик.

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

Сравнение с другими известными архитектурными шаблонами

Есть еще один очень важный вопрос: почему за основу был выбран именно MVP, а не паттерны, основанные на чистой архитектуре или MVVM? В начале статьи мы постарались сконцентрироваться на том, что имеем дело с “обычными” проектами, которые желательно написать быстро, но с должным качеством и возможностью долгосрочной поддержки.

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

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

Выводы

Перейдем к выводам. Преимущества, которые нам удалось выявить для паттерна MVP, если посмотреть на него со стороны выгоды внедрения в разработку:

  1. Настоящее отделение логики представления от модели, в отличие, к примеру, от Apple MVC;
  2. Четкое разделение ответственности между классами:
    • View — прорисовка, анимации, переходы между экранами;
    • Presenter — форматирование, реакция на события, логика представления и управление View;
    • Model — работа с загрузкой данных по API, извлечение данных из БД и их кэширование;
  3. Практически универсальная реализация интерфейсов Model-View-Presenter-а на мобильных платформах для “обычных” проектов;
  4. Интеграционное тестирование на уровне Presenter-а;
  5. Разделение задач в команде в рамках разработки одного экрана на задачи представления (вместе с Presenter-ом) и модели;
  6. Возможность показа интерактивного демо заказчику, без работающего бэкенда. При появлении реального сервиса мы не выбрасываем весь код, который написали, а адаптируем API;
  7. Возможность эффективного привлечения непрофильного разработчика из команды для написания кода на другой платформе;
  8. Расширение и добавление новых фич не вызовет эффекта “чужого кода”, когда человек возвращается к разработке проекта после длительного перерыва из-за набора простых правил размещения кода в строго определенных модулях.

Подводя итоги, можно утверждать следующее: если у вас есть небольшая команда из специалистов готовых на реализацию проектов под основные мобильные платформы, вам нужны универсальные архитектурные правила, а также возможность распараллеливания задач в рамках экрана и необходимость показа демо заказчику с частично работающей функциональностью, например, если практикуются спринты, то MVP определенно ваш выбор. Дополнительным бонусом выступает удобная поддержка проекта, которая не должна привести к фразе “а вот если бы мы сейчас написали все заново” и ситуациям, когда только для того, чтобы разобраться в коде одного огромного UIViewController-а или Activity будет потрачено больше времени, чем на саму фичу.

  • архитектура приложений
  • проектирование
  • mvp
  • разработка под ios
  • разработка под android
  • Разработка под iOS
  • Разработка мобильных приложений
  • Проектирование и рефакторинг
  • Разработка под Android

Что такое MVP архитектура

MVP (Model-View-Presenter) — это популярный паттерн архитектуры для разработки программного обеспечения, который используется для построения приложений.

5 месяцев назад

MVP (Model-View-Presenter) — это популярный архитектурный шаблон для разработки программного обеспечения, который используется для построения приложений. MVP разделяет приложение на три основных компонента:

  1. Модель (Model): Модель представляет собой бизнес-логику приложения и данные. Она ответственна за выполнение операций, таких как чтение и запись данных, обработка бизнес-логики и взаимодействие с базой данных или внешними источниками данных. Модель не зависит от представления или презентера и предоставляет API для доступа к данным.
  2. Представление (View): Представление отображает данные пользователю и обрабатывает пользовательский ввод. Оно представляет собой интерфейс пользователя, через который пользователь взаимодействует с приложением. В MVP представление пассивно и не содержит бизнес-логики. Оно лишь отображает данные, предоставленные презентером, и передает пользовательский ввод презентеру.
  3. Презентер (Presenter): Презентер является посредником между моделью и представлением. Он содержит бизнес-логику приложения и управляет взаимодействием между моделью и представлением. Презентер получает данные от модели, форматирует их и передает представлению для отображения. Он также обрабатывает пользовательский ввод, передавая соответствующие команды модели для обновления данных.

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

Чем MVP отличается от MVC

MVP (Model-View-Presenter) и MVC (Model-View-Controller) — это два популярных паттерна архитектуры, используемых для разработки программного обеспечения с пользовательским интерфейсом (GUI). Они имеют много общих концепций, но есть существенные различия в том, как они организуют компоненты приложения. Вот основные различия между ними:

  1. Распределение ответственности:
    • В MVC:
      • Модель (Model) представляет бизнес-логику и данные.
      • Представление (View) отвечает за отображение данных и обработку пользовательского ввода.
      • Контроллер (Controller) управляет взаимодействием между моделью и представлением, обрабатывает пользовательский ввод и принимает решения о том, какие данные должны быть показаны в представлении.
    • В MVP:
      • Модель (Model) также представляет бизнес-логику и данные.
      • Представление (View) пассивно отображает данные и передает пользовательский ввод презентеру.
      • Презентер (Presenter) берет на себя большую часть бизнес-логики и управления представлением. Он является посредником между моделью и представлением и принимает решения о том, какие данные должны быть отображены в представлении.
  2. Зависимость:
    • В MVC:
      • Представление (View) обычно зависит от контроллера (Controller) и обновляется контроллером при изменении данных модели (Model).
      • Контроллер (Controller) может непосредственно взаимодействовать с представлением (View) для обновления его состояния.
    • В MVP:
      • Представление (View) пассивно отображает данные и не зависит напрямую от презентера (Presenter). Оно обновляется презентером.
      • Презентер (Presenter) полностью управляет представлением и не имеет прямой зависимости от него.
  3. Тестирование:
    • В MVC:
      • Тестирование контроллера (Controller) может быть сложным из-за его прямой связи с представлением (View).
      • Представление (View) может быть трудно подвергнуто юнит-тестированию.
    • В MVP:
      • Презентер (Presenter) легко подвергается юнит-тестированию, так как он не имеет прямой связи с фактическим представлением (View).
      • Представление (View) может быть протестировано как отдельно, так и с заменой презентера на фиктивный (mock) объект для тестирования.

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

Что такое MVP архитектура

Недостатки MVP

Архитектура имеет свои преимущества, но она также имеет некоторые недостатки:

  1. Повышенная сложность: MVP может быть более сложной архитектурой по сравнению с некоторыми другими подходами, такими как MVC (Model-View-Controller) или MVVM (Model-View-ViewModel). Это может потребовать больше кода для настройки связей между компонентами и управления потоком данных.
  2. Большая ответственность презентера: В MVP презентер берет на себя множество задач, включая управление представлением и бизнес-логикой. Это может привести к созданию презентеров, которые становятся слишком громоздкими и сложными для поддержки и тестирования.
  3. Ненадежная связь между представлением и презентером: В MVP представление имеет ссылку на презентер, и эта связь может быть ненадежной, особенно при работе с множеством представлений и презентеров. Неправильное управление ссылками может привести к утечкам памяти или некорректному поведению.
  4. Сложность тестирования: Хотя презентеры в MVP легко поддаются юнит-тестированию, интеграционное тестирование представлений может быть сложным, особенно если представление содержит сложный интерфейс или зависимости от системных компонентов.
  5. Передача данных: В MVP данные передаются между компонентами с помощью интерфейсов и методов, что может быть несколько неуклюжим и требовать больше кода для маппинга данных.
  6. Повышенная зависимость от языка и фреймворка: Реализация MVP может сильно зависеть от конкретного языка программирования и фреймворков, что может затруднить перенос кода на другие платформы или использование новых технологий.
  7. Сложность поддержки сложных интерфейсов: Если приложение имеет сложный и динамический пользовательский интерфейс, то MVP может потребовать дополнительных усилий для управления этими интерфейсами и соблюдения принципов разделения ответственности.

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

Дополнительно

  • Model-View-Presenter в Википедии
  • MVP Sample: Android Clean Architecture + пример MVP

Если вы нашли опечатку — выделите ее и нажмите Ctrl + Enter! Для связи с нами вы можете использовать info@apptractor.ru.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *