 Alright. I really don't like talking about things like that. Alright, here we go. A clean, hierarchical, model, view, controller, pattern for Android. Also dependency injection and Kotlin and basically too much stuff for a single talk and also terrible, terrible title. Welcome to progress. Alright. I'll start with a warning. There's too much stuff in here for a single talk. This is a project that I was playing with for over like a week and I basically started testing out too many new things at once and they all got embedded in here. I was hoping to be able to clean it up a bit, but it wasn't the case. So, warning number two. This may contain a lot of Android stuff but not everyone in the audience is so familiar with it. So, any questions, please ask. But the general pattern here is actually applicable to iOS or automobile devices and probably beyond that as well. Maming is hard. Yes. I went with hierarchical, model, view, controller because after going through a gazillion variations on NBC, this kind of fits. Apparently this is a copy of something that was called pack which is presenter abstraction something and never mind. Let's not focus too much on the names of stuff but I'm open to suggestions on better naming for a lot of what comes next. So, to start, this is a to-do app to frontend for the standard to-do application and I'll go through some of the tools and frameworks I used and especially the ones that will be mentioned and are more or less important later on. Also, to get some of the terminology out of the way. All right. First, I use Kotlin to write this app. So, I might ask why did I choose to use Kotlin? I answer, why are you still using Java? There's no point in doing this. I don't think I need to sell Kotlin itself. You can use it side-by-side with any other Java class in your project. Just take one of your classes, convert to Kotlin and you can figure out the rest. That said, if you do have questions about the code that isn't Kotlin, you just ask me, save us the Android stuff. Dagger 2. Dagger is dependency injection framework. Well, who here is not familiar with dependency injection? All right. Okay. So, I'll go over a lot more in detail about this later because it's an important part of having a clean project and all that stuff. But in terms of terminology, if you see inject along the code, especially it's an annotation, it means that whatever that field is, whatever that object is, it's going to appear by magic. Somebody is going to put it there. It's not really magic. It's completely deterministic, which is important. It's an important detail. Components are what dagger uses to provide dependencies. The important scopes will go more in detail about this. There's also a dagger thing. We're using reactive extensions. RxJava, in particular, because there's variations for many other languages. We're also using RxJava. In Android, there's a bunch of different libraries on this line. RxJava basically provides with asynchronous and event-based programming. The idea is that you have observables that emit events. This might be something like I started a network call and it comes back with a result and that gets emitted. This could be events like I click on a button and that gets emitted as an event. There are also subscribers, which is basically the action you'll take on the observable when an event gets emitted. A short example, because we've seen things like this a lot. Over here we have a method called notify near home. It takes in this parameter an observable of locations. This means that this locations variable will be or object will be emitting locations. It could be that I'm walking around with my phone, you know, I have the GPS on. Every time there's a switch and change the framework says, hey, here's a new location, here's where you are now. RxJava lets you do things like take this location, map it, figure out am I near my home? Is it near home? I'll map it to a boolean to the falls. I'd say only the changes from true to false, etc. I throttle first, which is kind of like debalancing and eventually I subscribe and say, whenever this happens, notify your near home. RxJava has a steep birthing curve, I'm not going to lie, but once you get used to it and to the names of some of the functions, actually that's you. Yes, nice laser pointer. It lets you do things that are succinct in language, especially for UI stuff that can help a lot. I'm using conductor. This is probably the least important thing in this talk. I mention it because people are familiar with Android. This will look very strange to them. Conductor is a small framework that kind of aims to replace fragments in Android. Android has these things that are called activities, which is basically a screen on your phone and fragments which are sections of views and they're both kind of plagued with very difficult lifecycle issues. Conductor is a framework that tries to abstract that out. View-based Android applications, they provide controllers which sit on a view on your view tree, and they control the subtree of that. There's also routers which basically are in charge of moving from one controller to the next or from one screen to the next on the application. Okay, the motivation for this whole thing. I've worked so far in seeing a fair number of Android projects. A lot of them are horror stories. A lot of them are not, but all in all they tend to end up being very messy. This happens actually with just about any kind of programming. You end up getting very messy stuff. But when you have something like a mobile project and your messiness starts affecting the performance of your app, that's particularly important when you have to run your app on a low-power device. These are the kind of places where you actually want to have very good control of what your application is doing. Also, testing apps on a mobile device is extremely hard, much more than other frameworks. A lot of the time because it's very tightly coupled with the mobile framework itself. In the case of Android, you run tests, you can run tests on the device so you have access to the full Android operating system. But if you really want to do fast unit tests, which is the only kind of test that you write over time because the other ones take too long, then you need to do things without having the framework. And mocking the framework out is not easy, especially because Android has these God objects, like the context, which does absolutely everything. And if your object has a dependency on a context, yeah, you're not going to be doing unit tests anytime soon. Integration tests are possible, where you just run the whole test on the device, where you open views and you click on things, but they tend to be slow and reliable, and at the end of the day it's not good testing. So, recently I worked on a project that was using this framework called PIRMBC, which attempts to separate these things properly. After this, I concluded that PIRMBC is a little bit outdated at this point. The Java implementation is not that good, but the idea behind it was very good. I tried to create something more modern using all these other tools. So, I started, I opened Android Studio and said, give me a new project, make it a master detail flow, because it's a to-do app, you're not going to have a list of to-dos, and I can see the details, it seems like it's not. And Android Studio gave me this. It's called to-do front-end, it doesn't have to do yet, but this is basically the vanilla app with a very, very minimal change of like one line of code here. It's a list in an activity that is called to-do list activity, and to be honest, the whole structure of this template project is a little bit weird, but let's start looking at what's going on here in the onCreate. So, onCreate, for those who don't know, is the callback the Android gives you to set up your view hierarchy, especially when the activity means set up the whole screen. Put the views there, and more often than not, do some bindings. At the beginning here, we say set content view, this is basically saying, I'm going to choose this view layout. It's in a different file, it doesn't matter. It gives me all these things. There's a mention of setting up the toolbar, which is putting the title up here. It looks weird, but that's just how it is. At the bottom, there's something more interesting. It says find view by ID, and it says if I have, basically it's saying, if I have this to-do detail container, then I'm working with a two pane application. This is because this template, when you run it on the tablet, is supposed to show the list on one side, and the details on another. This is like the master flow, master detail flow thing. So, this is actually not an usual pattern. Android has some smarts behind that, it'll, layouts can be overloaded to show different things on different cases. So, let's see. What's next? In middle here, however, we're setting up the floating action button. There's nothing too weird looking here. In fact, this is something that you'll see in almost any Android app. Don't pick a button, don't find it, and don't attach an un-click listener. So, one thing to observe here, even though it's very common, is if I want to unit test this activity, what's the next thing I need to do? Let's say I want to unit test, what happens when I click on the floating action button down here? You're dependency on a snack bar. Yes, I do. I have a dependency on a snack bar. It's worse than that. This is a static method call. There's not even a dependency being passed in, there's not even like an object that I can mock out. If I were to try to mock this in a test, I would have to do something like power mock. Right? Which, you know, does some really weird stuff with behind the scenes. And hey look, it's chained, it's make and then set action, and goodness. Even if I did go through the trouble of setting this up with a power mock, this is happening in middle of my onCreate. So basically, to set this binding, I need to make sure that everything on onCreate can be run. So I need to make sure that findViewById for the toolbar, for example, or for this to-do list also works. That findViewById, by the way, is a method on the activity. So to unitize the activity, I need to spy on the activity, and yeah. So... Exactly. If I were, you know, I could try to like get this, this, like just run it somehow on an actual like Android unit, not on Java, and then get the view and say, hey, you know, let me see the type, but onCreateListener, you attach. Except that get onCreateListener is not a method onView. You can only set them. You cannot retrieve them later. You could run instrumentation test. Starts up the whole thing, clicks the fab, and then I can look for something that looks like a snack bar that appears on screen. Yeah. Imagine if you have like a network dependency on this. This is also going to start hitting the network. Yeah, never mind. Next, the RecyclerView. RecyclerView is a fancy term for a list view in Android. That's it. Again, nothing too weird here. There's a circle. It's kind of strange, but never mind. Then says, RecyclerView setAdapter. Adapter is basically the data source for this view in Android. It's this one. We're creating a new adapter and passing it this dummy content items. Once again, this is not injected. So I have no way of knocking this out of the test. This adapter is actually an inner class that's further down this file. This inner class takes care of, for example, each one of these rows individually. So here, on BuyingViewHolder, ViewHolder is just the name of one of these rows. It sets some values, but it also has an un-click list now because when you click on it, it does something, right? Yeah. Now, if you thought that one was interesting, let's look at this. If you click on one of these rows, the adapter set of listeners says, if you are too pain, well, let's say it's not because we're not, so let's just stick down here. If it's not too pain, like in this case, we're going to get a context from the view of the plot object. They're going to create an intent, which is basically saying, I want to go to a new screen and then we're going to start that new activity up here. If you are too pain, there's something that looks even more complicated, but it's basically similar. It's just that it's using a fragment instead. Okay. This view has code that's directly controlling the flow of your application. It's not telling the activity, for example, hey, move to an activity. It's like deliberately embedding the view. It knows about things that it shouldn't know about. Yeah. For example, it knows if this application is configured as a too pain or a single pain application. The only reason it knows about this is because it's an inner class of the activity. Again, if you wanted to call this out, now you need to know. You can't. It knows two ways of doing this thing. It knows how to build the arguments for this fragment and for this activity. It knows a method like new activity and has the argument. It's basically putting extras and treating them like a map. It knows what the keys for these arguments are. If I were to... I don't even know how it starts in the testings. From now on, in this situation, I'm going to make cut. Yeah. Now, code like this is fine in many cases when you're sketching things out. When you want to pass a code snippet to somebody to show somebody. But giving a developer this as their template for a new application is just setting bad precedence. So, let's start cleaning this stuff up. There's going to be two things that we're going to do for this. One is dependency injection and the other is having a model of view controller or a more linear separation of concerns. We'll get back to that second part later. We're going to start with dependency injection. What is dependency injection? You can probably have a full two-hour talk on dependency injection alone. I'm going to attempt to summarize this. Here we have a class. It's a whole notifyer. It knows how to do something. It knows how to notify when you're near home. It needs something to do that. It needs like a location source. Right? And in this case, he knows how to get what he needs. Right? He's saying, I just go to the location source and get the instance that exists. So, I would say that in a nutshell, dependency injection is getting rid of .3. Now we pass in what he needs to do the job. It's kind of as simple as that. Now, why? Dependency injection pushes you to keep things separate. It keeps you a bit more honest about saying this is what this object should be doing and it's not about doing other things. Once you have a lot of those location get instance, they usually end up covered around your code. When you have a bunch of variables that tell you, like, these are my dependencies, well, it's much clearer to see that. It also lets you know when your class has, you know, 20 dependencies. It's like, maybe something is wrong with this class. Maybe this needs to be broken down. And all these things are easier to see once you can clearly visualize what I need to do my job. Right? It allows you also to do some things like inject an interface that provides, you know, the actual implementation without having to know who exactly is doing the implementation. And just say what? What type of object are you using instead? It's... Yeah, it actually simplifies your code because, you know, you say how to get dependencies, that's no longer there. And the case that we saw just now, that was like a very trivial change. But there are cases in which, you know, having whoever is providing the dependency depends on the state of your application or other configurations and taking that away from this object simplifies code, provides easier refactoring with the caveat that once you're using a framework to do your dependency injection, it becomes that simple to add new dependencies and you don't have to change 20 call sites, you know, to say, hey, this guy now needs one of those added in. That was interesting. Unit testing. Now we're getting to the really nice stuff. When you have an object that takes a dependency, in a unit test you can provide a mock for that dependency very cleanly. For integration tests, is this interesting? In a mobile application, if your mobile app, for example, hits network, you know, you might not want to, you know, be spamming a server or having to deal with the latency of the server every time you're writing your test. You can have an alternate implementation of whatever the data source, for example, of your app is and make it not hit the network, make it return some kind of responses. And the rest of your code doesn't need to know that you're providing a different implementation. And in the case of Android in particular, you know, getting rid of dependencies, direct dependencies to the framework stuff, like if you depend on stuff and that. System service or a lot of static calls because there's a possibility of those or a context, you can wrap those up. Dagger 2 is the framework we're using for this. It's a work of Dagger, the original one. The original Dagger, I mean, from Square is actually still incredibly popular. I think it's probably used a lot more than Dagger 2. What's interesting about Dagger 2 in particular is that all its work is done in an annotation pre-processors and cogeneration. There's absolutely no reflection used which a lot of dependency injection frameworks actually do use. In Android this is important because reflection is costly and especially an older version older devices or lower power devices they make things very slow. Dagger also can handle nested dependency scopes which is very useful. A dependency scope for example, could be in this case like there's a dependency, there's a component a Dagger component that's providing things that are at the application level across the whole application like for Android an application object which is a singleton so you actually have one. An HTTP client. It's also a singleton, a client to an API. You can also have things that are not scoped like in HTTP requests. You get a new one of these that are able to provide new instances every time you ask for them. This is already very good sometimes you some dependencies require additional state or additional setup that you won't always have access to. So for example in an app where you can log in once you've logged in you have access to a user object you might provide new things like now maybe you can instantiate a friend's manager which is associated with the user or you can create authenticated requests to the API which you didn't so the idea of the scopes is this you can have different scopes of dependencies depending on how what additional objects you're able to provide the dependency to the dependency injection in Dagger these are also components and without further ado these are the scopes or the components that are going to be using the application there's a singleton component in this case the data source for example like the list of to-dos is actually provided here there is an activity component which you only will have available once you actually have a UI if I had this thing running in the background for example I would not be able to create an active component because I won't have a UI this one provides navigation for example now that I'm at the stubble and controller components controllers are for a specific area of the screen like one of the views in this case the controller for this particular view could provide the adapter for this data so now we have that set up finally we move into this hierarchical model view controller of sorts again I'm not going to get too hung up on the name the controller is just as before we were talking about controller is something that lives on a view node or part of your view hierarchy and just controls that node it will instantiate its view tree and it's then seems actually it will have access to model and a lot of other things that are needed for business logic basically now there's a pre-center which is basically wrapping around the view and simplifies the interface to it especially if you have a lot of nested views and trees getting or making changes to inner ones might be pretty difficult so the pre-center is basically an interface that runs around it just shows a simple API and we have a mediator which is in charge of the business logic and basically this guy binds to the view pre-center now this is all very abstract and it's hierarchical because you can have these guys nested because you can have controllers in different parts of each view tree nevermind it's a little bit easier to see so for this screen this is the detail view this is the mediator for the detail view he's in charge of tying together basically getting whatever data you need and tying it together with the view stuff he has the interfaces for means of navigating the navigator and he defines the interface as a pre-center he knows what controls it needs on the view and what events it needs from the view to actually do its job so it defines this interface and he defines the navigator because he knows when he should be moving to a different part what is a navigation event sorry he gets by injection a data source basically in this case he takes an identifier for it to do and once he gets the item he sets the title on the view which is up there the details for it to do and on clicks on this floating action button he is going to go to edit this to do so this little bit here reads very thinly and for purposes of testing this guy needs a navigator interface needs a pre-center and a string mocking these guys out is extremely simple providing a fully mocked implementation of this is really simple as well observables are not tied to particular sources they just emit events this is the pre-center for this view so he wraps around the actual view stuff and there is a tool bar a detailed view there is a fab all this is abstracted out of the way when the mediator wants to set title text behind the scenes we go and set the title on the application bar which is up here the detailed text is more simple it's just like a text view we are going to set the text directly on it the clicks observable are clicks the floating action button come from here clicks basically just emit every single click that happens on it and I'm just going to emit these things until the view gets detached so we don't get weird state the way I'm seeing this is that the presenter is giving you an abstraction layer one higher than the android view layer so that if you want to test the interactions with your view you can test at that level of abstraction you don't have to worry about bind view r by id you don't have to find those just like the mediator I could do it with a pure job I'm going to test I could actually create an android view for the presenter for example in which it's slower make clicks on objects and see if these events happen or as expected and finally there is the controller he's in charge of the dependence injection he gets his component over here the component does a lot more than just this but the controller itself only needs these two methods and when he does this it's also pretty direct on create view he just attaches a view tree and when the event of attaching this view happens he gets the component the injection component wraps the view in the presenter and then takes the mediator and binds it to that and that is pretty much all it does in this case at least so the nice thing here is that each one of these components reads a lot easier to itself looking at it you can tell what it needs to do it doesn't it's not all taught to get into a similar kind of file but you're worried more about the what and less about the how yes exactly and honestly in future controllers this thing gets repeated over and over again abstract into a base class because it's very repetitive let's take a look at the list view wow it doesn't actually fit in the screen this is because this guy is actually two mediators in one there's two parts in this view one is the larger screen in which in this case he's binding to the data source of items whenever it gets a new set of to-dos just notify us that this has to be redrawn and this floating action button here which takes me to the create controller is outside of the preview of the list itself and there's like a second mediator sort of hidden inside which is the one that deals with each one of these rows so whenever I get to you know I grab the actual to-do titles etc on clicks I go to the details controller but there's an error I warn this part is a bit more interesting is the first write operation we see whenever there's a click on the checkbox or when there is a change on the checks on the checkbox I will take my data source a copy of this to-do in which I just training the state of the computer sorry can I just ask take until is it observable thing yes take until in this case every presenter has this observable wixity patches which is just an event whenever it's taking away from the screen so you get unsubscribed for free yes exactly for a lot of like the clicks it's implicit because it comes from the presenter this one actually this one I can also remove it there's another case in the previous screen where I it was more important like data source right here I'm binding to the data source that I want to make sure that I stop binding to it when the presenter attaches because it's actually in a point and then I'll be leaking stuff this is the presenter for it again there's like two actually one for the list which I'm just skipping this is boring and there's an item for each one inside what's a little bit more interesting on this guy is this is checked which you know you could think of it as just the checkbox but it was checked or not but actually this presenter goes through trouble of doing a bit extra effort and putting a strike through on the text right this is something that is just visual the mediator itself doesn't care in this case he's just sitting with whether this presenter's hole is marked check or not but behind the scenes we just add a little bit of extra we don't put a strike through flag on the text or we take it away the question for me is why are you doing that presentation style work in what to me looks like a getter oh this is not a getter this is a property it's a getter and a setter I get it yes I can see that the get actually does only check whether the view has a check mark and whenever you change it you're not just setting the boolean flag where you're also repainting a program yeah cool this is the controller the basis of controller I just skipped what's interesting here is once again this is a little bit like a the adapter here works a bit like a nested controller because he's in charge of each one of these views and even though it was not planned he ended up doing pretty much the same thing uncreate this is like a method from the android adapters uncreate view holder I'm just instantiating the view unbind I'm actually calling bind in the mediator just as before so it acts pretty much exactly as controller even though it's called an adapter and this enters into a little bit of the idea that there's some nestedness going on here like there's controllers mediators and presenters happening at different points of the view hierarchy inside alright the edit view here we're going to flip around let's start with the edit controller it's poorly named this one actually when you create it you may or may not pass a URL like your eye if you don't this actually creates which is why this guy says new if not it would say edit otherwise it's like a very standard controller so we just skip it again very standard for center the only thing interesting in this guy is that other than setting and getting the title text as before we also have changes because these are now editable fields so now we also throwing those out as events and it doesn't fit again let's split this into two parts the mediator when binding basically depending on whether he has a URI he decides whether this is going to be a bind for create or for edit honestly in retrospect I probably should have moved that into the controller part but it kind of works though if it's for create I set the title to be new to do then I bind the fields and if it's for edit I set edit I get the data for what it to do and then I keep a reference to it set the initial values to field and then I finally bind the fields either way I first start by and this is again business logic this is a little bit of validation that's going on here I'm saying I only want to actually create to do's I have a title I don't want empty titles for this so since this is a very simple validation I've been in line if you had a lot of fields and a lot of validations you could probably wrap that up in a separate class that can be tested by itself in this case it's called a new to do validator yeah yeah yeah it could be something on the line yeah I have it or just to do validator right if it's empty I'll just start by setting the state of this button to you know whether it's disabled or not depending on how things are I subscribe to title changes whenever the title changes I check whether I should be able to submit basically then I keep a reference to the stream what it currently is and finally when I click if it's enabled I disable to prevent double clicks on this stuff and I submit which will basically go back to the data source I'm either going to create or update one of the to do's and then I'm going to say navigate or navigate back if I had like a network in between I could very easily throw in more UI show me a dialogue that is you know the progress indicators which will impact that would be like presenter.show async waiting and that would be right on the here do on subscribe async waiting and then do on complete and finally I go back so we've been seeing these navigator stuff here in places the navigators they're all in this case implemented in the activity itself activity does very little it's it creates its base component it creates a router just for conductor that's where everything all the other controllers it puts an initial controller on it and then it will have implementations for each one of the navigation methods since it has the router and it's at that point of the view hierarchy it knows how to move things around I didn't have time to implement the dual pane one but basically it would be very similar like everybody else would just call on an navigator the same methods they're calling now and then the activity would be deciding for example push dv controller if I'm too pain and now it really is like if I have two pains then instead of replacing one controller with another I could just push controller on my details pain or something on that line and that is that and I didn't have time to put in all the reference under yes I will it's already on github available yes skate I like your argument that the default template generated by injured studio is inappropriate because the code that we have today is a code we copy dish tomorrow and this is setting up developers for more pain down the track do you think that it is the way it is because this does require more concepts to learn it is more moving parts and like there's a as developers sometimes we have this we want to push away things that we say oh that's too complex but the hard part is figuring out like is it actually complexity right or is it like you're just tightly coupling all your shit together and that actually makes your life harder later and so you should there's some complexity you should deal with and like so is it the appropriate amount of complexity that's my question I agree like it's very easy and this is part of when you're starting and you start with this pattern it's kind of easy and when your application is still small to just throw everything in together and to be honest to get as I was playing around with to this level of separating in these particular parts like the controller the mediator the presenter and all that it took me quite some time to figure out what was interesting is that once I had those three pretty well defined adding the form for example the edit one took me like half an hour to an hour and otherwise how long would it take I don't know forms are like one of the things that I most push away from like I hate dealing with the forms they usually have a lot of complexity and it ended up being really simple once I was used to the pattern of having these things in three parts starting just creating a mediator not even worrying about how it's going to come to be or what the presenter view is going to be like and just saying your needs these things to work this is logic right unit is for it and once it was all completed I actually started implementing here's a view and controller for it and they all came out very naturally I'm sure there's points in which this will end up looking more complicated than that but it's definitely something that I want to try from the start in whatever my next full-fledged app is going to be I think like in general Android doesn't describe any folder structure like all of you controllers right and anybody having to do a control app is going to grapple with this issue and I guess it's the same thing with IOS they don't type okay this is how you structure your thing they just say okay this is a recycler view you need an adapter with a view holder like that's it the rest is very helpful sir there's a lot of life cycle so what you showed us maybe it's just a board that you showed us which is all about setting it up and you use it a lot while it's Java and I was using when you do something like take until it's all there and do something with that so how does it clean up are it's Java in particular or in general for example does the controller get destroyed, which in turn will go and cascade into other things the controller actually is is surprisingly long-lived sometimes a controller and this is just a constituency of conductor if you're using fragments it wouldn't be the case but a controller might outlive an activity, it might the same instance might like if you rotate a phone on an android your activity actually gets destroyed and a new one gets created but the controller might be detached from the first one and put on the second one so you have to be aware of those things to make sure that you're not holding references other than that debuts themselves as you see like I'm not holding I'm not keeping fields on the controller we're saying hey these are my views so I don't need to do a cleanup and that is partially because I am using rxjava if I weren't I probably would be keeping a few fields on detach or on destroy view I would be removing those as well now interestingly particularly with views because another thing that's common in android is that you have an activity or fragment and you have a whole number of fields that have views that are directly on there so on destroy view you have to go and clear all of them up once you have a pre-center that is just encapsulating all your views instead you have reference to one pre-center or whatever you just say pre-center dot equals to null and it goes away it is the reference to all of them so it actually makes cleaning up a lot easier thank you I was testing android security to see if I could make a text message to all of them