Tag Archives: Design

Rebuilding a legacy app from scratch (III): Clean Architecture.

Once we have decided the features we want to have in our Minimum Viable Product version of the app, and before jumping straight away to start coding, we need to decide how are we going to design and architect the application.

Why we need to implement a good architecture? Because we want the code base of our application to be testable, scalable, robust, modular and maintainable, among other things.

Over the years a few architectures patterns has been defined and used by Software engineers for different platforms and systems but one of them that has gained lot of traction and popularity in the mobile community is the well known Clean Architecture.

 

What is Clean Architecture?

This pattern was defined by Uncle Bob and described in this blog post.

He summarise the main goals of a good Software Architecture:

  • Independent of Frameworks: We want to isolate the Android or iOS framework from our business / UI logic, making them testable and interchangeable.
  • Testable: This has been one of the traditional issues when designing the testing strategy of our apps, it was difficult to test a module that has many external dependencies, like the Android SDK.
  • Independent of UI: We want to have our UI independent from our business logic, this way the last one can be unit tested without having to depend on UI or Integration tests.
  • Independent of Database: The source of data must be isolated from the rest of layers of the app, this way we can change this source without affecting the logic of the app.
  • Independent of any external agency: The business logic doesn’t depend on any external factor.

 

An Android approach to Clean Architecture

So for our Android implementation of the Clean Architecture we are going to follow the design described by Fernando Cejas in one of his great blog post.

We are going to identify three main layers in the code base: Presentation layer, Domain layer and Data layer.

 

Presentation layer

We are going to use  the Model-View-Presenter (MVP) pattern to implement this layer. I will explain briefly this presentation pattern but you can see a more detailed explanation in my introductory article here.

Basically we are going to have a View entity,  where we implement the Activities, Fragments and Views. These are what we call passive views, what means that they are totally dumb and have zero presentation or business logic. They just display information in the screen under the direction or the Presenter and dispatch events back to this one, like user actions.

Then we have the Presenter that as mentioned previously contains all the presentation logic and is acting as a bridge between the View and the Model layer. This entity should not have any Android dependency, but it knows how to respond to user actions and how to retrieve the information or data that is required to display in the view.

And finally we will have the Model layer that will contain the bridge and adapter classes accessing the Domain layer of our architecture.

 

Domain Layer

It’s going to contain all the business logic of our app. Once again there shouldn’t be any Android dependency in this layer. In here we will implement what we call Interactors, which basically are Use Cases.

For example, if we look into the MadridBus application, we will see that one use case is to get the list and information of all the bus lines in the city. This logic will be implemented in one Interactor and it will be used by the Presenter of the Line List View.

So when the user open the line list screen, the View is going to tell the Presenter that it has been loaded, the Presenter knows then knows that have to retrieve the line list, so it’s going to instantiate and use the GetLineListInteractor, which is going to access the Data Layer to get the list of lines. When the data set is returned the Presenter knows calls the View and tell it to display this information in the right way.

 

Data Layer

In this layer is where all the data of the application is stored and processed. This layer is responsible of providing the mechanisms to retrieve the data that the app needs. The Interactors will be calling the API of the data layer so they can retrieve this data to the Presenters.

We want to make the data source totally agnostic for the rest of the different layers of the app. This means that the Interactors doesn’t know from where the Data layer is extracting the information, they will just call the interface of the API exported following the Repository Pattern.

Screen Shot 2017-04-27 at 22.47.21

From Hannes Dorfmann blog post 

 

For example, in the app we are going to have two sources of data, the first one will be the Cloud, from the public transport agency data service. Then we will have the local database, where we will save the data taken from the cloud, so the next time when the GetLineListInteractor call the Repository to get the list of lines, if this exist in the local database, it will retrieve from there, and if not it will retrieve it from the cloud.

To read more about the repository pattern check out this great blog post from Hannes Dorfmann.

 

The project structure

One importante aspect when designing our code base which is dependent on the architecture of the app is the structure of the different modules and how are they grouped in the project.

As Uncle Bob says, this is like a blue print of the application. Looking at the project structure should give us an idea of what this system is about.

Screen Shot 2017-04-23 at 00.27.36

As we can see in the screen shot, the project has four main module groups: DI, Domain, Model and UI.

In DI we have all Dagger 2 dependency injections helpers.

Domain as we have mentioned before contains the business logic, interactors, network modules, rules, etc.

In Model basically we have Pojos and data classes.

Finally in UI we have all the Presentation layer modules, like Activities, Presenters, etc.

With this project structure we can easily find and navigate to a specific feature or functionality of the app, either the UI part, the Domain or the Data component of it.

 

Conclusion

A good architecture is the blueprint for our project, it will guide our implementation and will keep the maintainability, testability, cohesion and modularity of the project.

Clean Architecture is not the silver bullet nor the only way to design our apps, but has proved to be one of the best solutions.

We will be following this pattern in the MadridBus source code implementation that you check out in Github here.

Advertisements
Tagged , , , ,

A beginners guide to an effective Android testing strategy

Testing quite often is one of the most neglected aspect in many Software projects, and in Android this has been particulary a common issue since the beginning of the platform.
atsl-logo

Even Google didn’t seem to be making big efforts to encourage testing: Documentation was almost nonexistent, the tools and frameworks were confusing or hard to use and there was almost impossible to find an open source project with good testing implementation.

 

Why testing?

Implement a good suite of different type of tests with a good coverage ratio and maintain it requires time and discipline from the dev team. In some cases the member of the team might not be familiar with the testing frameworks or even never have implemented any  type of test. So what are the benefits of this time and resource investment? Here some of the reasons:

  • Testing allows us to check the correctness of the app features. We should never rely on the QA team to find defects in our code. Is a very common practice to implement some feature, test a couple of use cases, send it to the quality team and wait until they find a few bugs for us and then fix it. This is really a bad practice that a professional developer should never do. We should be confident that the deliverables that we release to QA team shoulders been tested throughly, has a good test code coverage and that our quality colleagues should almost never find a bug.
  • Improves the design and modularity of our code base. If we create a new feature with a TDD approach, we will be building our classes in short iterations, thinking in the interface and driving the implementation with the proper user requirements in mind. This will make our modules and classes small, independent and with one only responsibility unit.download
  • Help us to implement new features or refactor existing one with much more confidence that our changes will not break current working and tested
    functionalities. If every time we add a new piece of code to our project we run our test and all pass, we can be sure that we didn’t implement anything that is affecting and having negative side effects on the existing features.

 

Types of test

In the Android platform, generally we will implement two categories of tests: Unit Tests and Integration Tests.

  • Unit Tests.  We will test small and independent pieces of code. It might be a single class, an interface or just a method. We can consider it as the smallest possible testable piece of code part of an specific independent module. In Android we will use JUnit running either locally on the JVM (prefer this one as fastest method) or in an emulator or real device.
  • Integration Tests. We are testing more than one individual module working together that implements a complete functional part of our system. For example we test the Login feature of our application where different entities works together and and we want to test that the login process is accomplished successfully on different scenarios. In this case in Android  we will implement UI Instrumentation tests with Espresso and Automation tests with UI Automator.

 

Architecting the app for testing

As we mentioned before one of the complains of the Android community was that testing the platform was a difficult task. Apart from the lack of a good testing framework, the developers faced the problems of implementing tests for modules (Activities, Fragments, etc) coupled to multiple Android SDK dependencies.

In order to mitigate this issue, one best and most common solutions is to architect our application using the MVP pattern. With this approach we manage to have a clear separation of concerns of our modules making much more easy to unit test our models and use cases classes without having to mock and get around of all the Android SDK dependencies.

Typically we will have our View layer with the Activity or Fragment that have almost no logic at all. A Presenter acting as a bridge and a Model which will have our use cases and where we will probably focus most of our unit tests.

In a previous I made a basic introduction of the MVP pattern where you can see all these concepts with more detail.

Test Pyramid

Following the TestPyramid concept described by Mike Cohn, Unit Tests should be around test_pyramid60-70% of our test code base and the rest 30% should be implemented as End-to-End tests (Integration, functional, UI tests).

The reason for this is that the end to end tests has a few problems, like you need to wait until the app is deployed and running in a device. Then probably the test will have to deal with things like login, registrations, database access, etc.
Also if you find a bug it will be hard to figure out where exactly the problem is, as it could be in any of the multiple modules and components that are involved in the specific user flow.

On the other hand Unit Tests are fast, reliable and they isolate the test scope to very specific and isolated pieces of the system which makes it a much better way to identify the defects in our system.
If we have build our code base using TDD, we will probably have test covered almost all modules of our application which will give us peace of mind that all parts of the application are being tested and any regression would be detected.

Implementing Unit Tests

First let’s add to the project build.gradle file the required dependencies for Espresso, JUnit, UIAutomator, etc.

    // Dependencies for unit testing
    testCompile 'junit:junit:4.12'
    testCompile 'org.mockito:mockito-all:1.10.19'
    testCompile 'org.hamcrest:hamcrest-all:1.3'

    // Android Testing Support Library's runner and rules
    androidTestCompile 'com.android.support.test:runner:0.3'
    androidTestCompile 'com.android.support.test:rules:0.3'

    // Espresso UI Testing
    androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2'
    androidTestCompile 'com.android.support.test.espresso:espresso-intents:2.2'

    // UIAutomator Testing
    androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.1'
    compile 'javax.inject:javax.inject:1'

As we mention before we have two options to run Unit Tests, one is locally on the JVM and the other is running with UI Instrumentation runner. We will favour the local JVM test as they will compile and run much faster. The downside is that these can’t have any Android SDK dependency, but that should be our goal as we saw before using a MVP pattern.
One way to overcome this issue is providing any Android dependency using a mocking framework like for example Mockito.
This will be fine if we just need to mock a couple of dependencies with not many interactions between our code and the SDK, but if we have more complex interactions and we need to spend hours mocking classes, this would be a signal that we should run those test in a emulator or device using Instrumentation Test.

To add the tests in the project we haver will need two folders, one for each type of test as you can see in the picture below, the Unit Test lives in the folder named “test” and the UI test are located in the folder “androidTest”. Both have to be at the same level that our main folder of the project. This is important because otherwise Android Studio will not be able to identify these classes as tests.

Screen Shot 2016-04-02 at 20.14.14

 

Anatomy of a Unit Test

So now we are ready to add a Unit Test, to do this just add a new class to the Test folders of your project and now we will have to specify which runner we want to use, the size type of the test, etc. Let’s have a look at the example below and we will go through the different parts.

@RunWith(MockitoJUnitRunner.class)
@SmallTest
public class EmailValidationTest {

    String EMAIL_REGEX = SignupPresenterImpl.REGEX_EMAIL;

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void givenValidEmail_RegexCheckReturnsValid() throws Exception {
        String validEmail = "david.guerrero@quoders.com";
        Assert.assertTrue(validEmail.matches(EMAIL_REGEX));
    }

    @Test
    public void givenInvalidEmail_MissingAt_RegexCheckReturnsError() throws Exception {
        String invalidEmail = "david.guerreroquoders.com";
        Assert.assertFalse(invalidEmail.matches(EMAIL_REGEX));
    }

    @Test
    public void givenInvalidEmail_MissingHost_RegexCheckReturnsError() throws Exception {
        String invalidEmail = "david.guerrero@quoders";
        Assert.assertFalse(invalidEmail.matches(EMAIL_REGEX));
    }

    @After
    public void tearDown() throws Exception {
    }
}

@RunWith(MockitoJUnitRunner.class)
We specify the runner we want to use, it might be JUnit runner, the Instrumentation, Automation runner or even a custom runner. It depends on how and where we want to run our test.

@SmallTest
This annotation define the type of test we are runing, where “SmallTest” is usually a Unit Test, a “LargeTest” an end to end UI or Automation test and a “MediumTest” is when we are testing more than one module working together, like an Integration Test. See the table below to compare these different types.
Screen Shot 2016-04-03 at 21.19.34

@Before
The method marked with this annotation will be called every time before a test is launched. It useful to initialise and arrange any data needed for the tests.

@Test
This define a test method. It usually should follow the “Arrange-Act-Assert” pattern:
– Arrange all necessary preconditions and inputs.
– Act on the object or method under test.
– Assert that the expected results have occurred.

@After
This method will be execute after each test and we will use it to release resources, close files, etc.

Running the tests

Finally to run the tests we need to select “Unit Test” on the Build Variant menu. After this we can just right click at the Test package folder and then on “Run Tests..” (or Debug or Run with Coverage).

Screen Shot 2016-04-03 at 21.56.15.png

 

Implementing Integration Tests

As we saw before, these type of test should cover around the rest 30 or 20 percent of our test code base. We will use the Instrumentation and/or Automation frameworks that basically allows us to simulate user interactions on the application that will run in a real device or an emulator.

We are going to use Espresso as our Instrumentation test  framework. With it we can click on buttons, enter texts, do scrolls, etc. See below an example of a Sign Up screen tests.

 

@RunWith(AndroidJUnit4.class)
@LargeTest

public class SingupTest {

    @Rule
    public ActivityTestRule<SignupActivity> mSignupActivityRule = new ActivityTestRule<>(SignupActivity.class);

    @Test
    public void testperformValidCompleteSignup() throws Exception {

        //  Fill up new user fields
        onView(withId(R.id.editTextCreateUserName)).perform(typeText("david_" + System.currentTimeMillis()));
        onView(withId(R.id.editTextCreateEmail)).perform(typeText("david.guerrero@quoders.com_" + + System.currentTimeMillis()));
        onView(withId(R.id.editTextCreatePassword)).perform(typeText("password"));
        onView(withId(R.id.editTextPasswordConfirm)).perform(typeText("password"));

        //  Click on Sign Up button
        onView(withId(R.id.editTextPasswordConfirm)).perform(click());

        //  Check progress dialog is showed
        onView(withText(R.string.signup_progress)).check(matches(isDisplayed()));

        //  Assert Home screen has been launched
        onView(withText(R.string.title_activity_home)).check(matches(isDisplayed()));
    }
}

As we can see in the example, we are introducing all the fields needed to perform a new user registration, then clicking on the Sign Up button and assert that the Home Activity is launched correctly after this.
Notice how we have marked the test with the “LargeTest” annotation and we are running it with the “AndroidJUnit4” runner.
To run this test we now need to change to Build Variant to the “Android Instrumentation Test” option and then we just need to choose where to deploy and run the app and the test, either in a real or emulated device.

Summary

So that was a quite brief introduction to a much more complex subject as the testing strategy in Android. There are much more to talk about testing but that will be probably part of further posts.

You can find these examples on my work in progress open source project Treepolis in Github.

As usual please leave any comments, suggestion or corrections. What’s your testing strategy?

Tagged , ,

A brief introduction to a cleaner Android architecture: The MVP pattern

As the Android platform has been maturing, developers found that the standard approach to organise the architecture and design of the application code wasn’t the best at all. Usually we ended up having a massive monolithic module, an Activity or a Fragment, containing business and UI logic, creating an unmaintainable and untestable messy project.

Google itself haven’t provided so far a good practice guideline or code examples showing a modular and decoupled approach that implements any of the well known and widely used design patterns, like for example MVC which is encouraged by default on the iOS platform or the common MVVM in Microsoft environments.

One of the most common pattern that the community of Android developers has been using for a while and that has got lot of attention is the Model View Presenter (MVP) pattern and we will focus on it on this post. We will not go through a deep academic description of the pattern but we will focus on the advantages and practical use of it. For an awesome analysis of the MVP and other patterns take a look at this classic post from Martin Fowler about GUI architecture.

So what’s MVP?

18289

Basically MVP is an architectural design pattern that divides our application code in three entities in order to achieve a modular design, implementing the separation of concerns concept, allows an easier implementation of unit tests and making possible to reuse and replace modules either of our UI, data or business layer.

MVP is an evolution of MVC and it has multiple variants and implementations. There has been a lot of conversations and debate about the best and proper way to adopt it on Android. I’m going to expone my way which I have been using in a couple of projects and I reckon works better for me. Of course it doesn’t mean is the best or only one that works on Android, so please leave any comment and suggestions if you find any area of improvement.

Ok so let’s see who is who in this approach.

The View

This entity is going to include the visual part of our app, it is only the UI and it will not have any logic or knowledge of the data displayed. The View doesn’t know anything about the business logic or how to get the data it has to show to the user.

Activities, Fragments, Dialogs, etc… would be included in this category. This elements will contain only initialisation and display functionalities of the visual components and elements to display information to the user. It will not contain any functional or business logic like access to database or web server for example.

This module (Activity, Fragment, etc) exports an interface that will be used by the Presenter, which is responsible and have the knowledge and logic about how, when and what to show in the View. This interface will have methods like “showProgressBar”, “showLoginErrorMessage” or “launchSignupActivity”. Here is an example:

public interface WelcomeView {

    void launchHomeActivity();
    void LaunchSignupActivity();
    void closeActivity();

    void setWrongUsernameError();
    void setWrongPasswordError();

    void showLoginErrorAlertDialog();
}

The Presenter

As we mentioned before, this entity is going to have all the logic and knowledge about what, how and when to display in the user interface. It will be responsible of capture events raised by the user when interacting with the UI and perform any action.

The presenter also acts as a bridge between the View and the Model fetching any data needed from the data layer, making any transformation and display this info to the user on the View.
This entity ideally shouldn’t have any dependency of the Android SDK such us Context or Activity references.

The Activity will have a reference to the Presenter interface and it will use it to communicate any event occurred on the View, like the user tap on a button or the user enter any data in a TextView and then it will decide what to do in reaction of that event.

Here is an example of a Presenter interface:

public interface WelcomePresenter {
    void onCreateAccountClick();
    void onActivityResultCalled(int requestCode, int result);
    void onLoginClick();
}

So for example let’s say that if the user tap on a Logout button, the View call the exported method “onLogoutClick” of the Presenter interface. Then the it knows what interactor of the Model layer needs to invoke to perform a Logout action on the app.

Once the log out success callback has been received, the Presenter will perform any action on the View, for example closing the Activity and displaying a home screen Activity.

The Model

In this entity we will include the “interactors” (use cases of our business logic) that will perform and manage any business layer logic and data access, like fetching data from our web service, accessing the database, etc.

Once we have that piece of data the interactor will send it back to the Presenter and this will decide what to do with this data and how to show it to the View as we saw in the previous point.

Here an example of an implementation of an interactor:

public class WelcomeInteractorImpl implements WelcomeInteractor {

    private WelcomeInteractorListener   mListener;

    public WelcomeInteractorImpl(WelcomeInteractorListener listener) {
        this.mListener = listener;
    }

    @Override
    public void loginWithUserName(String username, String password) {

        ParseUser.logInInBackground(username, password, new LogInCallback() {
            public void done(ParseUser user, ParseException e) {
                if (mListener != null) {
                    if (user != null) {
                        mListener.onLoginSuccessful();
                    }
                    else {
                        mListener.onLoginError(e);
                    }
                }
            }
        });
    }
}

Summary

So this is a very brief summary of what is MVP and how to use it on Android to achieve a cleaner, modular and testable source code. This is just an interpretation of the pattern and is not a silver bullet or the perfect solution for our apps, so any comments or critics are more than welcome!

To see an example of this implementation you can take a look to one of my open source experimental apps “Treepolis”. Is still an in progress project and you can find it here in Github
To see a practical example of the pattern used for the Welcome screen and login functionality check this folder.

Tagged , , ,