We frequently get asked about our opinion, and direction Uno Platform will take, about declarative code vs markup. In good product (and OSS project) management the question we need to ask ourselves is not *could* we build something, but also *should* we build something.
One of our core team members and architects on Uno Team â David Oliver – discusses the kinds of concerns we take into consideration when deciding on our future approach. While we havenât made any decisions, the blog post will give you a general idea of items involved when making the decision to add declarative code approach in addition to markup approach Uno currently uses. This blog originally appeared at Davidâs personal blog.
“The Debate”
Thereâs a good-spirited but earnest debate currently about the âright wayâ to write a UI-driven application. In many domains where specialized markup languages for authoring visual layouts have long been the dominant paradigm, newer frameworks are appearing which eschew markup completely, opting to declare UI purely in code.
About the Uno Platform
For those new to Uno Platform â it allows for creation of pixel-perfect, single-source C# and XAML apps which run natively on Windows, iOS, Android, macOS, Linux and Web via WebAssembly. Uno Platform is free and Open Source (Apache 2.0) and available on GitHub.
Both the âmarkupâ approach and the âcodeâ approach have vocal proponents. Personally I donât have a horse in the race â yet â but I do have thoughts on the benefits and limitations of each approach, and I wanted to get them down, mainly for my own benefit.
Letâs give some concrete examples first, in case itâs not clear what Iâm talking about.
Examples of markup-based UI: HTML/CSS, Xaml (UWP+Uno Platform/WPF/Xamarin.Forms), Androidâs xml layout format
Examples of code-based UI: Flutter, React, SwiftUI, Comet (.NET)
Now we can talk about the relative merits of each approach.
Benefits of markup
Markup is structured
Retained-mode GUIs are typically implemented as a recursively-defined tree of objects, and UI markup formats are well-suited to defining a hierarchy of objects.
Consider the following UI layout, first in Xaml and then in C#:
Xaml:
1
2
3
4
5
|
< StackPanel > < TextBlock Text = "Enter search string" /> < TextBox /> < Button Content = "Search..." /> </ StackPanel > |
C#:
1
2
3
4
5
6
7
8
9
|
new StackPanel() { Children = { new TextBlock { Text = "Enter search string" }, new TextBox(), new Button { Content = "Search..." } } } |
With such a simple layout, theyâre not so different. Nonetheless I believe if I were to see them cold, in the middle of a file, itâd be almost immediately obvious for me what the first is describing, whereas itâd take me a few seconds to pin down the meaning of the second. The first has to be a hierarchical object declaration. The second could be anything â thatâs the beauty of code! â but by that token it takes a moment longer to narrow down the vast possibility space of what it could be saying to what it is saying.
Markup is a domain-specific language
This point is really a generalization of the first: markup is a domain-specific language for UI declaration, with all the advantages (and drawbacks) that entails. The parser can do a lot of clever stuff that might not be appropriate in a general-purpose language, like context-sensitive implicit conversions, specialized syntax, implicitly understanding nested content, etc.
Inherent separation of concerns
Markup pushes you to keep your UI separate from other layers of your app because it can only do UI. I donât find this point particularly compelling: weâre reliant on discipline and good dev culture to maintain separation of concerns in all the other layers of the app, so I donât think artificially forcing that separation solely for UI makes much difference. But I guess itâs a minor point in markupâs favour.
Markup is tooling-friendly?
I include this one because it seems toâve been an important argument historically for why markup is superior. The argument is that markup, with its inherent structure and reduced expressivity, would be more amenable to tooling support where you drag and drop UI elements into a WYSIWYG editor. The dream seems toâve been that designers would author the bulk of an app in such a tool, a developer would come along and tweak the resulting markup output, and app development times would be slashed.
I donât think thatâs necessarily technically inaccurate â such tools do exist, like Blend and Xaml Designer. It just doesnât seem to be particularly relevant. The dream never really panned out. WYSIWYG tools are great for static documents, but in an interactive application there are key aspects that in practice must be manually handled by an experienced front-end dev, like responsive layouts and virtualized lists to name a couple off the top of my head. And a tool and a human âcollaboratingâ on the same raw markup is not a pleasant experience for either, making it difficult to do further tool-aided edits after the markup has been hand-tweaked.
The trend in practice seems to be for designers to use designer-focused tools like Figma and Zeplin, and then to focus on improving the capabilities of such tools to export feedstock for front-end devs, like first-draft markup layouts, colour and text style resources, etc.
Meanwhile on the dev side, the increasing power of âhot reloadâ capabilities in most modern UI frameworks is making build-time design tools increasingly redundant.
Performance optimizations
Just as the constrained structure of markup is beneficial for editing tools, it also potentially lends itself to pre-parsed intermediate formats which may offer particular performance benefits. UWPâs Xaml, for instance, supports the Xaml Binary Format (.xbf) which loads faster at runtime.
Itâs probably more than that: I suspect the curtailed expressiveness of markup helps to steer UI authors away from performance-killing anti-patterns. Itâs easy to shoot yourself in the foot, when it comes to UI and performance, and markup by no means makes it impossible; but the exposed API surface tries to guide authors towards the happy path. Virtualized ListViews in Xaml languages are a good example.
Benefits of code
Letâs turn to the advantages of declaring UI in code.
Code is Turing-complete
I donât mean, like, you literally couldnât implement a Turing machine in markup somehow. (Maybe you could, feel free to tell me how.) But what I mean is that code is capable of expressing arbitrary logical constructs, thatâs basically codeâs whole job, whereas markup struggles to do so.
Proponents of code show examples of UI snippets that are neatly expressed as code, but verbose and unwieldy in markup, often involving conditionally setting a property, or transforming a value. Proponents of markup usually concede that there are some things markup just canât (or shouldnât do); no one Iâve seen is really maintaining the position that a rich interactive application can be built only in markup. The pro-markup position is that the mechanisms for calling into code from markup, or vice versa, are adequate. The anti-markup position is that they arenât worth the bother.
I would note that the interconnectivity between code and markup varies widely from one markup language to another. Xaml leans heavily into said interconnectivity, with the whole notion of âcode-behindâ as well as mechanisms like value converters, template selectors, behaviours, etc.
Iâm not sure where I stand on this one. Some of the âverbosityâ of markup seems more apparent than actual, but whenever I use, say, a value converter, it does feel like a lot of boilerplate. (You know that âboilerplate feelâ⊠ugh.) There are innovations that try to address this, like UWP Xamlâs function binding feature, but they donât yet go far enough.
Code is reusable
Code reuse is one of the major themes in the development of modern high-level programming languages, and one of the obsessions of the craft of software development. Code is reusable at the level of a one-line method, a million-line assembly, or absolutely anywhere in between.
Reuse is a problem for markup. Some languages, like HTML, have practically no âreuse storyâ for functionality. I think this is why code-only UI frameworks gained ground earlier in web development with respect to other settings.
Xaml has a much better reuse story, with affordances like UserControls and control templates. But the boundaries of reuse are relatively fixed and inflexible; and passing information into or out of a âblockâ of reuse can be tedious, at times arcane. Itâs a painful choice at times whether to refactor a Xaml app for greater reuse, or accept the markup duplication in exchange for a more sane architecture. Code wins this round.
Better IDE support
IDE features, be it an open-source or closed-source IDE, are driven by customer demand, and customer demand is proportional to the volume of customers.
As we noted, you can have code with no markup, but you canât have markup with no code. It follows, then, that code will always have better IDE support than markup, because the set of all users of a given markup language will always be a subset of the users of the associated coding language.
The IDE support for markup is not necessarily bad â Visual Studio for Windows actually has pretty nice support for Xaml. But Visual Studioâs C# support is amazing. And if we look at other popular IDEs, Visual Studio Code to take one example has good C# support but minimal understanding of Xaml. This will hopefully improve in the future, but it seems likely that IDE support for specialized markup is always going to lag behind support for the associated coding language.
You donât have to learn a new language
Given a programming task, many developers, not unreasonably, prefer to complete it using a language they already know and are familiar with, rather than one they never touched before. Many, moreover, are not full-time front-end developers, but still want to be able to throw together a GUI-driven application when the need arises.
Some developers judge specialized markup languages to be an unnecessary cognitive burden, and would rather write UI in the general-purpose coding languages they already know.
I am well-steeped in Xaml after years working on the Uno Platform, but I know how this feels. Specialized syntaxes serve to demarcate and perimeterize areas of expertise. I know when I see a YAML file, itâs as if Iâm seeing a battered wooden board with a skull-and-crossbones and âTHIS IS DEVOPS TERRITORYâ scrawled on it.
This is a valid shortcoming, then. The negative of being an âextraâ syntax to learn is something that markup has to outweigh with other positives, if itâs to be worthwhile.
Good tooling can go some way to alleviate the cognitive burden of a new language, by catching errors and guiding you toward the happy path. This couples into the area of IDE support already mentioned. The issue specifically of error-checking is trickier for Xaml than for a static-typed language like C#, since on Windows the bulk of the Xaml parsing takes place at runtime. Itâs further compounded in UWP and WinUI by the .NET/WinRT boundary, which can lead to frustratingly opaque errors.
Ok then!
I wanted to point a couple of other UI approaches that donât match the âmarkupâ definition here but arenât code either, but perhaps another time.
Before I started writing this post, I didnât have a strong opinion on whether markup or code was the âright answer.â Having written it, Iâm more convinced that there is no right answer. Each approach has inherent strengths and weaknesses. A specialized UI markup syntax is essentially a domain-specific language, which can be a powerful tool, but brings an additional knowledge burden and has to avoid the risk of being a second-class citizen in the tooling ecosystem.
I wrote this post mainly with an âapp developer hatâ on. To wear a âframework designer hatâ for a second: itâs obvious that many individual developers have a strong âgut levelâ preference for one model or the other. Is it possible for a single framework to please them both? But thatâs perhaps a fitting subject for a separate post.
David Oliver, Architect, Uno Platform