At this point I am convinced that the decision to define UI layouts in XML instead of code has been a terrible mistake.
- For starters, it's overly verbose. If you've worked with stuff like XAML in WPF or XML layouts on Android, you know how quickly those files tend to get bloated.
- It does not lend itself well to reuse compared to, well, actual code. Which means there tends to be a lot of repetition. Which leads to more bloat.
- Editing XML kind of sucks. You're more at risk of making silly typos that won't be caught at compile time.
- XML namespaces make an already verbose language even more verbose, not to mention just generally confusing.
- At some point you will need to access your user interface from your application code. Which means you end up with silly stuff like findViewById() to bridge the gap, adding even more boilerplate to your code.
- You essentially have to learn two different sets of APIs which do the same thing. <Button title="blah"/> vs button.setTitle("blah"). Why?
The only real strengths of XML are that 1) it's declarative, 2) it's hierarchical, and 3) it's diffable. But code can be too, without all of these other drawbacks.
Fortunately it seems like the industry is starting to figure this out with things like SwiftUI and Jetpack Compose. I really think we're going to look back in a few years and think it was ridiculous that we used to do this stuff in XML.
- User interfaces are very prone to have big files, because there tend to be a lot of different components. I don't get how XML will add more bloat, other than having the <> tags for defining elements.
- XAML lets you define custom controls. I'm not familiar with Android XML, but in any case it's not an issue of the language but of the framework.
- Again, a fault of the framework. Visual Studio, for example, checks your XAML for errors, both when writing and when compiling.
- I don't think namespaces are confusing (most programming languages have some concept of namespaces), but I agree that one could have more facilities to avoid specifying namespaces everywhere.
- Yes, but most of the time you shouldn't access the user interface from the application code, as coupling them tends to create ugly code that is prone to mistakes and failures. For me, this is an actual advantage of XML for UI, it makes it more difficult to create an interface out of spaghetti code.
- Well, one is declarative and the other one imperative. As long as you want to have both types, it doesn't matter what language you use.
For me, there's not that much of a difference between SwiftUI/Jetpack Compose and equivalent XML code. UI definitions are going to be messy no matter what.
> - User interfaces are very prone to have big files, because there tend to be a lot of different components. I don't get how XML will add more bloat, other than having the <> tags for defining elements.
I disagree that this is an inherent property of user interfaces. In fact I think it's a bit weird that we focus so much on abstractions and when it comes to the code we write (DRY principle, etc), but then when it comes to XML we wave our hands in the air and declare "well that's just the way it has to be".
> - XAML lets you define custom controls. I'm not familiar with Android XML, but in any case it's not an issue of the language but of the framework.
Custom controls allow you to reuse entire widgets, but what about code reuse?
> - Again, a fault of the framework. Visual Studio, for example, checks your XAML for errors, both when writing and when compiling.
No, ultimately it's the fault of the fact that you're trying to shoehorn a bunch of stuff into XML attributes (as strings) that weren't strings to begin with. As I said below, ever make a typo in a binding?
> - I don't think namespaces are confusing (most programming languages have some concept of namespaces), but I agree that one could have more facilities to avoid specifying namespaces everywhere.
This is admittedly worse on Android where almost everything needs to be prefixed with android:, except stuff that comes from the support library, plus these other handfuls of exceptions (which is definitely a framework problem), but even stuff like x:Name vs Name is unnecessarily confusing in WPF.
> - Yes, but most of the time you shouldn't access the user interface from the application code, as coupling them tends to create ugly code that is prone to mistakes and failures. For me, this is an actual advantage of XML for UI, it makes it more difficult to create an interface out of spaghetti code.
That sounds good in theory. In practice, you end up with a lot of code-like constructs in your user interface. Every XAML file I've ever seen is full of bindings, converters and converter parameters, triggers, etc. You might insist this is not code because it lives in an XML file but it sure looks a lot like code to me, just shoehorned into a document language format.
In other words, while we strive hard to avoid spaghetti code, it seem like we don't apply the same principles to avoid spaghetti XML.
> - Well, one is declarative and the other one imperative. As long as you want to have both types, it doesn't matter what language you use.
False dichotomy, IMO. You can build a declarative UI in your code without resorting to XML.
> For me, there's not that much of a difference between SwiftUI/Jetpack Compose and equivalent XML code. UI definitions are going to be messy no matter what.
Have you actually worked with either of these frameworks?
These forms can happily co-exist in the same document, e.g. you can start at the top with one default namespace and then switch it in some branch into another.
My suspicion is that XML and friends get chosen for compelling social reasons.
It's not a language that anyone would want to do the actual software implementation in. That's important because, if you pick an existing language, then everyone who plans to use some other language is going to see that choice and assume it means that their language is either unsupported or will be a second-class citizen on that UI toolkit. They might not be wrong.
Creating a whole new language that's custom-tailored for UI layout avoids that problem, but will also be off-putting, since people will perceive that they have to learn a whole new language just to use your UI toolkit.
And just slapping it into a mess of library calls that people can call from any language is perhaps the worst choice of all. GUI toolkits, for whatever reason, always end up being object-oriented. Meaning that you've got to export an object-oriented API. Meaning you've got to either implement it in an object-oriented language that probably has a deeply incompatible and possibly not even standardized ABI such as C++, or you've got to go to great lengths to Greenspun an object-oriented system into a procedural language that can export a C-style ABI. Neither of those is fun.
In summary. . . yeah, XML is an awful choice. It's easily the worst option, aside from all the other options, which are even worse.
"The only real strengths of XML are that 1) it's declarative, 2) it's hierarchical, and 3) it's diffable. But code can be too, without all of these other drawbacks."
Code generally isn't declarative or hierarchical unless your language is those things as well. A declaratively defined interface in C# would end up being some like a bunch of strings or enums passed to some object constructors. At that point I'd rather a an XML implementation that can be verified and processed with tools.
"- For starters, it's overly verbose. If you've worked with stuff like XAML in WPF or XML layouts on Android, you know how quickly those files tend to get bloated."
I frequently write WPF code these days and don't find it any more verbose than attempting the same thing in C# statements. If anything, it's less verbose and it has the added benefit that it's all organized in the same group of files.
"At some point you will need to access your user interface from your application code. Which means you end up with silly stuff like findViewById() to bridge the gap, adding even more boilerplate to your code."
I don't know about Android, but in WPF, you just add a name attribute to your ui element and reference it by name.
"Editing XML kind of sucks. You're more at risk of making silly typos that won't be caught at compile time."
Hasn't really been my experience. Syntax errors are caught by the editor typically and further errors do get caught at compile time for XAML at least. Some errors don't get caught, but these are the same errors that would get missed if I attempted the same thing in C# code.
> Code generally isn't declarative or hierarchical unless your language is those things as well. A declaratively defined interface in C# would end up being some like a bunch of strings or enums passed to some object constructors. At that point I'd rather a an XML implementation that can be verified and processed with tools.
I should clarify and say code can be declarative with the correct language support. I agree that it's probably not well suited to C# in its current state.
> I frequently write WPF code these days and don't find it any more verbose than attempting the same thing in C# statements. If anything, it's less verbose and it has the added benefit that it's all organized in the same group of files.
Here are two examples I would consider overly verbose in XAML:
1. Triggers, DataTriggers, EventTriggers, MultiTriggers, etc. Here we're dealing with the fact that XML is not a programming language and lacks basic control structures, so we've gone ahead and defined our own mini-programming language just so conditional values can be expressed in XML. Why?
2. Anything having to do with overriding ControlTemplates.
> Hasn't really been my experience. Syntax errors are caught by the editor typically and further errors do get caught at compile time for XAML at least. Some errors don't get caught, but these are the same errors that would get missed if I attempted the same thing in C# code.
Ever make a typo in a binding?
I agree that Visual Studio is really good at helping you out where it can, but at the end of the day we're still trying to shoehorn programming constructs (objects, properties, enums, etc) into a document language format by shoving everything into XML attributes (where everything is a string) and there is a fundamental impedance mismatch between the two. Good tooling only goes so far.
"I should clarify and say code can be declarative with the correct language support. I agree that it's probably not well suited to C# in its current state."
Ok, but which language do you think would work? Lisp? I like the things you can do with macros and s-expressions as much as the next guy, but you're still left with the question of what should people using C# (which has neither of those things) use to make GUIs.
"1. Triggers, DataTriggers, EventTriggers, MultiTriggers, etc. Here we're dealing with the fact that XML is not a programming language and lacks basic control structures, so we've gone ahead and defined our own mini-programming language just so conditional values can be expressed in XML. Why?"
Correct, all the different sorts of trigger are verbose. But, to answer your question as to 'why?' the reason is because we need a deterministic way to express conditional formatting. If we attempted to accomplish the same tasks with hooks we'd have the problem of intermixing imperative, state-full, code with logic that is supposed to be more deterministic. I've written code like that for WinForms like that and it's ugly and hard to debug.
If you were to try to implement triggers with code behind C#, it would still be very verbose because you wouldn't be writing actual C# logic. You'd be doing something like declaring an object with trigger conditions and results and it would be at least as verbose as the XAML triggers, that is, if you wanted to accomplish the same thing with the same guarantees as with XAML triggers. The problem here isn't really the XML, but the fact that there isn't really an available language that solves the relevant problem. It's not like you could use an `if` statement.
"Ever make a typo in a binding?"
I have. I've also made typos when writing viewmodel objects that implement the `INotifyPropertyChanged` interface to similar effect.
You're clearly coming from a very C# centric viewpoint and reacting to my statements from a perspective of: "well, if I don't do it in XML then I'd have to do it in C# and that would be even worse". Which I don't necessarily disagree with. But just because doing it in C# would be worse doesn't make doing it in XML good either.
My underlying point is with platforms like iOS and Android adopting declarative UIs, combined with languages like Swift and Kotlin evolving in parallel to better support them, I think we will eventually be able to move on from being stuck with XML.
Its funny WinForms was just code. The designer generated the code or you code do it by hand.
You could read it and understand it because it was the same language you used. If there was a problem you could debug it.
I never felt more productive than when my UI declaration was just code.
Inevitably you need to mix some logic in the layout language and then debug it (For each render this thing, binding syntax etc.) now you have a weird programming language that is hard to debug and remember syntax for, or you could just use a normal programming language, maybe one that supports some declarative constructs.
SwiftUI gives me hope, would like to see something similar show up for the .Net World.
The IDE wrote code and kinda hid it from you in a partial class. And every once in awhile, one would have to get in there and muck around with the generated code. This had the potential to break things pretty badly.
Normally didn't do much in the partial class other than reference it.
You could override what it was doing in the main class file though if needed pretty easy. Again if it did break it was just aode and threw a normal exception in the designer, usually revolved around something that didn't work right in DesignMode so you had to check for that explicitly.
If you use F#, Fabulous[1] for mobile apps and Fable+Elmish[2][3] for web exist. I use Giraffe's[4] view engine for server-side HTML templating. And it looks like AvaloniaUI is going to have a similar style UI in FuncUI[5], but I'm not sure how active that is.
"WinForms was just code" This conflates source text and product. Generated code was _output_ by the WinForms WYSIWYG editor, but the tool stored the layout source in a native project file format.
You could also write forms by hand, the WYSIWYG editor just visually represented the code and modified it using a bunch of metadata (again just .Net attributes) to help the designer.
The GUI designer actually just ran your code to display in the designer, which mostly worked, sometimes it could break if you form relied on runtime dependencies and you could code around that by specifically checking for DesignMode == true in your code.
I am not saying this was perfect but it had a lot of advantages. Now you see SwiftUI and the like going back toward that model.
I think qt widgets (not-qml, it's different and I haven't used it) uses XML without many of those problems.
Layouts are trees of widgets. Layouts are themselves widgets so repetition in the tree can be reduced.
You use XML, C++, or both to define a widget. The UI Compiler will turn that XML into C++.
That means further code reuse can leverage the C++ type system. All widgets are QWidgets, and MyProgressBar inherits from QScrollBar.
And you (or, at least I) never write .ui files by hand, they've got a GUI designer tool. And the tool supports your custom widgets by treating them the same as the known widget type it inherits from.
Accessing XML-defined widgets from code is the same as C++ defined widgets, because the compilation step means they are. Class member names come straight from the XML file.
The QObjects are constructed in a way that understands the UI hierarchy, and you can programmatically walk that hierarchy using the variable names. (You do have to tell objects their own names in the non-XML-generated code.)
Qt is really good for doing UI, in my opinion, both QML and non-QML. They do a really good job at keeping things coherent and concise, which really helps first-time users, specially after learning the basics.
After using Flex for a couple of years I have to agree. There always seemed to be two ways to do things: 1) Through the XML 2) Through the code. That may seem appealing initially but gets really ugly when certain developers do certain things with XML and others code. It basically doubles the API space and syntax.
I fully agree with this statement. My work is generally for the web, and HTML has the same issues. It's amazing how much removing a single tag in a nested tree can mess up VSCode's parsing engine. Just modifying the tags usually works on both open and close though.
One point I try to get across to people working on the web is that they should think of HTML as a render target, not as a layout tool.
The point of HTML isn't to make it easy to lay out a document, it's to have an easily understandable pure-text representation of hierarchical data that can be read by computers/users. Light, well-formatted, semantic HTML isn't an engineering concern, it's a UX concern.
Of course HTML can be used as a layout tool, but that's not its primarily purpose, otherwise it would include decent 2-way data bindings for tables.
One more interesting example of XML based GUI system that avoids most of the problems listed above is HaxeUI. The same way as Qt it solves them using compile time code generation.
Accessing objects from code is not a problem due to compile time code generation, no findById just access the field. Due to the powerful macro system in Haxe you even get in code autocomplete for objects defined in xml before running compilation.
For code reuse it allows easy way of defining custom widget classes based on xml file and using custom widgets in xml file.
In my experience with Qt bloat usually comes from graphical editors that add unnecessary properties you wouldn't have set in code or GUI systems that don't support creating reusable subcomponents.
Because sometimes you want to pass data between blobs of code, (possibly separated by time, environment or language), or even to and from humans who may not understand code.
> For starters, it's overly verbose. If you've worked with stuff like XAML in WPF or XML layouts on Android, you know how quickly those files tend to get bloated.
I've done a bit of WPF and a fair amount of Qt Widgets, and never once did the actual XML content matter since it was mostly putting the control at a place that looks good in a UI designer.
> Which leads to more bloat.
I'd like to know your definition of "bloat".It's not like 100kb or 500kb of XML are going to translate into 100kb or 500kb executables or runtime memory use, since the XML is generally only used at compile time before translation into code.
> Editing XML kind of sucks. You're more at risk of making silly typos that won't be caught at compile time.
well, Qt's main IDE marks the UI xml files as read-only so not much chance of that on that side.
> At some point you will need to access your user interface from your application code. Which means you end up with silly stuff like findViewById() to bridge the gap, adding even more boilerplate to your code.
... no, you will just refer directly to a variable that was generated in a precompilation pass - you can inherit from or compose the generated object depending on if you prefer to type `ui->myLabel.setText` or `this->myLabel.setText`.
> You essentially have to learn two different sets of APIs which do the same thing. <Button title="blah"/> vs button.setTitle("blah"). Why?
Chiming with my prior experience: My problem with Qt's approach is that their editor is atrocious despite their XML schema for UI layout being excellent.
Qt's XML schema makes sense and very easily translates to the C++ it generates. If one wishes they can write the XML themself using just their knowledge of the Qt Property System, the Layout System, and the very basics of how the XML is laid out. If they want to just use a designer tool, that's fine too however Qt's UI designer makes life very difficult from the perspective of version control and actual usability.
The UI designer doesn't respect any Canonical form of the UI files. This means that each time you save the file it more or less jumbles the entire thing up based on however it decided to hold it in memory. This turns tiny changes (what should be maybe 2-3 lines of XML) into massive ones (100s to 1000s of lines of XML shuffled just enough to shake off any semblance of contiguous history in the VCS). Likewise, it adds arbitrary property data to items that 95/100 times are unintended (setting default geometry sizes based on the sizes of the UI elements in the demo window) or are simply meaningless (storing the default value as a user selected property despite the user requesting to use the default).
It doesn't help that the UI of the designer is finicky as hell (layouts) and adding custom UI components is a hassle via the editor while it is exceedingly easy in the XML.
It's a bunch of small things like that that have resulted in teams I've worked on in the past refusing or at least strongly discouraging the committing of changes made by UI designer into VCS. It's really a shame too since a good UI editor is a boon for development and Qt has a really nice UI library.
I'm writing Flutter apps with Dart, and not having to use XML (or HTML+CSS) for UI layout has been a breath of fresh air. It's just code. I really like it.
- The verbosity is easily addressed by using an IDE which providing smart folding, highlighting, etc...
- Editing XML is actually a lot easier than JSON. Thanks to XML schemas, completion works really well in XML and very poorly (if at all) in JSON.
- Also, XML allows comments, which JSON doesn't.
- You don't need `findViewById()` in 2019 and haven't in a while, really: there are plenty of alternatives available (synthetic accessors, Kotlin, ButterKnife, etc...).
I want to address that reuse/repetition thing. It's totally possible to do this in XML+XSLT. E.g. you have some repeating structure that totally calls for what would be a helper function in a conventional language, say, "createMyButton(this, that)". In XML that could be done like this:
Ahhhh the never ending should UI live in the code, or should it live outside the code debate. There is definitely a cohort of people who find React and code based UI patterns better. There is also a cohort of people who prefer to keep the two separate. I tend to side with the former architecture, just from years of experience building software where keeping them separate actually doesn't win you anything. Yet I've met engineers who swear by XML/Interface Builder/VB style development. Hey, as long as you can build your software and get the job done and the tools are helping you get the job done, who am I to tell you what pattern to build with?!
UI frameworks that expose a findViewById function could be considered anti patterns in the first place. For a declarative view the dependency should go the other way around with the view reactivelly accessing the viewmodel, instead of (accidentally) embedding UI boilerplate in your business logic. To react on UI changes in your logic you can add listeners to changes made on the viewmodel.
See jQuery vs react/angular/vue for best example of the difference.
Android Jetpack also tries to bridge the gap of this in android, even though here you manually have to write some glue code yourself to create this reactive layer.
None of the flaws you list apply to TSX, which essentially gives you the best of both worlds. I really wish SwiftUI had used JSX-style syntax, just because of how nice it looks.
Technically, tsx / jsx is just a macro to convert an xml-like syntax to plain javascript objects... Neither xml nor json.
Inline functions and classes dont exist in either, JSX doesnt have to deal with xml's namespaces, and you dont need to construct an entire document- fragments are defined in functions at as granular a level as you like.
I do agree personally that I prefer tsx over the other alternatives, just pointing out that it is a pretty nice step up over something like flex or xaml.
There are languages and languages here, and your mileage will actually vary by orders of magnitude.
As people already pointed, code isn't inherently declarative or non-verbose. Some of the most popular languages for creating GUIs (Java, JS, C#) aren't either.
> It does not lend itself well to reuse
There isn't any inherent feature for code that will enable the kind of reuse you need when declaring a GUI either. You'll get it naturally in Lisp, you may be able to hack something in Haskell, and you can create a hacky DSP in in Python or Ruby, but if your GUI is in Java, CS, or JS you are out of luck.
> silly typos that won't be caught at compile time
That's a tooling issue. At Python, Ruby or JS you it is inherently more an issue than on XML, at Lisp it will vary with the actual idiom.
> At some point you will need to access your user interface from your application code
> You essentially have to learn two different sets of APIs
Well, that's bad design. There's nothing (except well, a lot of work) stopping a library from making the entire interface manipulation by actions made over XML. Granted, that is much easier and more natural in a DSL or in declarative reflexive code, so you do have a point, but it can be fixed by a lot of polishing over the worse fundamentals.
Yes I agree that building declarative UIs in code does require language support and some languages are not well suited to it. But I think this is an area where we could see real improvement and we should want our tooling to evolve to better handle these problems.
Oh, I completely agree that UI declared by code has much more potential than a frozen approach like UI declared in XML. It's only that presently, it's not a clear win.
Anything that builds the UI at runtime is silly. Your UI isn't going to change at runtime (other than in a few predictable spots), why would you waste processing time dynamically calculating it.
Not only that, XML actually diffs poorly -- line-by-line diffing of the sort git does makes it hard to see that a single attribute was changed in a long line.
What UI framework using XML is there where you can end up making silly typos that won't be caught at compile time? Or basically any sort of typo? I would expect any decent XML UI framework is going to have some sort of validation schema defined which will be quite stringent as to what is allowed at a particular level. Not that I like XML Schema.
One particular pet peeve of mine is the fact that it won't catch typos in data binding. If I have IsEnabled={Path IsEnabeld} in my XAML, the designer won't catch it. At runtime, the error is silently ignored. It just doesn't work, and no tooling, nothing other than triple checking every line of code will catch it.
Also it's really bad about picking up dependencies cross package, although it might be a problem in my org's config.
Primarily the two I originally mentioned, WPF and Android, both of which rely on configuration of controls through XML attributes, which are all strings and not necessarily checked for validity at compile time.
System.Windows.Forms works in the same way (the UI is serialized to code). WPF was designed many years after that because it allows different disciplines to work together.
Designers would most likely be familiar with XML given their HTML background, but they wouldn't necessarily know C#.
If Swift UI expresses the full fidelity of the API in the designer (e.g. expressing custom states and animations, keyframes, etc. on a custom button), then my point doesn't apply. If the full range of designer responsibilities cannot be achieved without dropping into code, then Swift UI isn't a real counterexample.
> Designers would most likely be familiar with XML given their HTML background, but they wouldn't necessarily know C#.
I am really curious how often XAML has been used by a designer who didn't know C#. Most of the XAML I've seen (in non-trivial apps) has a lot of code-like constructs in it. If you don't know what's going on under the hood, how are going to correctly declare your data bindings (for example)?
> Most of the XAML I've seen (in non-trivial apps) has a lot of code-like constructs in it.
Those code-like constructs are UI behavior (e.g. how to transition from checked to unchecked for a checkbox). While they do take learning, they are not strictly code.
Also, Expression Blend can interact with every part of XAML in full-fidelity. Designers need not worry about the code-like parts of XAML at all.
> If you don't know what's going on under the hood
I suppose the workflow is that the design team would log a ticket for the development team, who would expose said binding and add it to the UI as a placeholder. I'm not sure exactly how this is supposed to work, but Microsoft did have a project which combined Unity and WPF to solve this exact workflow (I forget the name), and they were using it internally.
---
Personally, I can see the benefit as I do work at a product company. Developers get bugs pretty often to do with "element X is 1 pixel off," usually from the design team (one designer was known to open screenshots in paint to measure distances). If you can empower the designers to just create real UIs instead of mockups, it would get done correctly in the first place. Vue SFCs come close to achieving this, but fall short in terms of state (you still need JS to add/remove CSS classes).
Either way, it isn't fair to compare Swift UI to XAML as Swift UI doesn't seem to attempt to solve this at all (even if XAML doesn't solve it perfectly). Swift UI is closer to System.Windows.Forms.
- For starters, it's overly verbose. If you've worked with stuff like XAML in WPF or XML layouts on Android, you know how quickly those files tend to get bloated.
- It does not lend itself well to reuse compared to, well, actual code. Which means there tends to be a lot of repetition. Which leads to more bloat.
- Editing XML kind of sucks. You're more at risk of making silly typos that won't be caught at compile time.
- XML namespaces make an already verbose language even more verbose, not to mention just generally confusing.
- At some point you will need to access your user interface from your application code. Which means you end up with silly stuff like findViewById() to bridge the gap, adding even more boilerplate to your code.
- You essentially have to learn two different sets of APIs which do the same thing. <Button title="blah"/> vs button.setTitle("blah"). Why?
The only real strengths of XML are that 1) it's declarative, 2) it's hierarchical, and 3) it's diffable. But code can be too, without all of these other drawbacks.
Fortunately it seems like the industry is starting to figure this out with things like SwiftUI and Jetpack Compose. I really think we're going to look back in a few years and think it was ridiculous that we used to do this stuff in XML.