I have two generic classes which need each other to instantiate, is there an elegant way of doing that?
protocol Presentable {
/// Protocol for view
}
protocol Action {
/// Protocol for Presenter
}
class Presenter<T: Presentable> : Action {
/// Presenter looking for a class that implementing the Presentable protocol
}
class SomeViewController<T: Action> : Presentable {
/// SomeViewController looking for a class that implementing the Action protocol
}
SomeViewController needs Presenter to instantiate and Presenter needs SomeViewController to instantiate.
Try to instantiate one of them will cause an endless loop
let vc = SomeViewController<Presenter<SomeViewController>>... you get the idea.
Any ideas how to solve it?
The low-level answer is that you "tie the knot" by making a non-generic type that wraps or extends one of them, so that you can just have Presenter<VCPresentable>, where VCPresentable delegates to or extends SomeViewController<Presenter<VCPresentable>>.
The high-level answer is that this kind of cycle usually indicates a poorly composable design.
I'm not sure what kind of architecture you are trying to implement here. It seems something like Model View Presenter, but you seem to be getting confused about the responsibilities of the classes involved.
The basic architecture is :
Presenter
-- Model
---- Value
---- Selection
---- CommandSet
------ Commands
-- Interactors
-- View
A Presenter does not contain a ViewController, it actually is a ViewController.
The rules of separation of concerns dictate that :
The Presenter knows about its Model, its Interactors and its View.
The Model knows about its Value, its Selection and its CommandSet - it does not know about the Presenter
The Value, Selection and CommandSet know nothing about the Model, apart from the type of Value being modelled.
Interactors know nothing about the Presenter. They are, in effect, mini-presenters that know about both a Model and a View and are responsible for "translating" or mediating between the two.
The View knows nothing about the Presenter.
If a "child" needs to pass on knowledge of something to its "parent", it does it by delegation; in Swift, this is best done using delegating closures, which are implemented in the parent. IOW, the child says "I have changed" - it is up to the parent to listen for such notifications. That way, the child need know nothing about its parent, or even if it has a parent.
A typical chain works like this, starting with a list Value :
The View is something like a TableView
A User selects a row in the TableView
The Interactor for the TableView, held in the Presenter, reacts by telling the Model that the item corresponding to the row in the list should be added to its Selection
The Model adds the item to its Selection
The CommandSet is listening for changes in the Selection and it reacts to this addition by updating the state of all its Commands to be appropriate for the new Selection. e.g. the Delete command is enabled as long as the Selection contains one or more items; the InsertItem command is only enabled if the Selection contains one and only one item
When I talk about an interactor for a TableView, in the case of UITableView, this could be one of two objects, held within the Presenter :
one which implements UITableViewDelegate
one which implements UITableViewDataSource
Separating out these two protocols into individual Interactors means you don't cram one class with too much "stuff". Using Apple's UITableViewController means that all this functionality gets stuffed into one class and, instead of implementing the Model View Controller design pattern, on which Apple's frameworks are based, you end up implementing the Massive View Controller anti-pattern.
I have been successfully designing MVP frameworks in various languages for some 25 years and will be presenting a Swift version at iOSDevUK at the beginning of September.
Your generic problem is only a problem because you are not following the rules of separation of concerns
Thank you so much @Joanna_Carter for you detailed answer.
Seems like you know what you talking about, but I do myself have experienced in MVP and other architecture for some years now.
let me elaborate of what I'm trying to achieve and then it might make more sense.
The main idea is to add ability for inheritance in the MVP architecture.
So if for example I have a very basic setup like
BaseViewController which implement BaseViewProtocol
and BasePresenter which implement BasePresenterProtocol.
The flow is BaseViewController talking with BasePresenter via BasePresenterProtocol and BasePresenter talks back via BaseViewProtocol, this is actually the basic MVP flow and setup regardless if you use closures or not.
Now let's say I want to inherit from this base stuff and add functionality (let's also give a pass for the discussion if inheritance is the best way to do it or not, but we want to know if it's possible.).
So I have HomeViewController which suppose to inherit from BaseViewController and also HomePresenter which suppose to inherit from BasePresenter.
The problem is, BaseViewController already composite the presenter protocol and BasePresenter also having the view protocol.
When we inherit we getting these references, but we don't want them since we don't want to have a duplicate view and presenter reference.
So the solution is to use generics exactly as I showed above in my original question, SomeViewController expecting to have some presenter protocol and the Presenter expecting to have some View protocol.
Is that make sense?
I will also promise to see your MVP session, good luck with that .
If you are familiar with MVP, then you will know that there is no such thing as a ViewController in the MVP architecture.
What there is, is the concept of Interactors, that are held in the Presenter and that sit between the various views and subviews. The most they know is about a particular type of view and a particular type of value. There is no need at all for them to know about the Presenter.
Here's a few of the base types in my framework (targetted at iOS) :
open class Presenter<modelT, viewT : UIView> : UIResponder { … }
open class ViewPresenter : UIViewController { … }
public protocol AnyModel : class
{
var anyCommandSet: AnyCommandSet? { get }
}
open class Model<subjectT : Equatable> : NotifyPropertyChanged { … }
public protocol InteractorProtocol : class
{
var isActive: Bool { get }
func activate()
func deactivate()
func addNestedInteractor<interactorT : InteractorProtocol>(_ interactor: interactorT)
func removeNestedInteractor<interactorT : InteractorProtocol>(_ interactor: interactorT)
}
open class Interactor: NSObject, InteractorProtocol { … }
public protocol ViewInteractor
{
associatedtype ViewType : UIView
var view: ViewType! { get }
}
public class LabelInteractor : PropertyInteractor, ViewInteractor
{
@IBOutlet public var view: UILabel!
…
}
open class TableViewDataSourceInteractor<itemT : Equatable,
viewT : UITableViewCell & Reusable,
cellPresenterT : CellPresenter<itemT, viewT>> : NSObject, UITableViewDataSource { … }
open class TableViewDelegateInteractor<itemT : Equatable, cellT : CellGeometry, commandT : CommandProtocol> : NSObject, UITableViewDelegate
{
public weak var model: ListModel<itemT>?
public weak var view: UITableView?
…
}
As you can see, nowhere is there any need for any mutual references between a Presenter and its Interactors. In fact, the Interactors are written in a non-generic manner, in order that they can be used at designtime in storyboards.
In fact, any generic type, even if it inherits from NSObject, cannot be used with Interface Builder, which is why everything gets bound together with concrete types in typealiases and instantiated in code :
typealias ValueListModelTableViewDataSourceInteractor = TableViewDataSourceInteractor<ValueModel, ValueModelCell, ValueModelCellPresenter>
typealias ValueListModelTableViewDelegateInteractor = TableViewDelegateInteractor<ValueModel, ValueModelCell, ValueListModelCommandSet.Command>
public class ValueListModelPresenter: ViewPresenter
{
@IBOutlet weak var tableView: UITableView!
public var model: ValueListModel!
private var tableViewDataSourceInteractor: ValueListModelTableViewDataSourceInteractor!
private var tableViewDelegateInteractor: ValueListModelTableViewDelegateInteractor!
…
}
A Presenter does not contain a ViewController, it actually is a ViewController.
Wow. I have a very different take on MVP.
The way I’ve always done it (and seen it), the view controllers are part of the “view”. That’s where all the UIKit code goes. The “presenter” is a UIKit-independent mediator between the “view” and the “model”, interacts with the various services, has all the business logic, etc. They know absolutely nothing about UIKit (and can be slotted in to AppKit or whatever). And when I write my unit tests, I’m testing the exposed methods of the presenter, as that’s where all the logic is.
For me, the isolation of UIKit code/types within the “view” seems like an essential characteristic of MVP (or MVVM or whatever). It seems very unusual take to assert that the view controller is the presenter.
Dave Delong’s talk on A Better MVC - He dodges the question about what the “controller” of “MVC” really is, but he also defines the view controller as being part of the “view” of MVC, not a real controller.
Indeed the Presenter is an abstract concept; thanks for pointing that out. So abstract, it only exists as a protocol.
public protocol PresenterProtocol
{
associatedtype ViewType
associatedtype ModelType : ModelProtocol
var view: ViewType { get }
var model: ModelType { get set }
init(with view: ViewType, for model: ModelType)
func updateView()
}
However, it very soon loses it "abstractness" because, in order to do anything sensible with a view, it needs to know about the view's type, in order to respond to user interactions on the View.
Then comes the problem, due to the way that Interface Builder doesn't play nicely with generic types, that any UIKit types, whether they be views or controllers, cannot conveniently inherit from generic base (abstract) classes.
As to whether a Presenter is a UIViewController or it has a UIViewController, seems somewhat irrelevant to me; either way, from then on, it is already bound to UIKit because it would have to know about UIViewController. Which is why I might as well have a base Presenter implementation, tied in to UIKit, by inheriting from UIViewController. OR would you abstract out a ViewController protocol, which knows nothing about UIKit - which is pretty much what Presenter is.
Two of the only other types that the Presenter protocol knows about are also totally abstract
public protocol ModelProtocol
{
associatedtype SubjectType
var subject: SubjectType { get set }
init(subject: SubjectType)
}
public protocol InteractorProtocol : class
{
var isActive: Bool { get }
func activate()
func deactivate()
func addNestedInteractor<interactorT : InteractorProtocol>(_ interactor: interactorT)
func removeNestedInteractor<interactorT : InteractorProtocol>(_ interactor: interactorT)
}
When it comes to the View, it is really so abstract that just about all you can do at a protocol level is to define an empty ViewProtocol { } ; which is hardly worth the inclusion, unless we are being ultra-purist.
Of course, you could go on to define protocols for the interactions expected from various types of view but, as those can be so varied, depending on the contents of a concrete view, it is hard to imagine how useful such an extra layer of abstraction would be at the base Presenter protocol level.
The concept of Interactors would, however, benefit from requiring a widget (subview of the Presenter's view) to implement an abstract "delegate" protocol that defines the interactions it "publishes"; thus hiding the type of widget it is managing.
Therefore, I only limit the view's type to a particular widget library in a base presenter class:
open class UIKitPresenter<modelT, viewT : UIView> : UIResponder, PresenterProtocol
{
public let view: viewT
public var model: modelT
{
didSet
{
updateView()
}
}
public required init(with view: viewT, for model: modelT)
{
self.view = view
self.model = model
super.init()
}
open func updateView() { }
}
I think, a lot of times when people compare MVC and MVP, they miss out on the full picture. They tend only to see three parts to the 'pattern", just with a different name (Presenter instead of Controller.
In fact, the Presenter is also meant to contain Interactors so, as you mention, you could justify making the view controller a ViewInteractor. Then the ViewInteractor for the overall View should contain nested Interactors, one for each widget present in the main view, to link those widgets to the properties of the Model being represented.
In this sense, you could say that a UIViewController is actually a ViewInteractor but, especially with UIKit, moving from one "presentation" to another usually involves UIStoryboardSegue, simply because it is easier than writing a whole load of presenter management code (which I agree with in principle), just to be "pure"
In the end, after many years of implementing the principles of MVP for real world development teams, in various IDEs, I have ended up having to take a pragmatic approach that doesn't impose too much complexity on those who are left to maintain and grow an application based on these design principles once I have left, some of whom already think that MVC really means Massive View Controller and "why bother with all this purist stuff?"
Hey, I’m all for pragmatism. As long as you’ve follow the single responsibility principle and write manageable and testable code, I’m happy. The terms (whether the “controller” is a “presenter”, “view model”, “coordinator”, or whatever) don’t matter much to me. As Ben Sandofsky said, you can call it the “cupcake” model if you want.
But it is worth noting that if you’re going to use the term “MVP” and if you’re going to include the view controller under the umbrella of the “presenter” (and if I’ve misunderstood you, I apologize), one should acknowledge that this is a somewhat contrarian position, that most iOS MVP/MVVM discussions keep it firmly within the domain of the “view”. And we don’t do this for any ivory-tower, “purist” intentions, but (speaking for myself, at least) rather, from because this becomes a clear line of demarcation, where we can now fully unit test in complete isolation of UI. That’s one of my primary objectives.
But, don’t characterize me as a purist. Lol. I hate when code goes off the deep end with two many levels of abstraction. (I love that cautionary quote, to paraphrase, that says “there is no problem in computer science that another level of indirection can’t solve, except too many levels of indirection.”) Pragmatism in our code is good.
Hi Robert. I am not trying to characterise you as anything, except a great help in talking things through.
I am rethinking a lot of assumptions as our conversation is progressing; permit me to discuss further something you said:
After much research, experimentation and internal mutterings, I have concluded (for the moment) that it is impossible to build a concrete Presenter without knowledge of the UI framework it is going to support.
Yes, in some ways it can be isolated but there will always have to be some point of contact. Take the idea of a "neutral" Presenter holding a reference to a view controller:
In the MVP framework paper paper that I have based my design on, it talks about the Presenter holding an Interactor. Now, Interactors can be nested and one could reasonably expect that the top level Interactor would be a UIViewController, since both concepts act as intermediaries between a view and the model it represents.
This top level Interactor would then hold a list of "property" interactors that mediate between subviews (like text fields, labels, table views, etc). In fact, I designed my PropertyInteractor hierarchy in a way that they can be placed on the Interface Builder design surface and connected visually rather than in code.
Likewise with the concept of CommandInteractors, these too would be held in the "ViewInteractor" (UIViewController) and connected at design time to buttons, menus, etc.
The main difference, at the moment, with my design, is that I chose, for the sake of expediency, to mix the concepts of Presenter and UIViewController, mainly because it made life easier
However, having looked at the concept of Coordinators in Paul Hudson's How to use the coordinator pattern in iOS apps article and Soroush Khanlou's Migrating To Coordinators articles, I am going to start experimenting with separating out the UIViewController stuff into the concept of a "view interactor".
The one thing I would point out is that the concept of Coordinators, as described in these articles, does seem to involve a tight coupling with UIKit, as it requires the inclusion of a UINavigationController in each Coordinator.
So, even with this separation, we still end up with a close tie-in between a Coordinator (which I would want to call a Presenter in my terminology) and a specific view framework.
It has been my experience that the abstract concept of a Presenter has to be made concrete, either by inheritance or implementation of a protocol, for each view framework we need to implement. The best we can do is minimise the tightness of that binding.
As for testing, in the Mike Potel article, you will see that the Model contains the concepts of Selection and CommandSet, thus encapsulating the entire business logic away from, even, the View Interactor.
So, having prepared my talk for iOSDevUK in September, your intervention is making me want to see if I can include some of this into it; or should I just go out for a walk on the beach?
Well, I've done it! I've mixed in the Coordinator pattern with the Chain of Responsibilty pattern and now gat a ViewPresenter that holds a ViewInteractor (aka a thinly veiled UIViewController)
It really is a work of art, if I may say so myself
@Joanna_Carter The article you are referring to is from 1996 and not necessary adapt for today MVP architecture in mobile.
Translating it exactly like it represented in the article is redundant IMO and maybe not even practical.
You basically can continue developing as you want, but this is not the industry MVP we all familiar with.
I’m actually curious to see your approach in a more concrete example, perhaps a login screen or something similar.
For how’s the industry working today is, the ViewController is completely abstracted from the Presenter and the Presenter has no idea about the ViewController.
They talk with each other via protocols, simple as that.
You have no UIKit in the Presenter class and all the logic is done there.
We usually inject services to the Presenter (Data, Network etc.) and that way we make it a testable piece.
It’s also pretty easy to no include UIKit the in the presenter itself, can you be more practical and give example for how it’s block you?
I suggest you look on VIPER which is kinda more close to what you want.
It’s add two extra layers which called Interactor and wireframe/router, and by that the presenter have different role, but that’s another story.
I started writing MVP frameworks, in Delphi, in 2001. I used the Taligent design then, and since, in C#, Objective-C and, now, in Swift.
I find it far from being redundant, mainly because it separates out all the business logic into the Model, including the concepts of Selection and Commands. This means that the business logic can be completely tested outside of any UI.
The Model contains a Value (business object), which can be tested on its own; then integrated into Model, alongside the other two components.
The Selection provides a way of testing the user selecting items, in a list model, from the UI; once again with no reference to any UI framework.
The CommandSet contains one Command for every anticipated user interaction, which can then be tested in code, without having to provide UI code with buttons and/or menu items to trigger them.
Once the Model, along with its Selection and Commands, have been tested, there really is nothing much left, in the way of business logic, to put in the Presenter.
The only situation that might require any code is if a Presenter in a "stack" needs to notify its "parent" of something; which, of course, can be implemented by creating a delegate protocol to relay such information back.
I have already spent a lot of time constructing an example for iOSDevUK and really can't spare the time to create yet another example. I may publish some articles on my blog after the conference.
Indeed. As I mentioned in my previous post, I have now separated out the ViewInteractor (ViewController) from the Presenter.
I could be interested to see how you have made that work.
I would question why you would put "services" in the Presenter. As the name suggests, it is there to present data, not be the kind of dumping ground for anything and everything that UIViewController has become. I use several "frameworks" apart from MVP to provide these services, independent of the Presenter, so that they can be tested in isolation. For example, outside of my MVP framework, I have a singleton DataProvider that can be implemented in any number of different ways, such as an SQL database, an OPF (Object Persistence Framework), XML files, CoreData, etc.
Networking also should be handled apart from presentation; I would put it in a similar singleton to the DataProvider.
This way, the Presenter actually becomes an extremely lightweight structure where, especially with UIKit, it only holds a reference to the Model and a ViewInteractor; the View being managed by ViewInteractor/ViewController, read from a storyboard or XIB.
In fact, in separating out the ViewInteractor/ViewController from the Presenter, I have found that, as soon as the ViewInteractor is pushed onto the UINavigationController, the Presenter is released from memory and would only be retained if it were a delegate for the Interactor and the object that created the Presenter were also a delegate for it.
Since there is usually no non-UI code in the Presenter, I can create ultra-lightweight classes that implement a very simple common protocol but that are adapted to the UI framework they are going to present the object in.
public class ValueModelPresenter : AnyViewPresenter
{
public var viewInteractor: ValueModelViewInteractor? // UIKit based
public var model: ValueModel?
}
The Model can either be passed to the ViewInteractor or the Interactor can "talk back" to it via a delegate Protocol.
I believe most of the "competing" designs don't cleanly separate out the Model/Selection/CommandSet triad from the Presenter, neither do they rely on the concept of things like PropertyInteractors to separate out mediation between textfields and other controls from the properties of the Model.
Not wishing to be at all arrogant, but I have found the Taligent design to be equally at home nowadays as it has been since its inception; personally, I see no need to reinvent the wheel.
If you can get to iOSDevUK, it would be good to exchange notes.
Mohen didn’t say “put”. He said “inject”.
Unfortunately, all of this comes across as a dogmatic defense of one particular, random MVP article, without acknowledgement of how this differs from practical, modern, MVP implementations. If you’re going to make this the centerpiece of your presentation, you might want to acknowledge how most of us do MVP, how your approach differs, and what its pros and cons are.
And please don’t misunderstand me: while I disagree with many of your assertions, I’m not criticizing your approach. I’m just saying that when you give your presentation, you might want to articulate how your approach differs (and it does) from established, well-designed MVP implementations. And if you assume that your audience is less experienced than you, or contrast your implementation to straw man alternatives, that undermines your case.
I'm really not sure what the difference is; in the end, the Presenter ends up knowing about the "service".
I would hardly call that article random; it happens to be one of the earliest documents on the subject, written by Mike Potel of Taligent. To quote Wikipedia:
The model-view-presenter software pattern originated in the early 1990s at Taligent, a joint venture of Apple, IBM, and Hewlett-Packard.[2] MVP is the underlying programming model for application development in Taligent's C++-based CommonPoint environment. The pattern was later migrated by Taligent to Java and popularized in a paper by Taligent CTO Mike Potel.[3]
And I'm not dogmatically defending it, I'm simply saying that, thus far, I haven't found anything as clean and well defined.
I certainly wouldn't claim to be the universal source of truth on MVP (or anything else actually) but I do know that I have implemented Mike Potel's "pattern" in some pretty big projects, for some very satisfied clients.
Other "versions"
I have looked at most of the "modern" versions that are around on the web and, personally, find them somewhat confusing to implement - possibly due to the different definitions used for the word "Presenter" and the uses to which that concept is put.
I have found examples where there seems to be mutual references between a Presenter and an Interactor. Some texts state that business logic should reside in the Presenter. Viper would place the business logic in the Interactor, placing view logic in the Presenter. And lots more inconsistencies in vocabulary and functionality.
In all of these variants, not one mention of the Model, its encapsulation and testability. Which is where my design, based on Mike Potel's, comes in.
If I may, here's a slide from my upcoming presentation:
As I have mentioned before, all business logic resides in the Model, including the concept of a Selection (for lists models) and a CommandSet, which contains discrete actions that can be executed against the subject of the Model.
In a single object presentation, PropertyInteractors are "bindings" between a property of the Model's subject and a UI control; when the property is changed, the binding is notified and it, in turn, notifies the UI control. The control is totally unaware of the overall subject type, in fact, only knowing that it has to display a representation of a value. It is the PropertyInteractor's job to translate the value type into (e.g. a string) and to validate and translate the string from the control into an appropriate type for the value of the property. These PropertyInteractors are tiny objects that do this one job, nothing more; all they know is the name of the property and the subject, just enough to allow it to get/set the value.
Likewise CommandInteractors are bindings between a visual control like a button or a menu item. When a Command is enabled or disabled by the business logic in the Model, the binding notifies the control and either enables or disables it. The binding also acts as a target for the control's "action" and simply calls execute() on the associated Command; the binding only knows the name of the Command and the Model that contains it.
The box marked "Other Interactors" includes such things as: a ListViewDataSourceInteractor, a ListViewDelegateInteractor and a ListModelCommandSetInteractor (which is responsible for updating a ListView before, during or after a Command's execution), etc.
Yes, I use the UIViewController class as a basis for most complex ViewPresenters, mainly because it already holds a reference to a View, but I also implement the concept of Presenter, independent of UIViewController, to wrap a UITableViewCell, thus removing business logic from an, otherwise, totally visual class.
Why do I stick with this pattern? Because it is simple to explain to a development team and, once the framework is written, implementing it in a domain and UI specific way is really simple and lightweight.
My clients usually start by writing the business model, without a single UI control in sight, and test it exhaustively, including every possible combination of Selection and enabled/disabled Commands.
If they don't already have the MVP framework, then most of that can be written in generic terms, only leaning towards a particular UI framework from the Interactors outwards.
I believe there used to be an advert that said something like "when you've tried the rest, settle on the best".
That's not dogmatism, that's simply 25+ years of experience
P.S. I love a good discussion and I teach my clients to expect to argue back and forth to find the best solution; too many bad designs have resulted from a client accepting everything the consultant says, without feeling that they can argue back.