About attitude, personal growth and community

It’s been quite a long time since I have been writing after a conference I joined as a speaker. Today something clicked and I felt like I had to put my thoughts down while driving back home from MobiConf (no worries, Francesca Bertola is actually driving the car 😂 ).

The new opportunity

A few months ago, MobiConf organizers reached out and invited me to speak in Krakow. I knew about MobiConf already and, since I have been to App Builders, I liked the idea of a multiplatform, multidisciplinary conference very much.

At the time the invitation came in, I was busting my ass modularizing a couple of Android projects to simplify and decouple the code base. I was also investigating Kotlin Coroutines, even if, on paper, they were still “experimental”.

The old attitude

As a senior engineer, I strongly believe that we need to invest time and energy in being early adopters. We need to be those that try and evaluate a technology to validate solutions and smooth out rough edges to be able to help those who can’t. It’s very rewarding to be able to help a junior developer who wants to try and learn a new technology, but for any possible reason is struggling and could use some help.

With the same attitude, I was also experimenting with different solutions for Dependency Injection and Service Location, to improve my relationship with Dagger.

I started to chat about this with a few friends and a talk idea was born. At that point, MobiConf staff was kind enough to bet on me even if I only had a rough idea of what I was going to talk about.

The new approach

Weeks went by and I started to work on my talk. For the first time I tried a different approach to lay down the first draft: a walk.

My classic approach has always been:

  1. Decide the topic
  2. Gather the ideas I want to share
  3. Create a draft of the slides and using Presenter Notes to create an engaging story to support the slides.

This time I wanted to start with the story first and I thought that, as for a lot of people, walking allows me to free my mind and facilitate my thoughts flow. Turn out this is actually a thing that our brain does pretty often: ever seen somebody walking in circles around the room while on the phone?

So I simply

  1. Got the dog
  2. Got the leash
  3. Got a mic
  4. Started recording myself
  5. Started walking
  6. Started talking

One hour later, I had the first draft of my talk. MobiConf provided every speaker with a presentation template, so I fired up my Keynote and I prepared my presentation draft.

How do we get feedback now?


Micro-bravery is a concept that I learned some time ago in an episode of the Tim Ferris’s podcast. The basic idea is that you gain more and more confidence thanks to a series of more and more challenging tasks.

When people ask me about how to start with public speaking, I always suggest the micro-bravery approach and I wish I had somebody back in the day suggesting that to me when I started. My first talk at a conference was at Droidcon Berlin in 2015. I had no experience and I was presenting a new topic back then: RxJava. Droidcon took a bet on me at the time, putting this funny Italian guy in the main room as the closing talk of the conference.

I was super happy to be there and I was happy to show RxJava, but I was also massively nervous. When I realized that I was in the main room I almost freaked out. When I saw the room full of people, I got seriously nervous. When I saw them adding more chairs to accommodate even more people, I felt like I was losing it.

The talk went well, but if you pay attention to the first five minutes of the video on YouTube, you will perceive my panic. It faded out as I went through the slides, but I will remember it forever.

We can do better 😄 Nowadays I implement and advice micro-bravery:

  1. Give your talk at your company and gather feedback from your colleagues. This is the safest environment for you to give your talk the first run. If you don’t feel safe giving the talk at your company, quit. It’s clearly a toxic work environment. You deserve better and they don’t deserve you. If you need help, reach out to me.
  2. Give your talk at your local favorite meetup. Meetups are safe places. I’m incredibly lucky to hang out with the lovely people of Berlindroid. We usually gather at c-base and from a venue point you can’t go nerdier than that 😂 For the MobiConf talk, I volunteered via Twitter, Mario Bodemann approved and BAM the thing was set. After the talk I asked for feedback and I got a variety of them: Miquel Beltran suggested to increase the font, Hasan warned me about a few points in the code that would be deprecated in the upcoming Kotlin version, Sasa Sekulic suggested that I could rearrange a couple of slides to improve the story telling.
  3. Give the talk at the conference. At this point, you have a different confidence in yourself and the quality of your material. You will once more get feedback and you will improve even more for the next conference.

These three steps always help me to approach every public speaking event with confidence and excitement. Simon Sinek once said that, in these type of situations, most people think they are nervous because, when you are nervous, your hands sweat, your heart rate is going crazy.

But if you pause for a moment and think about what happens when you are excited… well, your hands are sweating and your heart is pumping like crazy…

At your next conference, you won’t be nervous, you will be excited 😉


When I joined AsanaRebel, I picked up the project and I started to navigate through the repository, focusing especially on the build.gradle file.

Sadly, I had no CI setup to understand how to build the project on one side and, on the other side, I was facing 3 build types and 4 flavors, with not even a single line of documentation. Discomfort.

The plan: simplification

Simplification is the most complex thing to do

but I could count on a highly motivated QA team and I wanted to empower them even more, enabling them to take control on the Android release process.

My first goal was to automate the release process as much as possible, because I wanted to focus more on developing the app itself, having a lot of features to catch up with, compared to the iOS app.

As usual, when I approach new projects, the first step was to make sense out of the build.gradle file.


No joy there! 🤦‍

The good news was that when you are the only developer, there is no documentation or nobody to ask, and you are working for one of the fastest growing startup in Berlin, if you can’t make sense out of something in your project, you have any right to kill it. I mean it!

You are responsible for the code base, you are the one accountable for the status of the app, you are the one who’s gonna answer to any possible Android question from now on and you can’t afford to live with an area of your domain that you don’t know anything about, you don’t know the reasoning behind those decisions, and, even worst, if something goes south, you have no idea where to start to fix things.

Long story short,

Ciao ciao flavors

The current setup has two build types: debug and release. That’s it. No more releaseStaging or debugMockProduction nonsense:


Build server

I wanted a CI, of course. It’s a invaluable tool for any modern project and, with the plan to add more developers to the team, it was a necessary step to move forward with the right attitude: automation, safety nets and quick response.

Attempt #1: Circle CI

CircleCI was the first service I tried. They had a free tier so I could play around a bit and figure out scenarios.

It wasn’t nice, unfortunately.

The first pain point was the setup. They were, and probably still are, using a .yml file to setup the build workflow. This means that before being able to start building your project, you need to look for documentation, tutorials and examples by those who came before you and were kind enough to put that on writing. Painful.

Once you have the first draft of yml, you can start experimenting:

  1. Change something
  2. Commit and push
  3. Fingers crossed 🤞
  4. Build failed
  5. Go to 1

The Try&Error almost drove me crazy and generated this sort of git history:

CI related Git commits

You can guess my frustration. Eventually I managed to setup a successful build… kinda. I had to simplify a lot because the docker containers were failing due to not enough memory 😔

The free tier limits the available RAM in the container to 4GB, so I couldn’t run lint and anything else that would suck RAM, but at least, I had a CI.

Let’s connect it to Slack now to get build notifications!

Well, there was no ready-to-use solution available, so I had to come up with a Gradle task and some curl commands to pull the data from CircleCI and push it to Slack via Slack API. Here is a snippet:


The whole setup was working, but it was a bit flaky. Builds were still failing every now and then due to the memory problem in the container so I decided to look into it and we decided to switch to the premium plan to enable up to 8GB RAM containers.

I was pretty happy: after weeks of struggling, I was finally going to have a proper CI. Well, not really. We hit a blocker due to some undocumented change in the pricing in CircleCI. The premium plan was gone, replaced by a Performance plan with a different price bla bla bla with different performance yabba yabba…

I was pissed for the wasted time and wasted money so, living in a free world with a free market, I turned to another service.

Attempt #2: Bitrise

I created a Bitrise account, I linked GitHub. I started playing with the website and 20 minutes later I had a fully setup CI. FFS!!

No configuration file, no bullshit.

The GitHub hook allowed me to create triggers and connect triggers to workflows. Our current triggers setup is based on 4 branches:

  • master
  • develop
  • feature/*
  • hotfix/*

These triggers fire different workflows:

  • masterDeployAlpha
  • developDeployInternal
  • feature/*BuildStaging
  • hotfix/*BuildRelease

I trust your ability to infer what’s going on here, but still, let’s put some detail in. We are using Git-flow so master contains the current production release. This means that we only merge to master when the QA team and the PM give us the 👍

Once we merge to master and push it to GitHub, Bitrise kicks in:

  1. DeployAlpha workflow starts
  2. The CI pulls master
  3. It runs gradle assRel
  4. It deploys to the Google Play Store Alpha Channel
  5. It sends a Slack message to notify QA and Support team when the new build is available.

Something similar happens pushing develop, but the build ends up on the Internal Testing channel of the Play Store where I have a handful of brave colleagues that at willing to try these Internal builds. They like to live dangerously.

I also like to live dangerously

Once the new release reaches the Play Store, my work as a developer is complete and the ball is in Antonia Landi’s back yard. She is in charge of the release process: final QA approval, Alpha/Beta/Production staged roll-out, Play Store listing management and overall quality monitoring.

If something goes south, she’ll knock to my door and we start the whole process all over again.

Take aways

Having a releasing pipeline that you can trust is an incredibly powerful asset to guarantee speed, quality and resilience:

Happy releasing, people 😉

Modules, modules everywhere

I have joined asanarebel.com as Senior Android developer at the beginning of February. Asana Rebel is a health and fitness app with workouts for different body and health goals, but all of them are yoga inspired.

When I joined, the plan was to increase the team size and raise the code base overall quality, focusing on the release process, testability and modular architecture, keeping a fast pace and short feedback cycles.

Today I want to talk about modularization and how I managed to split the code base to improve separation of concerns and build speed.

I believe modularization is a key point in any modern Android app. I don’t necessarily mean having many Gradle modules, but having the source code nicely organized in cohesive and decoupled entities is definitely a good idea.

My strategy was mainly to create Gradle modules to increase the build speed, leveraging Gradle parallel build and caching strategies.

Attempt #1 — The bold way

I have a rough idea of what the app is doing. I’m going to split it by use case!

After a quick project overview, it seemed a reasonable idea at the time. I mean, we have the onboarding, we have the login/sign up, we have the Today screen, we have the programs, Settings, Profile screens: it looked feasible.

I started moving pieces around, keeping an eye on the build results, leveraging IntelliJ massive refactoring capabilities, and I failed miserably. No surprise though, this already happened in the past, I had the exact same experience in previous companies: no matter how much do you think what you are doing makes sense


Single module projects evolve in a very specific way: messy. It sounds harsh, but unfortunately it’s true. When you can access everything from everywhere, you stop thinking about how things are connected, the only thing that you see is the next dependency that you need to satisfy to complete the current task. If you are keen to zero testing #yolo, static methods, getInstance()s or poor Dagger design, well, it’s just a matter of time before everything turns into a spaghetti code hell, where everything is referencing everything else accessing things in a blocking fashion or, even worse, playing Russian roulette with race conditions.

After two days of digging my way down to the bottom of the rabbit hole, I gave up. I reverted everything and I went back to my app-android/app/src/main sadness.

Attempt #2 — The :base module way

A few weeks ago I came across an inspiring talk by Marvin Ramin (https://twitter.com/Mauin), http://uk.droidcon.com/skillscasts/10525-modularizing-android-applications, where he shows an interesting approach he’s been experimenting with for a while now: pull the monolithic module :app down in the dependency graph, renaming it to something like :base and from there walk your way up and sideways, pushing classes to new separate modules that may depend on :base instead of :app.

This is an oversimplification, of course, and I advice you to give the talk a try. I’m pretty sure you will relate with the pain that Marvin brings with himself after God knows how many trips down to the rabbit hole. I definitely could relate.

Unfortunately I couldn’t get any progress with his approach either. For some reason the :app is too entangled and I’m also in the middle of a conversion to Kotlin and Kotlin DSL, removing 12 flavors and 4 build types doesn’t help, documenting as much as I can to prepare the project for the new coming developers.

I know what you are thinking:

Come on, man! How about fewer things at the same time?! 😂

I know I know. What can I say? #yolo

Attempt #3 — Patience

I believe Marvin approach is solid and can work as a starting point, so even if I couldn’t move the :app module straight away, I started to browse the code base looking for another attack point. I’m new to the project so it was also a nice exercise to better understand the architecture, overcoming the fear of touching too many things and breaking everything.

I started looking for leaf classes: data classes, utility classes, interfaces with meaningful names. I had one simple goal: moving as many files to new modules as possible.

It sounds a bit pointless, but my goal was to break things to figure out how things were connected and coupled together.

  1. So you open a file
  2. you check the imports
  3. if they feel like reasonable you move the file to a new module that makes sense with the file
  4. run the build, run the tests, run the app, looking for crashes or regressions.

This is super tedious, and can be very frustrating, but if you are lucky, things don’t break too much and after a while you end up with a git history looking like this:

Sneak peak into the future

In real life, we are not lucky. Com’on! If we were lucky we wouldn’t have been here in the first place, right?

Things that broke during the journey

The first things that blew up were the Dagger scopes.

There were:

  • @ApplicationScope, a custom application wide scope. Not sure yet why this was preferred to Singleton
  • @UserScope, a scope designed to exist only when a user was logged in
  • @ActivityScope and friends

Scopes were OK from a design point of view, but in the practical implementation they were very messy and fragile due to a lack of proper dependency injection.

The UserScope set, for instance, initially looked like a nice candidate for a :user module. Working with the usual approach

  1. I created an Android Library module called :user and added it to :app build.gradle.
  2. Once I had the module, I started moving the tiniest and decoupled files I could find that could belong together in a :user module.

If you are like me, in a similar scenario, you would get in the zone, you would iterate over and over: move, build, test, commit, push. After a couple of hours, you sort of hate yourself, your CI hates you for the 150 builds your ran since you started, you start questioning your career, you feel like you will never see the end of this, imposter syndrome ramps up.

No worries, you are just low on sugar. Take a break, drink some water, eat a banana, troll an iOS colleague about how hard it must to be for them to support 4 devices and 2 OS versions at the same time and than go back to your task.

So far so good, then I reached a point where things started breaking for real: I found a couple of classes in the UserScope domain that required ApplicationScope classes. If you scope your app properly this shouldn’t be possible, but if you are working for a startup, accepting hacks and technical debt is part of the game and things get tricky.

To solve this issue one would have needed to rework the whole scoping, but I believe there was no time, so the solution was the infamous quick and dirty hack, a.k.a. quick to be forgotten, dirty forever:

I need the [ADD RANDOM]Manager, so I’m gonna access it statically. getInstance() FTW #yolo

This is, in my opinion, the starting point of the decline of the whole code base maintainability. After this moment, every time you hit a blocker, you will feel the pressure, you will know that you should try to make things right, but you will use that one time you did the hack as an excuse for every single future hack, because hacks take the discomfort away quicker than the proper solution.

For me, eventually this will need a major rework, but at that point it will be a technical/business decision: investing today to be consistently fast over time.

The second major thing that broke without mercy was Proguard.

No surprise here. I believe Proguard with its hard-coded package paths and carved in stone file names is not ready for dealing with this kind of infrastructure rework.

I’m sure that pro-Proguard people will yell at me that if you configure it properly everything will be fine, but I work in the real world where projects evolve quickly, people change, things get complicated exponentially because of… reasons and Proguard has never been a factor of simplification, on the contrary it always added more uncertainty and frustration.

In AsanaRebel, for instance, everything looked OK, no warning, no error, builds were successful, but at runtime the app just kept blowing up due to some missing resource file wrongly taken away by Proguard. Tracking down these things is exhausting and builds up a lot of frustration, for a still unclear final gain of some KB in your final APK.

Current status

At the moment we have a dozen of modules and counting. Some of them are pretty fat, others just contain a few files.

The :core module, for instance, is a sort of safe-harbor module, where dependencies that should be moved from :app to a module :foo can’t be moved there because they are also needed by a module :bar and this would create a weird circular dependency, so :core becomes this thirth party that helps to decouple things in the meantime that a better solution is put in place.

The going forward approach is creating a new module for every new feature. With this approach we are certain to leverage Gradle parallel build, we can also enforce a better separation of concerns and testability, and most of all, in the very fast and very experimental mindset that we have in AsanaRebel, if we want to drop a feature because it’s not performing well, we simply delete a folder.

Eventually we can guarantee that only the old and very coupled code is still in the :app module, contained and waiting for improvements.

On this note, the :app module will also contain a package with the same name of every Gradle module we have. These packages will contain Activities, Fragments, Adapters, Views related to that module and will allow the dependency injection. Only files in :app can access the main Application file and then the Dagger component and perform the injection. So far I was not able to find a solution to perform the injection from an Activity living in a module.

The more familiar I get with the code base, the easier will be for me to see how things are connected, how to rework the dependencies and how to move things to the proper modules. This is an incremental process, it’s slow, it takes patience and it can be very frustrating, but I believe it’s the right thing to do if you really care about the product you are working on.

With more developers joining the AsanaRebel Android team in the future, refactoring the old code base will be a team effort, somehow a team building exercise, instead of a single developer going John Wick mode, head-shooting every getInstance() until the end of time.

Kotlin DSL Gradle files, multiple modules and shared variables

This doesn’t want to be a real article, but more a crash course about Kotlin DSL for Gradle.

The crucial point is the possibility of migrating an existing project to the new Kotlin DSL for Gradle, in an incremental, modularized fashion.

Below we have a pretty standard root project build.gradle file:


The parts that I want to highlight are those shared version numbers, i.e. rxJavaVersion, timberVersion and so on.

This is a standard build.gradle file for an Android Library Module:


As you can see, we reference those constants.

If you want to migrate this file to the new Kotlin DSL, you need to create a build.gradle.kts file in place of your build.gradle one and make it look like this:


Notice how we can access those constants in a different way, but still pretty straightforward.

You will also notice that the dependencies are not the same in the two files, some versions are hardcoded, other are referencing the global constants.

It’s messy on purpose: this is an working example from one of my projects and I want to show a few of different choices you can have in those files. It’s up to you.

If you want a better overview about Kotlin DSL for Gradle, I would suggest the good article by Antonio Leiva https://antonioleiva.com/kotlin-dsl-gradle/.

Thank you all for the feedbacks and the support!

Happy Kotlin ❤️

Being alone is not being lonely

I have started meditating in 2014, thanks to Francesca. I was coming from a very hard year: working in the sport event business is no joke when it comes to stressful environment.

However, I was thinking I was doing OK: new year, new job, new city, new work domain. What could possibly go wrong?

Well, it turns out that sometimes the problem is you! You change everything you can, but you keep doing the same things with the same attitude and no surprise if you end up with the same results: I was still struggling.

Francesca figured out that I needed external help and knowing me, proud stubborn southern Italy nerd, she knew that it couldn’t be just “you should talk to somebody”, but it had to be some sort of a project I could keep doing by myself. She gave me Headspace by @andypuddicombe and everything changed.

At the beginning it was tough. I couldn’t focus on the exercise. I kept creating lame excuses like “I don’t have time for this meditation thing. I have stuff to do!”, but week after week, it kicked in.

For the first time in my life, things were different, because I was different. Being forced to sit for 10 minutes and do nothing became being able to sit for 10 minutes and be mindful.

Since then, I’m meditating every day, improving my ability of managing stress, unexpected events and conflicts, sleeping better, being focused and creative in what I do. A lot of improvement from just a few minutes of… well… of what exactly?

I put quite an amount of thoughts into this and now I can say “a few minutes of being alone”. I believe this is something that my generation lacks a lot. We are so constantly busy with everything that we struggle with being by ourselves, like if we were somehow scared.

I often got asked about my personal and professional path and the mindfulness topic always comes up. It’s always tricky because the moment I start talking about my experience and my current meditation habit, I get comments like “I can’t do it!”, “No way I can sit for that long. I have stuff to do!”, “I tried it once. It didn’t help” and so on.

After a few of these conversations, you start seeing patterns: people misunderstand being alone with being lonely. I see this a lot in my generation: a subtle, unconscious, uncomfortable feeling of guilt when you stop doing things, and so, we fill our lives with stuff to do, constantly struggling to complete the todo list.

I was exactly like this: busy, stressed, always struggling. It was a long time ago… actually not… it was just a few years ago, but it feels like a lifetime ago, because the difference is enormous and the difference is mostly in how I feel when I’m alone, in the room, meditating. I’m not lonely, I’m aware of myself, of things I can control and aware of my ability of properly processing what I can’t control.

Self-improvement never stops, because you can’t be prepared for everything that life throws at you. What you can do is working on being at peace with yourself and this reflects all around you. When I’m mindful I keep a positive mental attitude and this creates a healthy atmosphere also for those around me.

Make no mistake: I’m still a big work-in-progress and there is still a long path towards being the person I want to be, but what I can tell you is find a person that loves you and sees behind the mask you unconsciously built, find a company and colleagues that care about your happiness and find those 10 minutes to be alone with yourself.

Push vs Pull: air conditioning system

By Ivan Morgillo, Sasa Sekulic and Fabrizio Chignoli

This article has been excerpted from Grokking ReactiveX.

After a life of imperative programming, switching to a reactive mindset could seem challenging:

“Why should I give up all the control and bend to this <data are in control> thing?”

Let’s look at it in an everyday life scenario: the air conditioning system. Today is a hot day and we want to start the AC system when the temperature in the room reaches 77F. We need a thermometer.

Well, we need a Thermometer class that provides a temperature() method to obtain the current temperature in the room.

Once we know how to obtain the current temperature, we can combine it with our AirConditioning class.

This class provides three methods:

class AirConditioning {

To change the status of the air conditioning system, we can use start() and stop(). If we want to check if the status change was successful, isRunning() gives us info about the current status.

Now that we know the current temperature with temperature() and we can turn on the Air Conditioning system with start(), we can create an AirConManager class with a basic monitor() method that will contain the logic needed to retrieve the current temperature, evaluate a condition and execute the proper action:

fun monitor() {
while (true) {
if (thermometer.temperature() >= 77 && !ac.isRunning()) {

The current implementation of the monitor() function is almost offensive and I will understand if your eyes start bleeding:

  • we have a while(true) loop to keep on evaluating the condition;
  • we have the if condition itself that retrieves the current temperature, checks if it’s lower than 77 degrees and if the Air Conditioning system is already on;
  • we have the action block that starts the Air Conditioning system and ends the loop.

So far, we don’t have any special requirements and we don’t care about details like stopping the system or restarting the loop if the temperature drops.

This function could be refactored and polished in a few ways, but the key point will still be:

Constantly checking the temperature and deciding what to do accordingly

How could we migrate to a reactive scenario?

In an Rx oriented scenario, our thermometer would be an observable thermometer, represented by an ObservableThermometer class.

The ObservableThermomenter class will provide a single method: rxTemperature(). If we subscribe to this Observable we’ll receive the current temperature every time it changes:

fun rxTemperature() : Observable<Int> {

We can go back to our AirConManager and refactor it to handle out new reactive thermometer.

AirConManager can subscribe to ObservableThermometer in its monitor() method and receive a new temperature value:

void monitor() {
.subscribe(temperature -> {
if (temperature >= 77 &&!ac.isRunning()) {

Note: This .subscribe() method has a Subscriber implementing the onNext() method as a lambda expression. Subscribers usually have three methods, but if you don’t need to be notified when the stream completes or you don’t want to manage possible error scenarios, you can avoid implementing onCompleted() and onError().

The moment we subscribe, the data will start coming to us: the onNext() will receive a temperature value, we’ll evaluate it and act accordingly.

“Wait a second! All this fuss to save me a while loop?”

One of the key principles of reactive programming is that it is all about data being in charge, being able to create the perfect data stream you need and working with the stream that is available.

Let me introduce you to the .filter() operator!

Push vs Pull: create the flow you need

In our scenario, we don’t need a temperature value every time it changes. We just need to know when the temperature reaches 77F to start the Air-conditioning system. Rx is all about flowing data, coming to us to be used, filtered and transformed.

Let’s improve our monitor() method to create the sequence we need by filtering out all the temperature values we don’t need:

fun monitor() {
.filter(temperature >= 77)
.subscribe(temperature -> ac.start())}

As you can see, filter() evaluates a Predicate and propagates the item only if the condition is satisfied.

We were supposed to receive a new temperature value in our onNext() every second, but what we wanted was instead to get into the game only if the Air Conditioning system was off and the temperature in the room was higher than 77F. We used filter() to filter out all those scenarios we weren’t interested in and receive only the values that match our use case. We created the perfect sequence for the task at hand from an initial generic sequence that we can’t control.

This is the power of the Push approach: data coming to us. We can focus on using the data instead of retrieving and managing them.

If you’re interested in learning more, download the free first chapter of Grokking ReactiveX and see this Slideshare presentation for more details and a discount code.

If you enjoyed this article, please click the 💚 below and spread the Rx love 😊

GDG Geneva — July event

GDG Geneva is a small GDG, but we try hard 😊 Last Monday we had our July event, and, despite the tremendous heat, spent more than one hour talking about MVP on Android.

I prepared a small Android app to demonstrate how we can create an app that fetches data from a backend and shows them in a list, using two different design approaches:

  • !Good Old GOD Activity
  • MVP

Both versions are identical from a user point of view: same UI, same UX. What’s different is the code quality and maintainability, of course.

GOD Activity

Everything is in the Activity, because… why not!?

It’s easier and quicker to have everything in one place and if I need a Context I can use this.

The Retrofit network call is synchronous and we dodge the NetworkOnMainThread exception using an AsyncTask. The API client is created in the Activity, like every other needed component.

If you are like me, this approach keeps you awake at night or, even worse, gives you nightmares the moment you close your eyes.


Model-View-Presenter is the new standard de-facto on Android. In this version of the app, I tried to make the view as dumbest as possible, move as much as possible away from it and into a pure-Java codebase. Being pure-Java, we can easily test it without firing any Android device or emulator or using Robolectric.

I used Dagger2, RxJava, ButterKnife also to give an overview about common Android dev tools. Kotlin has been used in the test environment to show how you can start using the new language (read Our Savior) just for your tests and then move to a full Kotlin code base when you feel ready.

Source code

App source code is available here:



Slides are available here: