CHICIO CODING

Dirty clean code. Creative Stuff. Stuff.

React Native: use multiple RCTRootView instances in an existing iOS app

In this post I show you how is it possible to use multiple RCTRootView instances in an existing iOS app.


If we want to start to use React Native in an existing app, it’s really easy. We can have our first React Native component live inside our app by just following the getting started tutorial for existing app. But what happen if we need to use multiple react native component in different parts of our existing apps :fearful:? In this tutorial I will show you how we can use multiple instances of RCTRootView to show different React Native components in different parts of your app. Consider, for example, a simple iOS existing app with React Native. It has two very simple React Native components:

  • BlueScreen, that shows a blue view
  • RedScreen, that shows a red view
class BlueScreen extends React.Component {
    render() {
        return (
            <View style={styles.blue} />
        );
    }
}

class RedScreen extends React.Component {
    render() {
        return (
            <View style={styles.red} />
        );
    }
}

const styles = StyleSheet.create({
    blue: {
        backgroundColor: "#0000FF",
        width: "100%",
        height: "100%"
    },
    red: {
        backgroundColor: "#FF0000",
        width: "100%",
        height: "100%"
    }
});

AppRegistry.registerComponent('BlueScreen', () => BlueScreen);
AppRegistry.registerComponent('RedScreen', () => RedScreen);

On the native side there’s a controller, ReactViewController, that shows React Native components given their name.

class ReactViewController: UIViewController {
    init(moduleName: String) {
        super.init(nibName: nil, bundle: nil)
        view = RCTRootView(bundleURL: URL(string: "http://localhost:8081/index.bundle?platform=ios"),
                           moduleName: moduleName,
                           initialProperties: nil,
                           launchOptions: nil)
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

There’s also another controller, MainViewController, that shows the React Native components described above using multiple instances of the ReactViewController. The UI of the app is very simple: there are two buttons on the view of the MainViewController. A tap on the first one shows the ReactViewController with a RCTRootView that contains the RedComponent. A tap on the second one shows the ReactViewController with a RCTRootView that contains the BlueComponent.
This basically means that in this apps there are multiple RCTRootView, one for each controller created. This instances are kept alive at the same time (because the MainViewController keeps a reference to the two ReactViewController). The code to start the React Native components is the same contained in the getting started tutorial for existing app.

class MainViewController: UIViewController {
    private let blueViewController: ReactViewController
    private let redViewController: ReactViewController

    required init?(coder aDecoder: NSCoder) {
        blueViewController = ReactViewController(moduleName: "BlueScreen")
        redViewController = ReactViewController(moduleName: "RedScreen")
        super.init(coder: aDecoder)
    }
    
    @IBAction func showRedScreen(_ sender: Any) {
        navigationController?.pushViewController(redViewController, animated: true)
    }
    
    @IBAction func showBlueScreen(_ sender: Any) {
        navigationController?.pushViewController(blueViewController, animated: true)
    }
}

If we try to run the app something very strange will happen:

  • if we do a live reload, we will see our React components refreshed multiple times
  • if we press cmd + ctrl + z (shake gesture simulation) in the simulator 2 dev menu will be shown

React Native multiple dev menus

  • if we do a live reload while we’re in debug mode the app could crash

React Native crash multiple view

What’s happening here? Well, there’s something wrong in our code. If we take a look at the comments in the code of React Native for the RCTRootView initializer, we will notice something very strange:

/**
 * - Designated initializer -
 */
- (instancetype)initWithBridge:(RCTBridge *)bridge
                    moduleName:(NSString *)moduleName
             initialProperties:(NSDictionary *)initialProperties NS_DESIGNATED_INITIALIZER;

/**
 * - Convenience initializer -
 * A bridge will be created internally.
 * This initializer is intended to be used when the app has a single RCTRootView,
 * otherwise create an `RCTBridge` and pass it in via `initWithBridge:moduleName:`
 * to all the instances.
 */
- (instancetype)initWithBundleURL:(NSURL *)bundleURL
                       moduleName:(NSString *)moduleName
                initialProperties:(NSDictionary *)initialProperties
                    launchOptions:(NSDictionary *)launchOptions;

Whaaaaaaattttt :laughing:?????!?!?!??? This basically means that the documentation in the getting started is considering only the case where we will have a single RCTRootView instance. So we need to do something to our ReactViewController so that we can keep multiple RCTRootView alive at the same time. The solution to our problem is contained in the comments of the initializer above: we need to use the designated RCTRootView initializer to start to use multiple instances of them at the same time in the app. So the new ReactViewController with the new RCTRootView initialization is the following one:

class ReactViewController: UIViewController {
    
    init(moduleName: String, bridge: RCTBridge) {
        super.init(nibName: nil, bundle: nil)
        view = RCTRootView(bridge: bridge,
                           moduleName: moduleName,
                           initialProperties: nil)
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

Where do we get an instance of RCTBridge for the new init of the ReactViewController and RCTRootView? A new object, ReactNativeBridge, creates a new RCTBridge instance and store it as a property.
The RCTBridge instance needs a RCTBridgeDelegate. Another new object, ReactNativeBridgeDelegate, will be the delegate of the RCTBridge.

class ReactNativeBridge {
    let bridge: RCTBridge
    
    init() {
        bridge = RCTBridge(delegate: ReactNativeBridgeDelegate(), launchOptions: nil)
    }
}

class ReactNativeBridgeDelegate: NSObject, RCTBridgeDelegate {
    
    func sourceURL(for bridge: RCTBridge!) -> URL! {
        return URL(string: "http://localhost:8081/index.bundle?platform=ios")
    }
}

Now it is possible to modify the MainViewController. This controller will create a single ReactNativeBridge with a single RCTBridge instance. This instance will be passed to the two ReactViewController. So they will basically share the same bridge instance.

class MainViewController: UIViewController {
    private let blueViewController: ReactViewController
    private let redViewController: ReactViewController
    private let reactNativeBridge: ReactNativeBridge
    
    required init?(coder aDecoder: NSCoder) {
        reactNativeBridge = ReactNativeBridge()
        blueViewController = ReactViewController(moduleName: "BlueScreen",
                                                 bridge: reactNativeBridge.bridge)
        redViewController = ReactViewController(moduleName: "RedScreen",
                                                bridge: reactNativeBridge.bridge)
        super.init(coder: aDecoder)
    }
    
    @IBAction func showRedScreen(_ sender: Any) {
        navigationController?.pushViewController(redViewController, animated: true)
    }
    
    @IBAction func showBlueScreen(_ sender: Any) {
        navigationController?.pushViewController(blueViewController, animated: true)
    }
}

Now if we try to run the app again everything will work as expected:

  • if we do a live reload, we will see our React components refreshed just one time
  • if we press cmd + ctrl + z in the simulator 1 dev menu will be shown
  • no more crashes with live reload in debug mode

React Native single dev menus

The entire source code of the app used as example for this post is contained in this github repo. Now we’re ready to use multiple React Native components at the same time in our app :relieved:.

Physically based rendering: informal introduction

In this post I will give you an informal introduction (and my personal understanding) about Physically based rendering.


Physically Based Rendering (PBR) is one of the latest and most exciting trend in computer graphics. PBR is “everywhere” in computer graphics. But wait, what is it PBR :fearful:? PBR uses physically correct lighting and shading models to treat light as it behaves in the real world. As a consequence of the fact that what could be seen in a computer graphics application is decided by how light is represented, with PBR it is possible to reach a new level of realism. But wait, what do we mean with “physically correct”?
Before giving an answer and try to give a detail definition of PBR we need to understand well some important concepts.

What is light?

Light is a form of electromagnetic radiation. Specifically, it is a small subset of the entire electromagnetic radiation spectrum with wavelength between 400 nm and 700 nm. The set of studies and techniques that try to describe and measure how the electromagnetic radiation of light is propagated, reflected and transmitted is called radiometry. What are the fundamental quantities described by radiometry? The first one is the called flux, it describes the amount of radiant energy emitted, reflected or transmitted from a surface per unit time. The radiant energy is the energy of an electromagnetic radiation. The unit measure of flux is joules per seconds $\frac{J}{s}$, and it is usually reported with the Greek letter $\phi$.
Other two important quantities of radiometry are irradiance and radiant exitance. The first one described flux arriving at a surface per unit area. The second one describe flux leaving a surface per unit area (Pharr et al., 2010 [1]). Formally irradiance is described with the following equation:

where the differential flux $d\phi$ is computed over the differential area $dA$. It is measured as units of watt per square meter.
Before proceeding to the last radiometry quantity definition, it is useful to give the definition of solid angle. A solid angle is an extension of a 2D angle in 3D on a unit sphere. It is the total area projected by an object on a unit sphere centered at a point $p$. It is measured in steradians. The entire unit sphere corresponds to a solid angle of $4\pi$ (the surface area of the unit sphere). A solid angle is usually indicated as $\Omega$, but it is possible also to represent it with $\omega$, that is the set of all direction vectors anchored at $p$ that point toward the area on the unit sphere and the object (Pharr et al., 2010 [1]). Now it is possible to give the definition of radiance, that is flux density per unit solid angle per unit area:

In this case $dA^{\perp}$ is the projected area $dA$ on a surface perpendicular to $\omega$. So radiance describe the limit of measurement of incident light at the surface as a cone of incident directions of interest ${d\omega}$ becomes very small, and as the local area of interest on the surface $dA$ also becomes very small (Pharr et al., 2010 [1]). It is useful to make a distinction between radiance arriving at a point, usually called incident radiance and indicated with $L_{i}(p,\omega)$, and radiance leaving a point called exitant radiance and indicated with $L_{o}(p,\omega)$. This distinction will be used in the equations described below. It is important also to note another useful property, that connect the two types of radiance:

The rendering equation

The rendering equation was introduced by James Kajiya in 1986 [2]. Sometimes it is also called the LTE, Light Transport Equation. It is the equation that describes the equilibrium distribution of radiance in a scene (Pharr et al., 2010 [3]). It gives the total reflected radiance at a point as a sum of emitted and reflected light from a surface. This is the formula of the rendering equation:

In this formula the meaning of each symbols are:

  • $p$ is a point on a surface in the scene
  • $\omega_{o}$ is the outgoing light direction
  • $\omega_{i}$ is the incident light direction
  • $L_{o}(p,\omega)$ is the exitant radiance at a point $p$
  • $L_{e}(p,\omega)$ is the emitted radiance at a point $p$
  • $\Omega$ is the unit hemisphere centered around the normal at point $p$
  • $\int_{\Omega}…d\omega_{i}$ is the integral over the unit hemisphere
  • $f_{r}(p,\omega_{i},\omega_{0})$ is the Bidirectional Reflectance Distribution Function and we will talk about it in a few moments
  • $L_{i}(p,\omega)$ is the incident radiance arriving at a point $p$
  • $\cos\theta_{i}$ is given by the dot product between 𝜔: and the normal at point $p$, and is the attenuation factor of the irradiance due to incident angle

BRDF

One of the main component of the rendering equation previously described is the Bidirectional Reflectance Distribution Function (BRDF). This function describes how light is reflected from a surface. It represents a constant of proportionality between the differential exitant radiance and the differential irradiance at a point $p$ (Pharr et al., 2010 [1]). The parameter of this function are: the incident light direction, the outgoing light direction and a point on the surface. The formula for this function in terms of radiometric quantities is the following:

The BRDF has two important properties:

  • it is a symmetric function, so for all pair of directions
  • it satisfies the energy conservation principle: the light reflected is less than or equal to the incident light.

A lot of models has been developed to describe the BRDF of different surfaces. In particular, in the last years the microfacet models have gained attention. In these kind of models the surface is represented as composed by infinitely small microfactes that model in a more realistic way the vast majority of surfaces in the real world. Each one of these microfactes has is geometric definition (in particular its normal).
Some specific material surfaces, for example glass, reflect and transmit light at the same time. So a fraction of light goes through the material. For this reason, there’s another function, the Bidirectional Transmittance Distribution Function, BTDF, defined in the same way as the BRDF, but with the directions $\omega_{i}$ and $\omega_{o}$ placed in the opposite hemisphere around $p$ (Pharr et al., 2010 [1]). It is usually indicated as $f_{t}(p,\omega_{i},\omega_{o})$. The Fresnel equations tries to define the behaviour of light between different surfaces. They also help us to get the balance between different kind of reflections changes based on the angle at which you view the surface.

Physically Based Rendering

So let’s go back to our original question: What is PBR? PBR is a model that enclose a set of techniques that try to simulate how the light behaves in the real world. Taking an extraction from the Wikipedia definition:

PBR is often characterized by an approximation of a real, radiometric bidirectional reflectance distribution function (BRDF) to govern the essential reflections of light, the use of reflection constants such as specular intensity, gloss, and metallicity derived from measurements of real-world sources, accurate modeling of global illumination in which light bounces and/or is emitted from objects other than the primary light sources, conservation of energy which balances the intensity of specular highlights with dark areas of an object, Fresnel conditions that reflect light at the sides of objects perpendicular to the viewer, and accurate modeling of roughness resulting from microsurfaces.

You can see from the definition that PBR is a model that uses all the concepts we saw previously in this article to try to get the most accurate results in terms of realism in a computer graphics applications. PBR engines and asset pipelines let the artist define materials in terms of more realistic components, instead of tweaking ad-hoc parameters based on the type of the surface. Usually in these kind of engine/asstes pipeline the main parameter used to specify a surface features are:

  • albedo/diffuse: this component controls the base color/reflectivity of the surface
  • metallic: this component specifies the is the surface is metallic or not
  • roughness: this component specifies how rough a surface is on a per texel basis
  • normal: this component is a classical normal map of the surface

What results can you achieve suing PBR? These are two example images: the first one is taken from my physically based spectral path tracing engine Spectral Clara Lux Tracer and the second one is taken from PBRT, the physically based engine described in the book “Physically based rendering: from theory to implementation” by M. Pharr, W. Jakob, G. Humphreys.

Pbr examples

How coooool are these images???? :sunglasses: We are at the end of the introduction. I hope now it is at least clear what is PBR :relaxed:!! See you for other stuff about computer graphics and PBR :blush:.



[1] M. Pharr and G. Humphreys, “Color and radiometry,” in Physically based rendering: from theory to implementation, 2nd Edition ed., Burlington, Massachusetts: Morgan Kaufmann, 2010, ch. 5, pp. 261-297.
[2] J. T. Kajiya, “The Rendering Equation,” in SIGGRAPH ‘86, Dallas, 1986, pp. 143-150.
[3] M. Pharr and G. Humphreys, “Light transport I: surface reflection,” in Physically based rendering: from theory to implementation, 2nd ed., Burlington, Morgan Kaufmann, 2010, ch. 15, pp. 760-770.

React Native and Realm: custom manual link for an iOS app with custom directory structure

In this post I will show you how to install realm as a dependency in a React Native project with custom folders structure without using react-native link command.


What is React Native? It is one of the most successful and loved mobile development framework. It let you build real native mobile application using Javascript. It has been developed by Facebook. Let’s see the definition from the official website:

Build native mobile apps using JavaScript and React. React Native lets you build mobile apps using only JavaScript. It uses the same design as React, letting you compose a rich mobile UI from declarative components. With React Native, you don’t build a “mobile web app”, an “HTML5 app”, or a “hybrid app”. You build a real mobile app that’s indistinguishable from an app built using Objective-C or Java. React Native uses the same fundamental UI building blocks as regular iOS and Android apps. You just put those building blocks together using JavaScript and React.

Cool :sunglasses:!!!! Isn’t it? Write an app using Javascript with the same performance of native code. You can also reuse your native component and bridge them to the javascript side.
Most of the time the React Native framework will help you also to manage dependencies inside you project. But sometimes, especially if your project doesn’t follow the standard React Native directories structure you can have some problem when you try to link you external library.
While I was working on an existing native app integrated with React Native that has a custom directories structure for the react-native and native code, I found some problem to add Realm, the famous open source dbms, as a dependency to the project.
In this post I will show you an example of how you can add Realm to your app that has a custom React Native installation. Let’s start :cold_sweat:!! To describe the installation process I will use a sample app I created for this post called ReactNativeRealmManualLink. You can find it with realm installed in this github repo.
Suppose you have a project like the one I shared above, in which React Native is contained in a subfolder of the iOS project, instead of the other way around in a standard React Native installation.

React Native realm directories

First, to add realm as a dependency we need to install it through npm with following command.

npm install --save realm

Then we try to link the library to the native code with the standard React Native command.

react-native link realm

But here something strange happens: as you can see from the screenshot below the command fails to link the library. So we need to find another way to install the library.

React Native realm link fails

Usually, if the previous command fails, you have to do the manual linking. To do it we navigate inside the node_modules folder, contained in the React Native folder of our project, to found the realm folder. Inside it you will find an Xcode project named RealmReact, that you have to drag into our project. After that we have to add a reference to the static library libRealmReact and compile the project.

React Native realm manual link step 1 React Native realm manual link step 2

Now you would expect that everything works fine but…

React Native realm manual link fails

What’s happening? The RealmReact project is expecting the React Native headers in a relative position with respect to its original position. Arrrgghhh :rage:!! We need to find another way…

What can we do? We can start by observing that the RealmReact project is just a “container project” for:

  • RealmJS project, that generates two static libraries libRealmJS.a and libGCDWebServers.a
  • an Objective-C++ class RealmReact
  • an Objective-C++ file RealmAnalytics

So we can try to modify our main project by:

  • adding the RealmJS project and the Objective-C++ files/classes as references
  • linking the static libraries libRealmJS.a and libGCDWebServers.a to our main project and see if everything works

React Native realm custom manual link step 1 React Native realm custom manual link step 2

Now we need to add to the Header search path option of our main project the paths that were setted in the RealmReact project. In this way the RealmJS project will be able to find some headers it needs. You can find the complete list of the folder that we need to add in the screenshot below.

React Native realm header search path

Now if we try to compile our app we expect that everything works fine but…ERROR :warning::fire:!!! The build fails :boom:!!!

React Native realm C++ error

It seems like that in order to be able to compile the C++ source code contained in RealmJS we need to set a recent C++ version in our project setting that supports some new features like auto return type on static function. We can set it to C++ 14 and set the Standard Library to the LLVM one with C++ 11 support.

React Native realm C++ setup

One final step is to remove the flag -all_load from the Other linker flag option of the main project (if you have it). In this way we avoid to load all Objective-C symbols and have the “duplicated symbols” error.

React Native realm all_load flag

We are now ready to build our app and see if everything works. To do this we create a sample native view controller that has a RCTRootView

class ReactNativeRealmController: UIViewController {
    override func viewDidLoad() {
        let jsCodeLocation = URL(string: "http://localhost:8081/index.bundle?platform=ios")
        view = RCTRootView(
            bundleURL: jsCodeLocation,
            moduleName: "ReactNativeRealmScreen",
            initialProperties: nil,
            launchOptions: nil
        )
    }
}

and a sample react component with some realm write/read operations.

const Realm = require('realm');

class ReactNativeRealmScreen extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            realm: null
        };±
    }

    componentWillMount() {
        Realm.open({
            schema: [{name: 'Band', properties: {name: 'string', singer: 'string'}}]
        }).then(realm => {
            realm.write(() => {
                realm.create('Band', {name: 'HIM', singer: 'Ville Valo'});
            });
            this.setState({ realm });
        });
    }

    render() {
        const message = this.state.realm
            ? 'The singer of HIM band is: ' + this.state.realm.objects('Band').filtered('name = "HIM"')[0].singer
            : 'Loading...';

        return (
            <View style={styles.container}>
              <Text>
                  {message}
              </Text>
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#FFFFFF',
    }
});

AppRegistry.registerComponent('ReactNativeRealmScreen', () => ReactNativeRealmScreen, false);

We are now ready to build our app and, as expected, everything works fine.

React Native realm build works

That’s it!! As I told you before you can find the complete example in this github repo. We are now ready to create our React Native component with realm :bowtie:.

Model View Presenter on Android: unit test for everything

In this post I will talk about the model view presenter architectural pattern and how it can improve you unit test and your TDD workflow when developing an Android application.


In a previous post I talked about the Model View Presenter architectural pattern and how it could help you to develop apps fully tested. But what about Android? Can we reach the same level of testability using this pattern and improve our TDD workflow? Let’s find it out :smirk:!!
In this post we will try to develop the same application we developed on iOS in the previous post: a simple product catalog that shows a list of products. When you tap on one of them, its details is shown. Below you can find the same mockup we used for the iOS version.

Model view presenter mockup

Let’s start by creating a Product class. We need also to create a ProductsRepository class: in our case it will be a fake one that return to listener a list of products after 3 seconds. We do this to simulate a web service call. This is our implementation for the Product class:

public class Product {
    private String name;
    private String description;
    private String image;

    public Product(String name, String description, String image) {
        this.name = name;
        this.description = description;
        this.image = image;
    }

    public String getName() {
        return name;
    }

    public String getDescription() {
        return description;
    }

    public String getImage() {
        return image;
    }
}

And below there is the implementation of our ProductsRepository.

public class ProductsRepository implements Repository {
    private ProductsRepositoryListener productsRepositoryListener;

    @Override
    public void setListener(ProductsRepositoryListener productsRepositoryListener) {
        this.productsRepositoryListener = productsRepositoryListener;
    }

    public void get() {
        new Timer().schedule(new TimerTask() {
            @Override
            public void run() {
                Product[] products = {
                    new Product("Car", "A beautiful car", "car"),
                    new Product("Book", "", "book")
                };
                productsRepositoryListener.onRetrieved(products);
            }
        }, 3000);
    }
}

As we said before, and as you can see above the repository return to a ProductsRepositoryListener the list of products. So the interface definition for that listener is:

public interface ProductsRepositoryListener {
    void onRetrieved(Product[] products);
}

Now we can start to create our presenter. First of all we will define a ProductsView that will be responsible to implement the real platform dependent UI code. Our presenter will be responsible for:

  • the start of the view in the onStart() method. In this method it will update the view title, show a loading status and more important it will start the retrieve of the product list and become its listener.
  • listening to the repository callback when the products are retrieve. So our presenter will implement the ProductsRepositoryListener interface and pass to the view the updated product list.
  • the show detail action in the onSelected(Product product) method. In this case it will need to check that we have a valid product and eventually show its detail (or an error message).

First let’s see our ProductsView interface:

public interface ProductsView {
    void showLoadingStatus();
    void hideLoadingStatus();
    void show(String title);
    void show(Product[] products);
    void showErrorWith(String message);
    void showDetailFor(Product product);
}

Our ProductsPresenter implementation will be the following:

public class ProductsPresenter implements ProductsRepositoryListener {
    private ProductsView productsView;
    private Repository productsRepository;

    public ProductsPresenter(ProductsView productsView, Repository productsRepository) {
        this.productsView = productsView;
        this.productsRepository = productsRepository;
    }

    public void onStart() {
        productsView.show("Products");
        productsView.showLoadingStatus();
        productsRepository.setListener(this);
        productsRepository.get();
    }

    @Override
    public void onRetrieved(Product[] products) {
        tryToShowTheProducts(products);
        productsView.hideLoadingStatus();
    }

    private void tryToShowTheProducts(Product[] products) {
        if (isValidProduct(products)) {
            productsView.show(products);
        } else {
            productsView.showErrorWith("No products available");
        }
    }

    private boolean isValidProduct(Product[] products) {
        return products != null;
    }

    public void onSelected(Product product) {
        if (hasValidDescription(product)) {
            productsView.showDetailFor(product);
        } else {
            productsView.showErrorWith("Product without description");
        }
    }

    private boolean hasValidDescription(Product product) {
        return !product.getDescription().equals("");
    }
}

And this are our presenter tests:

public class ProductsPresenterTest {
    private ProductsView productsView;
    private Repository productsRepository;
    private ProductsPresenter productsPresenter;
    private final Product[] products  = new Product[]{new Product("aName", "aDescription", "anImage")};
    private final Product product  = new Product("aName", "aDescription", "anImage");

    @Test
    public void onStart() throws Exception {
        givenAProductsRepository();
        givenAProductsView();
        givenAProductsPresenter();
        whenTheProductsPresenterStarts();
        thenTheTitleIsDisplayed();
        thenTheProductViewShowsLoadingStatus();
        thenTheProductsPresenterBecomeListenerOfTheRepository();
        thenTryToRetrieveProduct();
    }

    @Test
    public void onProductsRetrieved() throws Exception {
        givenAProductsRepository();
        givenAProductsView();
        givenAProductsPresenter();
        whenTheProductsHaveBeenRetrieved();
        thenTheProductsViewShowsTheProducts();
        thenTheProductsViewHidesLoadingStatus();
    }

    @Test
    public void onNoProductsRetrieved() throws Exception {
        givenAProductsRepository();
        givenAProductsView();
        givenAProductsPresenter();
        whenTheProductsHaveNotBeenRetrieved();
        thenTheProductsViewShowsAnErrorMessage();
        thenTheProductsViewHidesLoadingStatus();
    }

    @Test
    public void onProductSelectedWithDescription() throws Exception {
        givenAProductsRepository();
        givenAProductsView();
        givenAProductsPresenter();
        whenAProductIsSelected();
        thenTheViewShowsTheProductDetail();
    }

    private void givenAProductsPresenter() {
        productsPresenter = new ProductsPresenter(productsView, productsRepository);
    }

    private void givenAProductsRepository() {
        productsRepository = mock(Repository.class);
    }

    private void givenAProductsView() {
        productsView = mock(ProductsView.class);
    }

    private void whenTheProductsPresenterStarts() {
        productsPresenter.onStart();
    }

    private void whenTheProductsHaveBeenRetrieved() {
        productsPresenter.onRetrieved(products);
    }

    private void whenTheProductsHaveNotBeenRetrieved() {
        productsPresenter.onRetrieved(null);
    }

    private void whenAProductIsSelected() {
        productsPresenter.onSelected(product);
    }

    private void thenTheTitleIsDisplayed() {
        verify(productsView).show(anyString());
    }

    private void thenTryToRetrieveProduct() {
        verify(productsRepository).get();
    }

    private void thenTheProductsPresenterBecomeListenerOfTheRepository() {
        verify(productsRepository).setListener(productsPresenter);
    }

    private void thenTheProductViewShowsLoadingStatus() {
        verify(productsView).showLoadingStatus();
    }

    private void thenTheProductsViewHidesLoadingStatus() {
        verify(productsView).hideLoadingStatus();
    }

    private void thenTheProductsViewShowsTheProducts() {
        verify(productsView).show(products);
    }

    private void thenTheProductsViewShowsAnErrorMessage() {
        verify(productsView).showErrorWith(anyString());
    }

    private void thenTheViewShowsTheProductDetail() {
        verify(productsView).showDetailFor(product);
    }
}

It’s easy to see that with our presenter we are able to test, also on Android, each UI operation without have to deal with platform dependent code in our unit test. As you can see our unit test are written, as on iOS, following the typical Behaviour Driven Development given-than-when approch. Now the same question we had in the iOS version of the app will start floating around in your head: who is our view? Fragments!!! On Android we will use fragments as our View for all the UI operation :sunglasses:. So let’s see our ProductsFragment implementation:

public class ProductsFragment extends Fragment implements ProductsView {
    private RecyclerView productsRecyclerView;
    private ProductsPresenter productsPresenter;
    private LinearLayoutManager productsLinearLayoutManager;
    private ProgressBar productsProgressBar;
    private ProductsNavigator productsNavigator;

    public static ProductsFragment newInstance(ProductsNavigator productsNavigator) {
        ProductsFragment productsFragment = new ProductsFragment();
        productsFragment.productsNavigator = productsNavigator;
        return productsFragment;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_products, container, false);
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        bindViews();
        initializeDependencies();
    }

    @Override
    public void onResume() {
        super.onResume();
        productsPresenter.onStart();
    }

    private void initializeDependencies() {
        ProductsRepository productsRepository = new ProductsRepository();
        productsPresenter = new ProductsPresenter(this, productsRepository);
    }

    private void setupProductRecyclerViewUsing(final Product[] products) {
        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                setupLayoutManager();
                setupStyle();
                setupAdapterUsing(products);
            }
        });
    }

    private void setupAdapterUsing(Product[] products) {
        ProductsAdapter productsAdapter = new ProductsAdapter(products, productsPresenter);
        productsRecyclerView.setAdapter(productsAdapter);
    }

    private void setupLayoutManager() {
        productsLinearLayoutManager = new LinearLayoutManager(getActivity());
        productsRecyclerView.setLayoutManager(productsLinearLayoutManager);
    }

    private void setupStyle() {
        productsRecyclerView.setHasFixedSize(true);
        DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(
                productsRecyclerView.getContext(),
                productsLinearLayoutManager.getOrientation());
        productsRecyclerView.addItemDecoration(dividerItemDecoration);
    }

    private void bindViews() {
        productsProgressBar = (ProgressBar) getView().findViewById(R.id.products_progress_bar);
        productsRecyclerView = (RecyclerView) getView().findViewById(R.id.products_recycler_view);
    }

    @Override
    public void showLoadingStatus() {
        productsProgressBar.setVisibility(View.VISIBLE);
    }

    @Override
    public void hideLoadingStatus() {
        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                productsProgressBar.setVisibility(View.GONE);
            }
        });
    }

    @Override
    public void show(String title) {
        getActivity().setTitle(title);
    }

    @Override
    public void show(Product[] products) {
        setupProductRecyclerViewUsing(products);
    }

    @Override
    public void showErrorWith(final String message) {
        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                showErrorAlertWith(message);
            }
        });
    }

    private void showErrorAlertWith(String message) {
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        builder.setMessage(message)
                .setTitle(R.string.dialog_error_title)
                .setPositiveButton(R.string.dialog_error_ok_button, new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        dialog.dismiss();
                    }
                });
        AlertDialog errorAlert = builder.create();
        errorAlert.show();
    }

    @Override
    public void showDetailFor(Product product) {
        productsNavigator.goToDetailOf(product);
    }
}

As you can see it implements all the UI operation we defined in our view as the UIViewController do on iOS. But if you look well we have a little difference between the two platform. In the Android platform the tap on a product is managed in the adapter, so the presenter is passed to this component to manage the product selection. Let’s see the implementation of our ProductsPresenter:

class ProductsAdapter extends RecyclerView.Adapter<ProductsAdapter.ViewHolder> {
    private Product[] products;
    private ProductsPresenter productsPresenter;

    ProductsAdapter(Product[] products, ProductsPresenter productsPresenter) {
        this.products = products;
        this.productsPresenter = productsPresenter;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View rowProductView = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_product, parent, false);
        return new ViewHolder(rowProductView, productsPresenter);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        holder.textView.setText(products[position].getName());
        holder.product = products[position];
    }

    @Override
    public int getItemCount() {
        return products.length;
    }

    static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        private ProductsPresenter productsPresenter;
        TextView textView;
        Product product;

        ViewHolder(View itemView, ProductsPresenter productsPresenter) {
            super(itemView);
            textView = (TextView) itemView.findViewById(R.id.product_name_text_view);
            textView.setOnClickListener(this);
            this.productsPresenter = productsPresenter;
        }

        @Override
        public void onClick(View v) {
            productsPresenter.onSelected(product);
        }
    }
}

There’s also another little difference between the Android and the iOS version. If you look carefully in the showDetailFor(Product product) method, that is called after the product selected is checked in the presenter, there is another component responsible to manage the navigation between the screen of our app. In particular, the screen of our app will be Fragment objects and there will be an Activity, the ProductsActivity, that will implement the ProductsNavigator interface and will be responsible to manage the correct navigation between fragments in the app. Let’s see in order the ProductsNavigator interface:

public interface ProductsNavigator {
    void goToDetailOf(Product product);
}

And the ProductsActivity implementation:

public class ProductsActivity extends AppCompatActivity implements ProductsNavigator {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_products);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        showFragment(ProductsFragment.newInstance(this));
    }

    private void showFragment(Fragment fragment) {
        FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
        fragmentTransaction.setCustomAnimations(
                R.animator.enter,
                R.animator.exit,
                R.animator.pop_enter,
                R.animator.pop_exit
        );
        fragmentTransaction.replace(R.id.products_activity_content, fragment);
        fragmentTransaction.addToBackStack("ProductsStack");
        fragmentTransaction.commit();
    }

    @Override
    public void goToDetailOf(Product product) {
        showFragment(ProductDetailFragment.newInstance(product));
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                onBackPressed();
                break;
        }
        return false;
    }

    @Override
    public void onBackPressed() {
        if (getFragmentManager().getBackStackEntryCount() > 1) {
            getFragmentManager().popBackStack();
        } else {
            finish();
        }
    }
}

Ok, now we are ready to implement our product detail. First of all we define the new ProductDetailView:

public interface ProductDetailView {
    void show(String title);
    void show(Product product);
    void showErrorWith(String message);
}

And then our presenter:

public class ProductDetailPresenter {
    private ProductDetailView productDetailView;
    private Product product;

    public ProductDetailPresenter(ProductDetailView productDetailView, Product product) {
        this.productDetailView = productDetailView;
        this.product = product;
    }

    public void onStart() {
        productDetailView.show("Product");
        if (isValidProduct()) {
            productDetailView.show(product);
        } else {
            productDetailView.showErrorWith("Product not valid");
        }
    }

    private boolean isValidProduct() {
        return product != null;
    }
}

And its unit tests:

public class ProductDetailPresenterTest {
    private ProductDetailPresenter productDetailPresenter;
    private ProductDetailView productDetailView;
    private Product product;

    @Test
    public void onStartWithValidProduct() throws Exception {
        givenAValidProduct();
        givenAProductDetailView();
        givenAProductDetailPresenter();
        whenThePresenterStarts();
        thenTheTitleIsShown();
        thenTheProductDetailIsShown();
    }

    @Test
    public void onStartWithInvalidProduct() throws Exception {
        givenAnInvalidProduct();
        givenAProductDetailView();
        givenAProductDetailPresenter();
        whenThePresenterStarts();
        thenTheTitleIsShown();
        thenAnErrorMessageIsDisplayed();
    }

    private void givenAValidProduct() {
        product = new Product("aName", "aDescription", "anImage");
    }

    private void givenAnInvalidProduct() {
        product = null;
    }

    private void givenAProductDetailView() {
        productDetailView = mock(ProductDetailView.class);
    }

    private void givenAProductDetailPresenter() {
        productDetailPresenter = new ProductDetailPresenter(productDetailView, product);
    }

    private void whenThePresenterStarts() {
        productDetailPresenter.onStart();
    }

    private void thenTheProductDetailIsShown() {
        verify(productDetailView).show(product);
    }

    private void thenTheTitleIsShown() {
        verify(productDetailView).show(anyString());
    }

    private void thenAnErrorMessageIsDisplayed() {
        verify(productDetailView).showErrorWith(anyString());
    }
}

And finally our ProductDetailFragment:

public class ProductDetailFragment extends Fragment implements ProductDetailView {
    private Product product;
    private ImageView productImageView;
    private TextView productNameTextView;
    private TextView productDescriptionTextView;
    private ProductDetailPresenter productDetailPresenter;

    public static ProductDetailFragment newInstance(Product product) {
        ProductDetailFragment productDetailFragment = new ProductDetailFragment();
        productDetailFragment.product = product;
        return productDetailFragment;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_product_detail, container, false);
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        bindViews();
        initializeDependencies();
    }

    @Override
    public void onResume() {
        super.onResume();
        productDetailPresenter.onStart();
    }

    private void bindViews() {
        productImageView = (ImageView) getActivity().findViewById(R.id.product_image_detail_image_view);
        productNameTextView = (TextView) getActivity().findViewById(R.id.product_name_detail_text_view);
        productDescriptionTextView = (TextView) getActivity().findViewById(R.id.product_description_detail_text_view);
    }

    private void initializeDependencies() {
        productDetailPresenter = new ProductDetailPresenter(this, product);
    }

    @Override
    public void show(String title) {
        getActivity().setTitle(title);
    }

    @Override
    public void show(Product product) {
        productImageView.setImageDrawable(getActivity().getDrawable(getActivity().getResources().getIdentifier(
                product.getImage(),
                "drawable",
                getActivity().getPackageName()
        )));
        productNameTextView.setText(product.getName());
        productDescriptionTextView.setText(product.getDescription());
    }

    @Override
    public void showErrorWith(String message) {
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        builder.setMessage(message)
                .setTitle(R.string.dialog_error_title)
                .setPositiveButton(R.string.dialog_error_ok_button, new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        dialog.dismiss();
                    }
                });
        AlertDialog errorAlert = builder.create();
        errorAlert.show();
    }
}

That’s it!!!!! You’ve made it!!! Now you master the Model View Presenter architectural pattern on Android and you’re ready to rock with unit test on all the main mobile platform on the market (somebody said Windows Phone!?!?!?!?!? :stuck_out_tongue_closed_eyes:).

Model view presenter platforms

Clean Code: meaningful names

In this post I will talk about clean code and how important are the name you choose while you’re developing software.


I always cared about the software I developed. I also always though that what makes a real professional software developer is how much he/she care about the software he/she is creating: the approach to the problem, the attention to details in code, the passion put into creating every single line of code, the focus on the mission to solve his/her customer problems with your software.
When I started to work at lastminute.com group I discovered that I’m not the only one to think about software development in this way.
In fact an entire new approach to software development has been create by Robert Cecil Martin, known as “Uncle Bob” (whatt??!?!!? :stuck_out_tongue:) and famous also to be the guy that invented the SOLID principles. The name of this new approach to software development is clean code.
So as I promised in my first post on this blog I will publish a series of articles in which I will talk about the foundation of clean code and my personal experiences with it. So let’s start the discussion with one of the principles of clean code that impressed me the most: meaningful naming.

Uncle bob meaningful names

As stated by Uncle Bob in the beautiful meme above, this principle is simple: choose your name carefully. But what does it really mean to “choose carefully”? :confused:. Choosing the right names means the following thing:

  • Names should releal intent. Names should answer why a variable, a class or a method exists, what it does and how it must be used.
  • Avoid disinformation. Names should not contains false clues about the scope of a variable, method or class. Taking an example from Uncle Bob’s clean code: “Do not refer to a grouping of accounts as an accountList, unless it is actually a list…So accountGroups or just plain accounts would be better”.
  • Don’t use noise words. Adding in the name something like “Info” , “Data” doesn’t give you any value.
  • Use pronounceable names. This is simple: use names that humans can pronounce without feeling stupid.
  • Use searchable names. Avoid single-letter names and numeric constants that make your components harder to find.
  • Avoid encodings. Avoid unnecessary encoding notation, like for example Hungarian Notation in which the name of a variable or function indicates its type.
  • Avoid member prefix. Don’t add unnecessary name prefix.
  • Avoid encoding interface and implementations. Avoid encoding interface with “I” and concrete implementation with “Impl”. If you really need to encode, do it for the implementation.
  • Use noun or noun phrase for classes.
  • Use verb or verb phrase for methods.
  • One word per concept. Choose a word for a concept and always use it each time you have to refer to it in code.
  • Use solution domain names. Your code will be read by other programmers. Math names, algorithm names, pattern names are all good choices.
  • Use problem domain names. If no “programmer oriented name” exists, go with names taken from the problem domain.

Let’s see an example to understand the real value of naming classes, methods, functions and variable in the right way. For example, take a look at the following C++ code:

struct pt {
    float x;
    float y;
    float z;
};

struct mt {
public:
    float m[4][4];
};

class Obj {
public:
    bool act;
    mt matr;
    std::vector<pt> ms;
};

class GameManager {
public:
    
    GameManager(std::vector<Obj> anObjList){
        objList = anObjList;
    }
    
    std::vector<Obj> get() {
        std::vector<Obj> newObjList;
        for (auto currObj : newObjList) {
            if (currObj.act && currObj.ms.size() > 0) {
                newObjList.push_back(currObj);
            }
        }
        return newObjList;
    }
    
private:
    
    std::vector<Obj> objList;
};

Even if you can maybe get a feeling of what is going, it’s hard to really understand all the details of this code, and every class, struct is supposed to do and to represent. What are pt and mt???? What is supposed to represent a GameManager and an Obj? And the method get, what wants to get????? :cold_sweat:. You can see that a lot of things are a little bit obscure in this code.
We can try to refactor it following the names guidelines we exposed above. Do you think the code will improve in this way? You can judge it by yourself:

struct Point {
    float x;
    float y;
    float z;
};

struct Matrix {
public:
    float values[4][4];
};

class GameObject {
public:
    bool isActive;
    Matrix transformation;
    std::vector<Point> mesh;
};

class Scene {
public:
    
    Scene(std::vector<GameObject> newGameObjects){
        gameObjects = newGameObjects;
    }
    
    std::vector<GameObject> getValidGameObjects() {
        std::vector<GameObject> activeGameObjects;
        for (auto gameObject : gameObjects) {
            if (isValid(gameObject)) {
                activeGameObjects.push_back(gameObject);
            }
        }
        return activeGameObjects;
    }
    
private:
    
    std::vector<GameObject> gameObjects;
    
    bool isValid(GameObject gameObject) {
        return gameObject.isActive && isValid(gameObject.mesh);
    }
    
    bool isValid(std::vector<Point> mesh) {
        return mesh.size() > 0;
    }
};

Whoaaah!! I mean, the code now seems self explained. Each instruction appears more clear in its intents. Each class, struct and method doesn’t need any additional comment/documentation. I think it’s really amazing how some changes to the names could improve the quality of a piece of code dramatically like in our case. We’re done with names :relieved:. You can find the complete example here I hope that this article will convince you that the names you choose define how much you code is “beautiful” in terms of readability and also, more import, maintainability. Quoting what Grady Booch said about clean code:

Clean Code reads like a well-written prose.

Choosing the right names is the first step to make your code more similar to a well-written prose.