Building Programmatic and Declarative-Reactive UI

For the first two labs, we will build the UI visually using Xcode’s Storyboard or Android Studio’s Layout Editor. In the third lab, we will build the UI programmatically. In the fourth lab, we will build the UI declaratively using SwiftUI/Jetpack Compose and their corresponding reactive frameworks. In the final lab, we look at interoparability of declarative and programmatic-imperative UI, i.e., how to write a SwiftUI/Jetpack Compose UI that incorporates a UIKit/AndroidView component written programmatically.

Why Programmatic UI?

We can build the UI of a mobile app visually: on the Storyboard in Xcode or the Layout Editor in Android Studio. Both platforms store their UI layouts in XML files, which can be edited directly/textually. Or we could construct the UI programmatically by creating UI element objects, and specifying the constraints between them, in code.

Pedagogical advantages

From a pedagogical point of view, the main advantage of learning how to construct UI programmatically is:

If you know how to code a user interface, then you know what happens under the hood, whereas the same is not necessarily true of [building UIs textually or visually] . . . . Mastering the coding of . . . user interfaces gives you more control over and greater awareness of how these pieces fit together, which raises your upper-bound as a developer.

Source: Bello

Practical advantages

The advantages of implementing UI programmatically from a practical perspective are:

  1. If the view has a dynamic layout, when the look and placement of UI elements depend on content or other runtime factors, UI by code is the only option. XML layouts are static.

  2. Team maintainability: merge conflicts are easier to understand in code context. This is more of an issue with Xcode Storyboard-generated XIB files, which uses randomly-generated UI element IDs. Android’s Layout Editor uses developer-provided IDs to tag UI elements.

    loss of context

    When developers view source code, they ascribe it semantic meaning. So when manually merging, they’re able to read and understand both sides of a conflict and act accordingly. A storyboard, instead, is an XML file managed by Xcode, and the meaning of each line of code is not always easy to understand.

    Source: Bello, see also Davis

  3. Reusability: XML/NIB files can be re-used by copying, but not with the same ease and fluidity as classes with slightly different behavior adopting the same protocols/interfaces.

  4. Not everything can be done visually or with XML, e.g., passing data between controllers, to use specialized containers (swipe-to-refresh, for example), or for interoperability with declarative UI. The more overriding by code, the more likely app may look different in visual builder than when running. Whereas anything that can be done visually or textually can be implemented with code.

  5. Performance: skip the overhead of parsing and loading/inflating of XMLs and skip the slow render time of Storyboard/Layout Editor during development.

  6. Smaller app size without all those XML files.

  7. Code obfuscation tool will obfuscate UI code as well, but not XML files.

  8. Programmatic UI is used in the industry, so we might as well learn it.

Disadvantages

The disadvantages of implementing UI programmatically:

  1. One of the main challenges in learning to develop apps programmatically is unfamiliarity with the platform’s UI framework. What are all the available view controllers? What are all the available UI elements? How do we create them? What are the APIs’ signatures? Everything is documented of course, but if you don’t know what’s available, if you don’t know the name of the class to use, how do you search for it? When you try to use the standard library of a new language framework, its documentation will list and reference the available APIs and the standard tutorials will show you how to use them. Mobile UI programming for beginners assume use of the visual editors, so finding your way in programmatically requires more searching and more targeted searches on the Web. Or one could consult the Library/Palette of the visual editors to discover what’s there.

  2. Must build app to see UI.

  3. Lost the separation of UI design and application code (though something must always be done in code, e.g., implementing data flow).

  4. Don’t have an overall, big picture view of all screens and navigation between them (especially in Storyboard). Could be alleviated by the use of a design app like Figma?

  5. Additional boilerplate code: to allocate, initialize, layout, and present views.

Why Declarative-Reactive UI?

Advantages

  1. Declarative UI comes with default layout: UI elements are automatically aligned along an axis, evenly spaced. No more futzing around with margins/constraints between elements. Constraint layout is now also available on both Compose and SwiftUI to give developer finer controls on layout.

  2. \(UI = f(State)\): UI observes and reacts to State changes automatically, enabled by the use of a publish-subscribe reactive framework. State is the single source of “truth”. Less chance of bugs due to data inconsistency.

  3. The reactive framework serves as an automated Controller in an MVC architecture, no need to write per-View Controller (or Presenter or ViewModel) anymore.

  4. Can build UI using native language (Kotlin/Swift) instead of having to use another language (XML), although, Compose/SwiftUI being domain-specific languages (DSLs), with a reactive framework, means there’s a paradigm shift required.

Disadvantages

  1. Including the reactive framework increases (doubles?) the size of an app.

  2. Both Compose and SwiftUI are relatively new. Not all their kinks have been ironed out. They could still be buggy, lacking features, and have lower level of community support. That said, multiple course projects have been successfully built using declarative, reactive UI.


Thanks to Pranay Shah for topic.
Prepared for EECS 441 by Sugih Jamin | Last updated: January 1st, 2023