SlideShare a Scribd company logo
1 of 49
Most Volatile Palaver
Paul Blundell
MVP examined holistically and subjectively
My Vision Program
- Highlight the variations
- Talk about the conflictions
- Define the naming
- Example implementation
- Emphasize important points
- Get Pragmatic
image
Oh you know MVP?
Oh you know MVP?
http://www.wildcrest.com/Potel/Portfolio/mvp.pdf
http://martinfowler.com/eaaDev/uiArchs.html
https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93presenter
https://msdn.microsoft.com/en-us/library/ff649571.aspx
https://github.com/konmik/konmik.github.io/wiki/Introduction-to-Model-View-Presenter-on-
Android
http://c2.com/cgi/wiki?ModelViewPresenter http://www.gwtproject.org/articles/mvp-
architecture.html https://www.youtube.com/watch?v=oiNfPjV72lg
http://polymorphicpodcast.com/shows/mv-patterns/
https://developer.ibm.com/open/2015/10/22/model-view-presenter-mvp-for-ibm-ready-
apps/ https://caster.io/episodes/episode-48-model-view-presenter-part-1-what-is-the-
mvp-pattern/ http://fernandocejas.com/tag/model-view-presenter/
http://engineering.remind.com/android-code-that-scales/
http://antonioleiva.com/mvp-android/
http://geekswithblogs.net/nharrison/archive/2008/09/22/125373.aspx
image
image
P
V
image
image
https://leanpub.com/software-architecture-for-developers https://leanpub.com/visualising-software-architecture
image
I know MVP
No I know MVP
No. I know MVP
Ivory Tower Syndrome
- My MVP works so it should work
everywhere
- My MVP is the only possible architecture
- Non collaboration
- Lack of discussion of the details
further reading: http://techdistrict.kirkk.com/2009/11/03/turtles-and-architecture/
image
image
Indecent Exposure (42):
This smell indicates the lack of
what David Parnas so famously
termed information hiding. The
smell occurs when methods or
classes that ought
not to be visible to clients are
publicly visible to them. Exposing
such code means that
clients know about code that is
unimportant or only indirectly
important. This contributes
to the complexity of a design.
image
image
image
Here is another opinion!
- Hangover Cures is an app I wrote back in 2012
- Two screens, a list of hangover cures, individual details
- All code was in the Activity
- Added new feature:
Now has a comment
stream, for people to leave
comments about the
cures.
Model
- Thin layer and a boundary to the rest of the architecture
of the application (in my case ‘clean architecture’)
- It’s not so much a domain model more of a ‘what can be
done on this view’ api
- Model contains the threading choices
View
- Passive View (not observing the model)
- Gets information from ViewModel objects
- The Activity as the View on Android
- Treat Android Views like primitives and we always want
to wrap them in a Domain View
- Encapsulate native Android user interaction
mechanisms and define Domain specific ones
Presenter
- Has knowledge of Model & View
- Decides on action after user interaction
- Observes the Model for changes
- Decides how View is notified of Model changes
- Doesn’t care about threading
- Never uses primitive Views or native Listeners
image
Package Structure
- Not necessary for MVP but a
good bedrock to work from
- Feature based
- Clearly see the app’s
concerns
- Minimal learning curve
Core / Mobile split
MVP is a UI level architecture it is not an application
architecture
MVP belongs in the mobile module*
The presenter can have Android imports, that’s ok
For application wide architecture see:
https://blog.8thlight.com/uncle-bob/2012/08/13/the-clean-architecture.html
https://www.novoda.com/blog/hexawhat-architecture/
Single Feature Example - Comments
Only the Activity needs to be public
First place to start [Feature]Mvp.java
Classes shaded out not directly involved
in MVP
[Feature]Mvp.java
class CommentsMvp {
public interface Model extends Closeable {
...
}
public interface View {
...
}
public interface Presenter {
...
}
- The inner classes allow for great naming
practices and improved readabilty.
- This stops strange things like
CommentsPresenterImpl implements CommentsPresenter
- It also highlights the UI layers MVP pattern
very obviously to the legacy developer
CommentsMvp.java Implementers
class CommentsModel implements CommentsMvp.Model {
...
}
public class CommentsActivityView extends AppCompatActivity implements CommentsMvp.View, CommentsStream.Listener {
...
}
class CommentsAnalyticsView implements CommentsMvp.View {
...
}
class CommentsPresenter implements CommentsMvp.Presenter,
CommentsMvp.Model.AdvertRequestLoadedCallback,
CommentsMvp.Model.UserLoadedCallback,
CommentsMvp.Model.CommentSavedCallback,
CommentsMvp.Model.CommentsLoadedCallback,
CommentsMvp.Model.CommentUpdatedCallback {
...
}
CommentsMvp.Model
public interface Model extends Closeable {
void loadUser(UserLoadedCallback callback);
void loadAdvertRequest(AdvertRequestLoadedCallback callback);
void loadCommentsFor(Cure cure, SortOrder sortOrder, CommentsLoadedCallback callback);
void saveComment(Cure.Id id, ViewComment comment, CommentSavedCallback callback);
void saveVoteFor(Cure.Id id, ViewComment comment, Vote down, CommentUpdatedCallback callback);
boolean canVoteOnCommentWith(Cure.Id cureId, Comment.Id commentId);
interface CommentSavedCallback {
void onSaved(ViewComment comment);
}
interface UserLoadedCallback {
void onLoaded(String username); // TODO param can be an object containing also users profile pic
}
interface AdvertRequestLoadedCallback {
void onLoaded(AdRequest advertRequest);
}
interface CommentsLoadedCallback {
void onLoaded(List<ViewComment> comments);
}
interface CommentUpdatedCallback {
void onUpdated(ViewComment comment);
}
}
- callbacks here, can be any
observing method
- save/load is a simple pattern
when you don’t have much
client side state
- knowledge of MVP domain
objects
- no knowledge of Android
CommentsMvp.Model Implementor
class CommentsModel implements CommentsMvp.Model {
...
private final UseCaseModelAdapter modelAdapter;
private final Log log;
public CommentsModel(UseCaseModelAdapter modelAdapter, Log log) {
this.modelAdapter = modelAdapter;
this.log = log;
}
@Override
public void loadAdvertRequest(final AdvertRequestLoadedCallback callback) {
Subscription subscription = Observable.create(modelAdapter.getAdvertRequest())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
...
}
- Thin layer that then moves
from MVP architecture to our
back end of the app
architecture
- Injects the logger to allow
dependency inversion
- Controls asynchronicity as
the model knows when its
innards need threads
CommentsMvp.Model Implementor
class CommentsModel implements CommentsMvp.Model {
...
private final UseCaseModelAdapter modelAdapter;
private final Log log;
public CommentsModel(UseCaseModelAdapter modelAdapter, Log log) {
this.modelAdapter = modelAdapter;
this.log = log;
}
@Override
public void loadAdvertRequest(final AdvertRequestLoadedCallback callback) {
Subscription subscription = Observable.create(modelAdapter.getAdvertRequest())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
...
}
- Thin layer that then moves
from MVP architecture to our
back end of the app
architecture
- Injects the logger to allow
dependency inversion
- Controls asynchronicity as
the model knows when its
innards need threads
CommentsMvp.Model Implementor
class CommentsModel implements CommentsMvp.Model {
...
private final UseCaseModelAdapter modelAdapter;
private final Log log;
public CommentsModel(UseCaseModelAdapter modelAdapter, Log log) {
this.modelAdapter = modelAdapter;
this.log = log;
}
@Override
public void loadAdvertRequest(final AdvertRequestLoadedCallback callback) {
Subscription subscription = Observable.create(modelAdapter.getAdvertRequest())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
...
}
- Thin layer that then moves
from MVP architecture to our
back end of the app
architecture
- Injects the logger to allow
dependency inversion
- Controls asynchronicity as
the model knows when its
innards need threads
CommentsMvp.View
public interface View {
void create();
void show(ViewCure cure);
void show(String username);
void show(AdRequest advertRequest);
void show(List<ViewComment> comments);
void showInteractionsFor(ViewComment comment);
void update(ViewComment comment);
void notifyAlreadyVoted();
}
- All commanding methods, telling what to
do
- Use ViewModels to pass the data, here
the naming I think lets it down a bit as
ViewCure could be read incorrectly as
“view the cure” rather than “the view cure
model”
CommentsMvp.Presenter
public interface Presenter {
void onCreate(ViewCure cure);
void onCommented(String comment);
void onSelected(ViewComment comment);
void onSelectedVoteUp(ViewComment comment);
void onSelectedVoteDown(ViewComment comment);
void onSelectedFilterCommentsByMostPopularFirst();
void onSelectedFilterCommentByNewestFirst();
}
- includes the lifecycle methods
needed
- includes methods that react to user
interaction (i.e. methods you call
inside a click listener)
Want to investigate this for the lifecycle callbacks https://github.com/soundcloud/lightcycle
CommentsMvp.Presenter Implementor
class CommentsPresenter implements
CommentsMvp.Presenter,
CommentsMvp.Model.AdvertRequestLoadedCallback,
CommentsMvp.Model.UserLoadedCallback,
CommentsMvp.Model.CommentSavedCallback,
CommentsMvp.Model.CommentsLoadedCallback,
CommentsMvp.Model.CommentUpdatedCallback {
private final CommentsMvp.Model model;
private final CommentsMvp.View view;
private String username;
private ViewCure cure;
…
@Override
public void onCreate(ViewCure cure) {
this.cure = cure;
view.create();
view.show(cure);
model.loadAdvertRequest(this);
model.loadUser(this);
model.loadCommentsFor(cure, SortOrder.MOST_POPULAR_FIRST, this);
}
- observes the model
- knows about the Model and the View
- keeps state
- onCreate it tells the view to create,
populates the view and requests first
load from the model
CommentsMvp.Presenter Implementor
class CommentsPresenter implements
CommentsMvp.Presenter,
CommentsMvp.Model.AdvertRequestLoadedCallback,
CommentsMvp.Model.UserLoadedCallback,
CommentsMvp.Model.CommentSavedCallback,
CommentsMvp.Model.CommentsLoadedCallback,
CommentsMvp.Model.CommentUpdatedCallback {
private final CommentsMvp.Model model;
private final CommentsMvp.View view;
private String username;
private ViewCure cure;
…
@Override
public void onCreate(ViewCure cure) {
this.cure = cure;
view.create();
view.show(cure);
model.loadAdvertRequest(this);
model.loadUser(this);
model.loadCommentsFor(cure, SortOrder.MOST_POPULAR_FIRST, this);
}
- observes the model
- knows about the Model and the View
- keeps state
- tells the view to create, populates the
view and requests first load from the
model
CommentsMvp.Presenter Implementor
class CommentsPresenter implements
CommentsMvp.Presenter,
CommentsMvp.Model.AdvertRequestLoadedCallback,
CommentsMvp.Model.UserLoadedCallback,
CommentsMvp.Model.CommentSavedCallback,
CommentsMvp.Model.CommentsLoadedCallback,
CommentsMvp.Model.CommentUpdatedCallback {
private final CommentsMvp.Model model;
private final CommentsMvp.View view;
private String username;
private ViewCure cure;
…
@Override
public void onCreate(ViewCure cure) {
this.cure = cure;
view.create();
view.show(cure);
model.loadAdvertRequest(this);
model.loadUser(this);
model.loadCommentsFor(cure, SortOrder.MOST_POPULAR_FIRST, this);
}
- observes the model
- knows about the Model and the View
- keeps state
- tells the view to create, populates the
view and requests first load from the
model
CommentsMvp.Presenter Implementor
class CommentsPresenter implements
CommentsMvp.Presenter,
CommentsMvp.Model.AdvertRequestLoadedCallback,
CommentsMvp.Model.UserLoadedCallback,
CommentsMvp.Model.CommentSavedCallback,
CommentsMvp.Model.CommentsLoadedCallback,
CommentsMvp.Model.CommentUpdatedCallback {
private final CommentsMvp.Model model;
private final CommentsMvp.View view;
private String username;
private ViewCure cure;
…
@Override
public void onCreate(ViewCure cure) {
this.cure = cure;
view.create();
view.show(cure);
model.loadAdvertRequest(this);
model.loadUser(this);
model.loadCommentsFor(cure, SortOrder.MOST_POPULAR_FIRST, this);
}
- observes the model
- knows about the Model and the View
- keeps state
- tells the view to create, populates the
view and requests first load from the
model
CommentsMvp.Presenter Implementor
…
@Override
public void onSelectedFilterCommentByNewestFirst() {
model.loadCommentsFor(cure, SortOrder.NEWEST_FIRST, this);
}
...
@Override
public void onSaved(ViewComment comment) {
view.update(comment);
}
...
- observes the View and decides what
action to take on user interaction
- observes the Model and decides how
the view should be updated
ViewComment
A comment whos responsibilities lie in the view layer
- vs a comment whos responsibilities lie in the domain
layer
- Meaning it can have view centric methods
- getContentDescription, getFormattedDate
- Immutable, only get never set
- Could implement Parcelable
CommentsAnalyticsView
- Analytics tracking can be thought
of as another view on the same
presenter
- Uses decorator pattern, could
also be an observer pattern if you
wanted more than two
- Experimental ...
class CommentsAnalyticsView implements CommentsMvp.View {
...
public CommentsAnalyticsView(Tracker tracker, CommentsMvp.View view) {
this.tracker = tracker;
this.view = view;
}
@Override
public void create() {
tracker.setScreenName("Comments");
tracker.send(new HitBuilders.ScreenViewBuilder().build());
view.create();
}
@Override
public void show(Cure cure) {
view.show(cure);
}
…
@Override
public void showInteractionsFor(ViewComment comment) {
tracker.setScreenName("Interaction " + comment.getName());
tracker.send(new HitBuilders.ScreenViewBuilder().build());
view.showInteractionsFor(comment);
}
}
Presenter Instantiation
onCreate is in the Activity, newInstance is in the Presenter (or in any factory)
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ViewCure cure = (ViewCure) getIntent().getSerializableExtra(EXTRA_CURE);
HangoverCuresApplication dependencyProvider = (HangoverCuresApplication) getApplicationContext();
presenter = CommentsPresenter.newInstance(dependencyProvider, this);
presenter.onCreate(cure);
}
public static CommentsMvp.Presenter newInstance(HangoverCuresApplication dependencyProvider, CommentsMvp.View view) {
Log log = new AndroidLog();
FirebaseCommentRepository firebase = new FirebaseCommentRepository();
SharedPrefsVoteRepository sharedPrefsVoteRepository = SharedPrefsVoteRepository.newInstance(dependencyProvider.getApplicationContext());
CommentUseCase commentUseCase = new CommentUseCase(firebase);
VotingUseCase votingUseCase = new VotingUseCase(sharedPrefsVoteRepository);
UseCaseModelAdapter useCaseModelAdapter = new UseCaseModelAdapter(commentUseCase, votingUseCase);
CommentsMvp.Model model = new CommentsModel(useCaseModelAdapter, log);
Tracker tracker = dependencyProvider.getAnalyticsTracker();
return new CommentsPresenter(model, new CommentsAnalyticsView(tracker, view));
}
Deliberate View language
- Try to consider the domain of your UI (talk to the designers & business
analysts)
- Never end a custom view with the word view
- Avoids communication issues & complications
class CommentsStream extends LinearLayout {
- When using primitive views consider naming them widgets
public class DetailsActivityView extends AppCompatActivity implements DetailsMvp.View {
private DetailsMvp.Presenter presenter;
private TextView titleWidget;
private TextView descriptionWidget;
private RatingBar ratingBarWidget;
private AdView advertWidget;
image
image
SRS TEAM
TIME
image
image
image
image
https://github.com/novoda/spikes/tree/master/Architecture
image
Thanks
blundell_apps
G what?
blundell
throw new SlideIndexOutOfBoundsException();
blundell_apps
G what?
blundell
Questions?

More Related Content

Similar to My perspective on MVP and architecture discussions

Architectural Design Pattern: Android
Architectural Design Pattern: AndroidArchitectural Design Pattern: Android
Architectural Design Pattern: AndroidJitendra Kumar
 
jquery summit presentation for large scale javascript applications
jquery summit  presentation for large scale javascript applicationsjquery summit  presentation for large scale javascript applications
jquery summit presentation for large scale javascript applicationsDivyanshGupta922023
 
jQquerysummit - Large-scale JavaScript Application Architecture
jQquerysummit - Large-scale JavaScript Application Architecture jQquerysummit - Large-scale JavaScript Application Architecture
jQquerysummit - Large-scale JavaScript Application Architecture Jiby John
 
From User Action to Framework Reaction
From User Action to Framework ReactionFrom User Action to Framework Reaction
From User Action to Framework Reactionjbandi
 
Windows Store Apps: Tips & Tricks
Windows Store Apps: Tips & TricksWindows Store Apps: Tips & Tricks
Windows Store Apps: Tips & TricksRobert MacLean
 
Skroutz Android MVP and Adapter Delegates presentation
Skroutz Android MVP and Adapter Delegates  presentationSkroutz Android MVP and Adapter Delegates  presentation
Skroutz Android MVP and Adapter Delegates presentationgmetal
 
Understanding angular js
Understanding angular jsUnderstanding angular js
Understanding angular jsAayush Shrestha
 
MVVM ( Model View ViewModel )
MVVM ( Model View ViewModel )MVVM ( Model View ViewModel )
MVVM ( Model View ViewModel )Ahmed Emad
 
Reactive application using meteor
Reactive application using meteorReactive application using meteor
Reactive application using meteorSapna Upreti
 
JavaScript Framework Smackdown
JavaScript Framework SmackdownJavaScript Framework Smackdown
JavaScript Framework Smackdownmeghantaylor
 
Code Camp 06 Model View Presenter Architecture
Code Camp 06   Model View Presenter ArchitectureCode Camp 06   Model View Presenter Architecture
Code Camp 06 Model View Presenter Architecturebitburner93
 
Caliburn.micro
Caliburn.microCaliburn.micro
Caliburn.microbwullems
 
Ppt of Basic MVC Structure
Ppt of Basic MVC StructurePpt of Basic MVC Structure
Ppt of Basic MVC StructureDipika Wadhvani
 
Write Once, Run Everywhere - Ember.js Munich
Write Once, Run Everywhere - Ember.js MunichWrite Once, Run Everywhere - Ember.js Munich
Write Once, Run Everywhere - Ember.js MunichMike North
 
Structuring a Client-Side App
Structuring a Client-Side AppStructuring a Client-Side App
Structuring a Client-Side AppEirik Bakke
 
Catalyst 1 Introduction
Catalyst 1   IntroductionCatalyst 1   Introduction
Catalyst 1 IntroductionAran Deltac
 
Javascript from beginning to modern
Javascript from beginning to modernJavascript from beginning to modern
Javascript from beginning to modernPrem Narain
 
Mvvm in the real world tccc10
Mvvm in the real world   tccc10Mvvm in the real world   tccc10
Mvvm in the real world tccc10Bryan Anderson
 

Similar to My perspective on MVP and architecture discussions (20)

Training: MVVM Pattern
Training: MVVM PatternTraining: MVVM Pattern
Training: MVVM Pattern
 
Architectural Design Pattern: Android
Architectural Design Pattern: AndroidArchitectural Design Pattern: Android
Architectural Design Pattern: Android
 
jquery summit presentation for large scale javascript applications
jquery summit  presentation for large scale javascript applicationsjquery summit  presentation for large scale javascript applications
jquery summit presentation for large scale javascript applications
 
jQquerysummit - Large-scale JavaScript Application Architecture
jQquerysummit - Large-scale JavaScript Application Architecture jQquerysummit - Large-scale JavaScript Application Architecture
jQquerysummit - Large-scale JavaScript Application Architecture
 
From User Action to Framework Reaction
From User Action to Framework ReactionFrom User Action to Framework Reaction
From User Action to Framework Reaction
 
Windows Store Apps: Tips & Tricks
Windows Store Apps: Tips & TricksWindows Store Apps: Tips & Tricks
Windows Store Apps: Tips & Tricks
 
Skroutz Android MVP and Adapter Delegates presentation
Skroutz Android MVP and Adapter Delegates  presentationSkroutz Android MVP and Adapter Delegates  presentation
Skroutz Android MVP and Adapter Delegates presentation
 
Understanding angular js
Understanding angular jsUnderstanding angular js
Understanding angular js
 
MVVM ( Model View ViewModel )
MVVM ( Model View ViewModel )MVVM ( Model View ViewModel )
MVVM ( Model View ViewModel )
 
Reactive application using meteor
Reactive application using meteorReactive application using meteor
Reactive application using meteor
 
JavaScript Framework Smackdown
JavaScript Framework SmackdownJavaScript Framework Smackdown
JavaScript Framework Smackdown
 
Soft serve prism
Soft serve prismSoft serve prism
Soft serve prism
 
Code Camp 06 Model View Presenter Architecture
Code Camp 06   Model View Presenter ArchitectureCode Camp 06   Model View Presenter Architecture
Code Camp 06 Model View Presenter Architecture
 
Caliburn.micro
Caliburn.microCaliburn.micro
Caliburn.micro
 
Ppt of Basic MVC Structure
Ppt of Basic MVC StructurePpt of Basic MVC Structure
Ppt of Basic MVC Structure
 
Write Once, Run Everywhere - Ember.js Munich
Write Once, Run Everywhere - Ember.js MunichWrite Once, Run Everywhere - Ember.js Munich
Write Once, Run Everywhere - Ember.js Munich
 
Structuring a Client-Side App
Structuring a Client-Side AppStructuring a Client-Side App
Structuring a Client-Side App
 
Catalyst 1 Introduction
Catalyst 1   IntroductionCatalyst 1   Introduction
Catalyst 1 Introduction
 
Javascript from beginning to modern
Javascript from beginning to modernJavascript from beginning to modern
Javascript from beginning to modern
 
Mvvm in the real world tccc10
Mvvm in the real world   tccc10Mvvm in the real world   tccc10
Mvvm in the real world tccc10
 

More from Paul Blundell

In 10 mins a software crafting journey
In 10 mins a software crafting journeyIn 10 mins a software crafting journey
In 10 mins a software crafting journeyPaul Blundell
 
Android Things - Solid Foundations
Android Things - Solid FoundationsAndroid Things - Solid Foundations
Android Things - Solid FoundationsPaul Blundell
 
Java Patterns - Strategy
Java Patterns - StrategyJava Patterns - Strategy
Java Patterns - StrategyPaul Blundell
 
Survival of the Continuist
Survival of the ContinuistSurvival of the Continuist
Survival of the ContinuistPaul Blundell
 
Google I/O 2015 Android & Tech Announcements
Google I/O 2015 Android & Tech AnnouncementsGoogle I/O 2015 Android & Tech Announcements
Google I/O 2015 Android & Tech AnnouncementsPaul Blundell
 
Android Jam - Services & Notifications - Udacity Lesson 6
Android Jam - Services & Notifications - Udacity Lesson 6 Android Jam - Services & Notifications - Udacity Lesson 6
Android Jam - Services & Notifications - Udacity Lesson 6 Paul Blundell
 
Android Jam - Loaders - Udacity Lesson 4c
Android Jam - Loaders - Udacity Lesson 4cAndroid Jam - Loaders - Udacity Lesson 4c
Android Jam - Loaders - Udacity Lesson 4cPaul Blundell
 
Android Jam - ContentProviders - Udacity Lesson 4b
Android Jam - ContentProviders - Udacity Lesson 4bAndroid Jam - ContentProviders - Udacity Lesson 4b
Android Jam - ContentProviders - Udacity Lesson 4bPaul Blundell
 
Android Jam - Activity Lifecycle & Databases - Udacity Lesson 4a
Android Jam - Activity Lifecycle & Databases - Udacity Lesson 4aAndroid Jam - Activity Lifecycle & Databases - Udacity Lesson 4a
Android Jam - Activity Lifecycle & Databases - Udacity Lesson 4aPaul Blundell
 
Oh so you test? - A guide to testing on Android from Unit to Mutation
Oh so you test? - A guide to testing on Android from Unit to MutationOh so you test? - A guide to testing on Android from Unit to Mutation
Oh so you test? - A guide to testing on Android from Unit to MutationPaul Blundell
 
Jenkins project based authorization
Jenkins   project based authorizationJenkins   project based authorization
Jenkins project based authorizationPaul Blundell
 
Judge my gym - GymBabes Walkthrough
Judge my gym - GymBabes WalkthroughJudge my gym - GymBabes Walkthrough
Judge my gym - GymBabes WalkthroughPaul Blundell
 
Open Closed Principle kata
Open Closed Principle kataOpen Closed Principle kata
Open Closed Principle kataPaul Blundell
 

More from Paul Blundell (14)

In 10 mins a software crafting journey
In 10 mins a software crafting journeyIn 10 mins a software crafting journey
In 10 mins a software crafting journey
 
Android Things - Solid Foundations
Android Things - Solid FoundationsAndroid Things - Solid Foundations
Android Things - Solid Foundations
 
Java Patterns - Strategy
Java Patterns - StrategyJava Patterns - Strategy
Java Patterns - Strategy
 
Survival of the Continuist
Survival of the ContinuistSurvival of the Continuist
Survival of the Continuist
 
Google I/O 2015 Android & Tech Announcements
Google I/O 2015 Android & Tech AnnouncementsGoogle I/O 2015 Android & Tech Announcements
Google I/O 2015 Android & Tech Announcements
 
Android Jam - Services & Notifications - Udacity Lesson 6
Android Jam - Services & Notifications - Udacity Lesson 6 Android Jam - Services & Notifications - Udacity Lesson 6
Android Jam - Services & Notifications - Udacity Lesson 6
 
Android Jam - Loaders - Udacity Lesson 4c
Android Jam - Loaders - Udacity Lesson 4cAndroid Jam - Loaders - Udacity Lesson 4c
Android Jam - Loaders - Udacity Lesson 4c
 
Android Jam - ContentProviders - Udacity Lesson 4b
Android Jam - ContentProviders - Udacity Lesson 4bAndroid Jam - ContentProviders - Udacity Lesson 4b
Android Jam - ContentProviders - Udacity Lesson 4b
 
Android Jam - Activity Lifecycle & Databases - Udacity Lesson 4a
Android Jam - Activity Lifecycle & Databases - Udacity Lesson 4aAndroid Jam - Activity Lifecycle & Databases - Udacity Lesson 4a
Android Jam - Activity Lifecycle & Databases - Udacity Lesson 4a
 
Y U NO CRAFTSMAN
Y U NO CRAFTSMANY U NO CRAFTSMAN
Y U NO CRAFTSMAN
 
Oh so you test? - A guide to testing on Android from Unit to Mutation
Oh so you test? - A guide to testing on Android from Unit to MutationOh so you test? - A guide to testing on Android from Unit to Mutation
Oh so you test? - A guide to testing on Android from Unit to Mutation
 
Jenkins project based authorization
Jenkins   project based authorizationJenkins   project based authorization
Jenkins project based authorization
 
Judge my gym - GymBabes Walkthrough
Judge my gym - GymBabes WalkthroughJudge my gym - GymBabes Walkthrough
Judge my gym - GymBabes Walkthrough
 
Open Closed Principle kata
Open Closed Principle kataOpen Closed Principle kata
Open Closed Principle kata
 

Recently uploaded

+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...Health
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxComplianceQuest1
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsJhone kinadey
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfkalichargn70th171
 
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️anilsa9823
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...MyIntelliSource, Inc.
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comFatema Valibhai
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsAndolasoft Inc
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Steffen Staab
 
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AISyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AIABDERRAOUF MEHENNI
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfkalichargn70th171
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...ICS
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️Delhi Call girls
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdfWave PLM
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providermohitmore19
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerThousandEyes
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...MyIntelliSource, Inc.
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Modelsaagamshah0812
 

Recently uploaded (20)

+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docx
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
 
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS LiveVip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.com
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.js
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AISyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 

My perspective on MVP and architecture discussions

  • 1. Most Volatile Palaver Paul Blundell MVP examined holistically and subjectively
  • 2. My Vision Program - Highlight the variations - Talk about the conflictions - Define the naming - Example implementation - Emphasize important points - Get Pragmatic
  • 4. Oh you know MVP? http://www.wildcrest.com/Potel/Portfolio/mvp.pdf http://martinfowler.com/eaaDev/uiArchs.html https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93presenter https://msdn.microsoft.com/en-us/library/ff649571.aspx https://github.com/konmik/konmik.github.io/wiki/Introduction-to-Model-View-Presenter-on- Android http://c2.com/cgi/wiki?ModelViewPresenter http://www.gwtproject.org/articles/mvp- architecture.html https://www.youtube.com/watch?v=oiNfPjV72lg http://polymorphicpodcast.com/shows/mv-patterns/ https://developer.ibm.com/open/2015/10/22/model-view-presenter-mvp-for-ibm-ready- apps/ https://caster.io/episodes/episode-48-model-view-presenter-part-1-what-is-the- mvp-pattern/ http://fernandocejas.com/tag/model-view-presenter/ http://engineering.remind.com/android-code-that-scales/ http://antonioleiva.com/mvp-android/ http://geekswithblogs.net/nharrison/archive/2008/09/22/125373.aspx
  • 9. image I know MVP No I know MVP No. I know MVP
  • 10. Ivory Tower Syndrome - My MVP works so it should work everywhere - My MVP is the only possible architecture - Non collaboration - Lack of discussion of the details further reading: http://techdistrict.kirkk.com/2009/11/03/turtles-and-architecture/
  • 11. image
  • 12. image Indecent Exposure (42): This smell indicates the lack of what David Parnas so famously termed information hiding. The smell occurs when methods or classes that ought not to be visible to clients are publicly visible to them. Exposing such code means that clients know about code that is unimportant or only indirectly important. This contributes to the complexity of a design.
  • 13. image
  • 14. image
  • 15. image
  • 16. Here is another opinion! - Hangover Cures is an app I wrote back in 2012 - Two screens, a list of hangover cures, individual details - All code was in the Activity - Added new feature: Now has a comment stream, for people to leave comments about the cures.
  • 17. Model - Thin layer and a boundary to the rest of the architecture of the application (in my case ‘clean architecture’) - It’s not so much a domain model more of a ‘what can be done on this view’ api - Model contains the threading choices
  • 18. View - Passive View (not observing the model) - Gets information from ViewModel objects - The Activity as the View on Android - Treat Android Views like primitives and we always want to wrap them in a Domain View - Encapsulate native Android user interaction mechanisms and define Domain specific ones
  • 19. Presenter - Has knowledge of Model & View - Decides on action after user interaction - Observes the Model for changes - Decides how View is notified of Model changes - Doesn’t care about threading - Never uses primitive Views or native Listeners
  • 20. image
  • 21. Package Structure - Not necessary for MVP but a good bedrock to work from - Feature based - Clearly see the app’s concerns - Minimal learning curve
  • 22. Core / Mobile split MVP is a UI level architecture it is not an application architecture MVP belongs in the mobile module* The presenter can have Android imports, that’s ok For application wide architecture see: https://blog.8thlight.com/uncle-bob/2012/08/13/the-clean-architecture.html https://www.novoda.com/blog/hexawhat-architecture/
  • 23. Single Feature Example - Comments Only the Activity needs to be public First place to start [Feature]Mvp.java Classes shaded out not directly involved in MVP
  • 24. [Feature]Mvp.java class CommentsMvp { public interface Model extends Closeable { ... } public interface View { ... } public interface Presenter { ... } - The inner classes allow for great naming practices and improved readabilty. - This stops strange things like CommentsPresenterImpl implements CommentsPresenter - It also highlights the UI layers MVP pattern very obviously to the legacy developer
  • 25. CommentsMvp.java Implementers class CommentsModel implements CommentsMvp.Model { ... } public class CommentsActivityView extends AppCompatActivity implements CommentsMvp.View, CommentsStream.Listener { ... } class CommentsAnalyticsView implements CommentsMvp.View { ... } class CommentsPresenter implements CommentsMvp.Presenter, CommentsMvp.Model.AdvertRequestLoadedCallback, CommentsMvp.Model.UserLoadedCallback, CommentsMvp.Model.CommentSavedCallback, CommentsMvp.Model.CommentsLoadedCallback, CommentsMvp.Model.CommentUpdatedCallback { ... }
  • 26. CommentsMvp.Model public interface Model extends Closeable { void loadUser(UserLoadedCallback callback); void loadAdvertRequest(AdvertRequestLoadedCallback callback); void loadCommentsFor(Cure cure, SortOrder sortOrder, CommentsLoadedCallback callback); void saveComment(Cure.Id id, ViewComment comment, CommentSavedCallback callback); void saveVoteFor(Cure.Id id, ViewComment comment, Vote down, CommentUpdatedCallback callback); boolean canVoteOnCommentWith(Cure.Id cureId, Comment.Id commentId); interface CommentSavedCallback { void onSaved(ViewComment comment); } interface UserLoadedCallback { void onLoaded(String username); // TODO param can be an object containing also users profile pic } interface AdvertRequestLoadedCallback { void onLoaded(AdRequest advertRequest); } interface CommentsLoadedCallback { void onLoaded(List<ViewComment> comments); } interface CommentUpdatedCallback { void onUpdated(ViewComment comment); } } - callbacks here, can be any observing method - save/load is a simple pattern when you don’t have much client side state - knowledge of MVP domain objects - no knowledge of Android
  • 27. CommentsMvp.Model Implementor class CommentsModel implements CommentsMvp.Model { ... private final UseCaseModelAdapter modelAdapter; private final Log log; public CommentsModel(UseCaseModelAdapter modelAdapter, Log log) { this.modelAdapter = modelAdapter; this.log = log; } @Override public void loadAdvertRequest(final AdvertRequestLoadedCallback callback) { Subscription subscription = Observable.create(modelAdapter.getAdvertRequest()) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) ... } - Thin layer that then moves from MVP architecture to our back end of the app architecture - Injects the logger to allow dependency inversion - Controls asynchronicity as the model knows when its innards need threads
  • 28. CommentsMvp.Model Implementor class CommentsModel implements CommentsMvp.Model { ... private final UseCaseModelAdapter modelAdapter; private final Log log; public CommentsModel(UseCaseModelAdapter modelAdapter, Log log) { this.modelAdapter = modelAdapter; this.log = log; } @Override public void loadAdvertRequest(final AdvertRequestLoadedCallback callback) { Subscription subscription = Observable.create(modelAdapter.getAdvertRequest()) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) ... } - Thin layer that then moves from MVP architecture to our back end of the app architecture - Injects the logger to allow dependency inversion - Controls asynchronicity as the model knows when its innards need threads
  • 29. CommentsMvp.Model Implementor class CommentsModel implements CommentsMvp.Model { ... private final UseCaseModelAdapter modelAdapter; private final Log log; public CommentsModel(UseCaseModelAdapter modelAdapter, Log log) { this.modelAdapter = modelAdapter; this.log = log; } @Override public void loadAdvertRequest(final AdvertRequestLoadedCallback callback) { Subscription subscription = Observable.create(modelAdapter.getAdvertRequest()) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) ... } - Thin layer that then moves from MVP architecture to our back end of the app architecture - Injects the logger to allow dependency inversion - Controls asynchronicity as the model knows when its innards need threads
  • 30. CommentsMvp.View public interface View { void create(); void show(ViewCure cure); void show(String username); void show(AdRequest advertRequest); void show(List<ViewComment> comments); void showInteractionsFor(ViewComment comment); void update(ViewComment comment); void notifyAlreadyVoted(); } - All commanding methods, telling what to do - Use ViewModels to pass the data, here the naming I think lets it down a bit as ViewCure could be read incorrectly as “view the cure” rather than “the view cure model”
  • 31. CommentsMvp.Presenter public interface Presenter { void onCreate(ViewCure cure); void onCommented(String comment); void onSelected(ViewComment comment); void onSelectedVoteUp(ViewComment comment); void onSelectedVoteDown(ViewComment comment); void onSelectedFilterCommentsByMostPopularFirst(); void onSelectedFilterCommentByNewestFirst(); } - includes the lifecycle methods needed - includes methods that react to user interaction (i.e. methods you call inside a click listener) Want to investigate this for the lifecycle callbacks https://github.com/soundcloud/lightcycle
  • 32. CommentsMvp.Presenter Implementor class CommentsPresenter implements CommentsMvp.Presenter, CommentsMvp.Model.AdvertRequestLoadedCallback, CommentsMvp.Model.UserLoadedCallback, CommentsMvp.Model.CommentSavedCallback, CommentsMvp.Model.CommentsLoadedCallback, CommentsMvp.Model.CommentUpdatedCallback { private final CommentsMvp.Model model; private final CommentsMvp.View view; private String username; private ViewCure cure; … @Override public void onCreate(ViewCure cure) { this.cure = cure; view.create(); view.show(cure); model.loadAdvertRequest(this); model.loadUser(this); model.loadCommentsFor(cure, SortOrder.MOST_POPULAR_FIRST, this); } - observes the model - knows about the Model and the View - keeps state - onCreate it tells the view to create, populates the view and requests first load from the model
  • 33. CommentsMvp.Presenter Implementor class CommentsPresenter implements CommentsMvp.Presenter, CommentsMvp.Model.AdvertRequestLoadedCallback, CommentsMvp.Model.UserLoadedCallback, CommentsMvp.Model.CommentSavedCallback, CommentsMvp.Model.CommentsLoadedCallback, CommentsMvp.Model.CommentUpdatedCallback { private final CommentsMvp.Model model; private final CommentsMvp.View view; private String username; private ViewCure cure; … @Override public void onCreate(ViewCure cure) { this.cure = cure; view.create(); view.show(cure); model.loadAdvertRequest(this); model.loadUser(this); model.loadCommentsFor(cure, SortOrder.MOST_POPULAR_FIRST, this); } - observes the model - knows about the Model and the View - keeps state - tells the view to create, populates the view and requests first load from the model
  • 34. CommentsMvp.Presenter Implementor class CommentsPresenter implements CommentsMvp.Presenter, CommentsMvp.Model.AdvertRequestLoadedCallback, CommentsMvp.Model.UserLoadedCallback, CommentsMvp.Model.CommentSavedCallback, CommentsMvp.Model.CommentsLoadedCallback, CommentsMvp.Model.CommentUpdatedCallback { private final CommentsMvp.Model model; private final CommentsMvp.View view; private String username; private ViewCure cure; … @Override public void onCreate(ViewCure cure) { this.cure = cure; view.create(); view.show(cure); model.loadAdvertRequest(this); model.loadUser(this); model.loadCommentsFor(cure, SortOrder.MOST_POPULAR_FIRST, this); } - observes the model - knows about the Model and the View - keeps state - tells the view to create, populates the view and requests first load from the model
  • 35. CommentsMvp.Presenter Implementor class CommentsPresenter implements CommentsMvp.Presenter, CommentsMvp.Model.AdvertRequestLoadedCallback, CommentsMvp.Model.UserLoadedCallback, CommentsMvp.Model.CommentSavedCallback, CommentsMvp.Model.CommentsLoadedCallback, CommentsMvp.Model.CommentUpdatedCallback { private final CommentsMvp.Model model; private final CommentsMvp.View view; private String username; private ViewCure cure; … @Override public void onCreate(ViewCure cure) { this.cure = cure; view.create(); view.show(cure); model.loadAdvertRequest(this); model.loadUser(this); model.loadCommentsFor(cure, SortOrder.MOST_POPULAR_FIRST, this); } - observes the model - knows about the Model and the View - keeps state - tells the view to create, populates the view and requests first load from the model
  • 36. CommentsMvp.Presenter Implementor … @Override public void onSelectedFilterCommentByNewestFirst() { model.loadCommentsFor(cure, SortOrder.NEWEST_FIRST, this); } ... @Override public void onSaved(ViewComment comment) { view.update(comment); } ... - observes the View and decides what action to take on user interaction - observes the Model and decides how the view should be updated
  • 37. ViewComment A comment whos responsibilities lie in the view layer - vs a comment whos responsibilities lie in the domain layer - Meaning it can have view centric methods - getContentDescription, getFormattedDate - Immutable, only get never set - Could implement Parcelable
  • 38. CommentsAnalyticsView - Analytics tracking can be thought of as another view on the same presenter - Uses decorator pattern, could also be an observer pattern if you wanted more than two - Experimental ... class CommentsAnalyticsView implements CommentsMvp.View { ... public CommentsAnalyticsView(Tracker tracker, CommentsMvp.View view) { this.tracker = tracker; this.view = view; } @Override public void create() { tracker.setScreenName("Comments"); tracker.send(new HitBuilders.ScreenViewBuilder().build()); view.create(); } @Override public void show(Cure cure) { view.show(cure); } … @Override public void showInteractionsFor(ViewComment comment) { tracker.setScreenName("Interaction " + comment.getName()); tracker.send(new HitBuilders.ScreenViewBuilder().build()); view.showInteractionsFor(comment); } }
  • 39. Presenter Instantiation onCreate is in the Activity, newInstance is in the Presenter (or in any factory) @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); ViewCure cure = (ViewCure) getIntent().getSerializableExtra(EXTRA_CURE); HangoverCuresApplication dependencyProvider = (HangoverCuresApplication) getApplicationContext(); presenter = CommentsPresenter.newInstance(dependencyProvider, this); presenter.onCreate(cure); } public static CommentsMvp.Presenter newInstance(HangoverCuresApplication dependencyProvider, CommentsMvp.View view) { Log log = new AndroidLog(); FirebaseCommentRepository firebase = new FirebaseCommentRepository(); SharedPrefsVoteRepository sharedPrefsVoteRepository = SharedPrefsVoteRepository.newInstance(dependencyProvider.getApplicationContext()); CommentUseCase commentUseCase = new CommentUseCase(firebase); VotingUseCase votingUseCase = new VotingUseCase(sharedPrefsVoteRepository); UseCaseModelAdapter useCaseModelAdapter = new UseCaseModelAdapter(commentUseCase, votingUseCase); CommentsMvp.Model model = new CommentsModel(useCaseModelAdapter, log); Tracker tracker = dependencyProvider.getAnalyticsTracker(); return new CommentsPresenter(model, new CommentsAnalyticsView(tracker, view)); }
  • 40. Deliberate View language - Try to consider the domain of your UI (talk to the designers & business analysts) - Never end a custom view with the word view - Avoids communication issues & complications class CommentsStream extends LinearLayout { - When using primitive views consider naming them widgets public class DetailsActivityView extends AppCompatActivity implements DetailsMvp.View { private DetailsMvp.Presenter presenter; private TextView titleWidget; private TextView descriptionWidget; private RatingBar ratingBarWidget; private AdView advertWidget;
  • 41. image
  • 43. image
  • 44. image
  • 45. image
  • 47. image

Editor's Notes

  1. I've hacked an app together with MVP, I want to show my findings and opinions about the most over defined term for a pattern ever. https://play.google.com/store/apps/details?id=com.blundell.hangovercures.free
  2. So you know MVP?
  3. You have read all of these right
  4. And you can explain MVP with a simple diagram or sentence right
  5. Is this the answer?
  6. Seems like everybody else thinks they can as well, this is a google images search on the subject. Lots of diagrams all showing .. something different
  7. Recommended if you want to get into diagrams. I have another H&T on the C4 model coming soon!
  8. Everyone has their own opinion and choice of what the pattern is, because it’s so over defined. Everyone says MVP but nobody talks about the details. Yes it means you have a front end architecture with some separation, but it doesn’t mean two people would code it the same way. Change from “This should not be in the view” to “This View does not have a single responsibility anymore, who normally controls X?”
  9. Beware the ivory tower syndrome everyone thinks they are an architect and that their way is the right way http://techdistrict.kirkk.com/2009/11/03/turtles-and-architecture/
  10. Need to make sure when you are selecting patterns, you are refactoring for a reason In this book he doesn’t just say, here’s a cool pattern use it! He deliberately lays out the positives and the negatives
  11. Try to talk about code smells when you are tackling problems. “MVP will help with fixing the ‘hollywood principle’ here” Always give a reference when needed
  12. The MVP of choice doesn’t matter too much (on a single project) as long as the code is SOLID, crafted and at times pragmatic
  13. If we are going to synchronise and agree we need a common language and shared definitions
  14. Since this is a talk and not a discussion unfortunately you just have to sit there and listen
  15. This is not perfect! And I don’t want you to concentrate on the things that are missing, or what you can improve or add. Just listen about what is there, as I think it has some “clean”ness to it.
  16. I have already done a H&T that was recorded on the “core mobile divide” you should go watch
  17. The inner classes allow for great naming practices and readabilty. CommentsModel implements CommentsMvp.Model Activity implements CommentsMvp.View CommentsPresenter implements CommentsMvp.Presenter This stops strange things like CommentsPresenterImpl implements CommentsPresenter It also highlights the layer pattern very obviously to the legacy developer
  18. More on the AnalyticsView later
  19. Think of the Activity in two parts. It is the Mvp.View It’s onCreate is the static void main method that creates the MVP triad
  20. Serious Time
  21. It doesn’t matter who knows the most or what pattern we use.
  22. What matters is we work together
  23. And we get shit done
  24. We don’t need 1 architecture to bind them We need a multiple options, a bag full of tools with descriptions of benefits and drawbacks, then new projects can pick from the selection. The skill in architecture is knowing what you need for your use case and knowing how to apply that
  25. Architecture at every layer is important.