Categories
Programming

What is Declarative UI?

Jetpack Compose is the latest Android UI development framework from Google that nowadays piques my interest. Jumping from using Java to Kotlin was for the most part an enjoyable experience: I feel I can be expressive and more efficient with Kotlin. I get that same feeling whenever I’m digging further into Jetpack Compose, compared to the usual method of using XML files for UI development (also known as the imperative paradigm).

I haven’t actually used Jetpack Compose in production, and in this post I’d like to get to know it better by nerding out on its paradigm, declarative UI.

What is Jetpack Compose? From the announcement post:

Jetpack Compose is a fully declarative component-based approach, meaning you describe your UI as functions that transform data into a UI hierarchy. When the underlying data changes, the Compose framework automatically updates the UI hierarchy for you, making it simple to build UIs easily and quickly.

(emphasis mine)

This matches this cool formula I found on Flutter’s “Start thinking declaratively” documentation:

A mathematical formula: UI = f(state). 'UI' is the layout on the screen. 'f' is your build methods. 'state' is the application state.

What’s the difference between declarative and imperative? Let’s start with digging linguistically. These are definitions from dictionary.com:

declare [ dih-klair ]
verb
to make known or state clearly, especially in explicit or formal terms

imperative [ im-per-uh-tiv ]
adjective
of the nature of or expressing a command; commanding.

If we bring these definitions back to UI development, what does it mean to declare/state a user interface, compared to commanding a user interface?

I found this illuminating example from a PDF lecture from MIT about Declarative UI. Declarative UI can be found within this HTML example:

<div id=“main”>
<div id=“toolbar”>
<button>
<img src=“cut.png”></img>
Cut
</button>
</div>
<textarea id=“editor”></textarea>
</div>

And here’s how a relatively similar UI can be done imperatively in Java:

JPanel main = new JPanel();
JPanel toolbar = new JPanel();
JButton button = new JButton();
button.setIcon(…);
button.setLabel(“Cut”);
toolbar.add(button);
main.add(toolbar);
JTextArea editor = new JTextArea();
main.add(editor);

The way I understand it, the HTML is about describing the UI I want to display. It’s the what. Conversely, the Java example has commands in it (create new toolbar, create new button, set the button label, and so on). It’s the how. The difference between what and how seems to be the simplest way to explain the declarative vs imperative paradigm.

Declarative paradigm used on UI development are pretty popular, lately. Prominent examples are:

  • ReactJS in JavaScipt development
  • SwiftUI in iOS
  • Jetpack Compose in Android
  • Flutter for multi-platform development

It is often described that using the declarative paradigm, the key idea is to think about how a UI component should look like under any possible states. For example: how should an input box looks like if it’s empty? What if the user entered invalid information?

When writing React, it’s often good not to think of how you want to accomplish a result, but instead what the component should look like in its new state.

“Declarative vs Imperative Programming”

Coming back to the formula above, it means that essentially we’ll be writing component builder functions where we declare how the component should look like, given some parameters for the state.

From Jonathan Romano:

Benefits you get from declarative programming are largely in making code read more naturally. It allows for your code to visually convey structure and meaning. It allows for the entirety of the intent of some code to be described in one place. It allows a developer to spend less time parsing and instead jump right to the answer of “what does this code do?” It can also mean abstracting away the details of complex APIs behind a cleaner interface, letting someone else deal with the complexity of making sure everything is executed properly.

With Android development, the common, imperative way is to use XML layout files to declare the UI components, then we mutate and manipulate them inside the Java/Kotlin activity/fragment/others classes. The structure and meaning are separated. They’re okay once I’m used to it, however the declarative paradigm indeed seems like an improvement.

Here’s an example code from Jetpack Compose’s tutorial:

@Composable
fun NewsStory() {
    val image = imageResource(R.drawable.header)
    Column(
        modifier = Modifier.padding(16.dp)
    ) {
        val imageModifier = Modifier
            .preferredHeight(180.dp)
            .fillMaxWidth()
            .clip(shape = RoundedCornerShape(4.dp))

        Image(image, modifier = imageModifier,
                  contentScale = ContentScale.Crop)
        Spacer(Modifier.preferredHeight(16.dp))

        Text("A day in Shark Fin Cove")
        Text("Davenport, California")
        Text("December 2018")
    }
}

It’s for creating a “news story” component with an image at the top, then some text below it. The fun part is, that is all that’s needed. There’s no XML layout file anymore, and to me they’re so much easier to read.

Of note, see how the “news story” component above is set as a function: fun NewsStory(), which reminds me again to Flutter’s formula UI = f(state). This encourages creations of custom UI components that can be reused whenever needed.

Categories
Programming

What Exactly is a “Repository”?

The Repository pattern is one of the concepts frequently used and mentioned within Android Architecture Components. As English is not my first language, I’m drawing a blank in my head whenever I read or hear the term “repository” itself. I have some abstract idea about what it is, mostly from the concept of Github repositories: it seems to be a central place for something.

In my experience, not understanding an English term is a common barrier to having a better intuition of a programming concept. I would read about something new and would have a hard time connecting a term that drew a blank in my mind, to the larger understanding of the concept. So today I figured I’ll geek out a little bit and see what the “repository” word really means.

According to Merriam-Webster, the word means:

: a place, room, or container where something is deposited or stored

This definition matches my understanding of a Git repository: it’s a place where the code is stored.

What about when the term is used in Android Architecture Components? From this Codelab:

A repository class abstracts access to multiple data sources. The repository is not part of the Architecture Components libraries, but is a suggested best practice for code separation and architecture. A Repository class provides a clean API for data access to the rest of the application.

and

A Repository manages queries and allows you to use multiple backends. In the most common example, the Repository implements the logic for deciding whether to fetch data from a network or use results cached in a local database.

Uh, what? That sounds like a lot of things it’s doing other than just being a storage.

The Codelab also provides this graphic:

Repository concept in Android Architecture Components
Repository concept in Android Architecture Components

I found a clearer explanation from an article about the Repository pattern:

[The repository] will persist your objects sans the need of having to know how those objects would be actually persisted in the underlying database, i.e., without having to be bothered about how the data persistence happens underneath. The knowledge of this persistence, i.e., the persistence logic, is encapsulated inside the Repository.

In essence, the Repository design pattern facilitates de-coupling of the business logic and the data access layers in your application with the former not having to have any knowledge on how data persistence would actually take place.

In using the Repository design pattern, you can hide the details of how the data is eventually stored or retrieved to and from the data store. This data store can be a database, an xml file, etc. You can apply this design pattern to even hide how data that is exposed by a web service or an ORM is accessed. Martin Fowler states: “Mediates between the domain and data mapping layers using a collection-like interface for accessing domain objects.”

So from the above, it sounds like the Repository pattern is more of a way to allow access to various data sources, without the accessor having to know about how the data sources are created. It’s not just a dumb place to store things, instead it’s a smart storage that allows someone to add or remove things as needed.

That mental model still makes sense for a Git repository as well: I add and remove code to my repository without really knowing how Github stores it: is it in a database? If yes, what database? I don’t need to know.

Picture of a library

From now on I figure I’d imagine the Repository pattern as a sort of librarian who I can talk to to help me find a book: I mention a title and they’d go ahead and fetch it for me. From my perspective it’s not important where the book is stored within the library (shelves? Fridge? Vault?), as long as I can borrow and return it properly. After all, a library is indeed a repository of books, yeah?