Development

App Architecture Series: Building a Better User Interface

October 21, 2019

008 0 U0 A1630 Edit

At Michi­gan Soft­ware Labs, we don’t sim­ply write code to sat­is­fy require­ments. We find ways to solve prob­lems effi­cient­ly and effec­tive­ly. Know­ing that a well-struc­tured appli­ca­tion comes down to a set of tech­niques and pat­terns, I have been explor­ing design pat­tern the­o­ries and how they shape our think­ing. Grant­ed, it’s huge and com­plex top­ic, but here are some areas I’d like to cover: 

  • Con­sis­ten­cy
  • Reusabil­i­ty
  • Opti­miza­tion
  • Testa­bil­i­ty

Let’s begin with the pre­sen­ta­tion lay­er. The user inter­face (UI) is the top-most lev­el of the appli­ca­tion. It’s also the most frag­ile aspect of the devel­op­ment process — the part clients want to tweak long after we begin imple­ment­ing code. 

A senior devel­op­er once told me he nev­er want­ed to devel­op mobile apps because of the con­stant UI headaches. The ongo­ing changes drove him nuts. I on the oth­er hand enjoy changes, because they lead to progress. The ques­tion is, how can we bet­ter pre­pare for these inevitable changes? 

The tra­di­tion­al cod­ing work­flow looks some­thing like this: Get the mocks from design­ers, open a new sto­ry­board in Xcode (or cre­ate a new xml file in android stu­dio), fol­low the design details close­ly (font size, text and back­ground col­or, etc.), build­ing every com­po­nent one by one (text fields, labels, but­tons, views, shapes, etc.). 

A num­ber of ele­ments are repeat­ed when writ­ing UI code. Things like text size, font styles, mar­gins, paddings, and col­ors. They tend to be so sim­ple I don’t pay much atten­tion to what I’m doing. With text col­or, for exam­ple, I just grab the hex val­ue from the Zeplin file and code: 

android:textColor="#166503"
self.label.textColor = UIColor(red:0.09, green:0.40, blue:0.01, alpha:1.0)

Not ide­al, right? These val­ues don’t make much sense and are error prone. Lat­er, I changed them to: 

android:textColor="@color/colorGreen"
self.label.textColor = CustomColor.green

An improve­ment, but still not good enough. Nam­ing can be tricky. What if I want to go from green to pur­ple? I talked to our design­ers and we came up with a bet­ter col­or nam­ing sys­tem that defines pri­ma­ry col­ors, sec­ondary col­ors, error col­ors, etc. As it turns out, a small change in col­or nam­ing pro­vides far greater flex­i­bil­i­ty down the road, espe­cial­ly if there’s a theme switch requirement. 

This exam­ple under­lies the impor­tance of open com­mu­ni­ca­tion between devel­op­ment and design teams. Col­lab­o­ra­tion is a must if we want to be able to reuse/​maintain the resources ref­er­ences in the code. 

Start With a Style Guide or Design System?

As the chart, below, shows, Style Guide is a set of design basics. Here, you can find every­thing from col­ors, typog­ra­phy to grids and paddings. This is the most abstract part of UI design sys­tem. For small projects, it should be all you need. 

The Design Sys­tem on the oth­er hand is more com­pli­cat­ed and requires more of a team effort. It’s noth­ing new. In fact, many com­pa­nies are already using it: A Design Sys­tem is the sin­gle source of truth which groups all the ele­ments that will allow the teams to design, real­ize and devel­op a product.” 

When we take a clos­er look, it’s actu­al­ly a com­po­nent-based sys­tem that ensures visu­al and func­tion­al con­sis­ten­cy. This includes all the com­po­nents of the Style Guide along with an inte­grat­ed set of func­tion­al com­po­nents, such as spin­ners, but­tons, images, etc. Although com­pa­nies have unique ways of defin­ing a Design Sys­tem, the end goal is con­sis­ten­cy and reusability. 

Con­sis­ten­cy

Con­sis­ten­cy can elim­i­nate con­fu­sion and short­en the learn­ing curve for users. Con­sis­tent and clear com­mu­ni­ca­tion also ensures a lev­el of qual­i­ty con­trol when ques­tions arise around use case, such as: What load­ing indi­ca­tor should we use to inform users the data is being loaded, a sys­tem spin­ner or a fan­cy skele­ton view? How should we dis­play an error mes­sage if one should occur? Should users be expect­ed to pull and refresh to search or should we show them a retry but­ton? These aren’t always indi­cat­ed in the design file, so devel­op­ers often leave them blank. 

Anoth­er issue is con­sis­ten­cy across plat­forms. Most of the time we build apps for both Android and iOS. Google and Apple guide­lines rec­om­mend using plat­form-stan­dard con­trols when­ev­er pos­si­ble. Unfor­tu­nate­ly, Google and Apple have very dif­fer­ent thoughts on the UX with their devices and apps. Google tends to go deep, while Apple is flat. 

Should we cre­ate a sep­a­rate design style for each plat­form to give users a native” expe­ri­ence and main­tain con­sis­ten­cy with oth­er mobile apps with­in each platform’s ecosys­tem? Or should we keep the plat­forms iden­ti­cal to main­tain a con­sis­tent UI expe­ri­ence for users, regard­less of who they are or what device they’re on? 

Ulti­mate­ly, these are design or even busi­ness deci­sions; how­ev­er, from a developer’s per­spec­tive it is obvi­ous that build­ing native components/​navigation pat­terns is more effi­cient than build­ing a mix of Google’s Mate­r­i­al Design com­po­nents and Apple’s Human Inter­face Guidelines. 

Before cod­ing your first ele­ment, it’s always a good idea to eval­u­ate the design’s con­sis­ten­cy with the native sys­tem to deter­mine how much effort will go into build­ing cus­tom ele­ments, such as: 

  • Nav­i­ga­tion pat­terns and nav­i­ga­tion elements
  • Default con­trols
  • Inputs styles and but­ton styles
  • Alerts
  • Typog­ra­phy
  • Ani­ma­tion

List­ing and com­par­ing these ele­ments gives a bet­ter sense of how to approach the project. For instance, whether to use native com­po­nents or exist­ing com­po­nents, or whether to cre­ate com­pound com­po­nents or self-drawn com­po­nents. A view may seem basic enough but actu­al­ly con­tain many self-drawn or com­pound com­po­nents. This is when we begin to under­es­ti­mate the amount of effort involved.

Reusabil­i­ty

It’s a tall order writ­ing code that can be uti­lized through the dura­tion of a project. By its nature devel­op­ment is an evolv­ing process, requir­ing mod­i­fi­ca­tions as new fea­tures are added or sys­tems upgrad­ed. One thing we need to pay atten­tion to is when we intend to cre­ate a component/​style glob­al­ly, but end up instead with a series of over­ride base class­es or xml styles to fit spe­cif­ic require­ments. Such over­rides erode consistency. 

Some­thing else to keep in mind are the dif­fer­ences between plat­forms. It’s impor­tant to know how UI sys­tems are struc­tured in order to deter­mine the best strate­gies for work­ing with each one. 

And we haven’t even begun to touch on Opti­miza­tion and Testa­bil­i­ty. Look for that in our fol­low up post. 

To be continued…

Ready to get started?

Call us at 616-594-0269 or send us a note below.
Visit our office @ 452 Ada Drive SE Suite 300 Ada, Michigan 49301
Send us an e-mail @ info@michiganlabs.com