Design Philosophy
Tracy: “We sailed it down the coast of Maine and back the Summer we were married. My, she was yar…”
George: “Yar? What does that mean?”
Tracy: “It means… easy to handle, quick to the helm, fast, right. Everything a boat should be, until she develops dry rot.”
From “The Philadelphia Story” by Philip Barry
Creating a UI auto-layout tool doesn’t require much code. There isn’t any algorithmic complexity; performance isn’t a concern. The difficulty lies in coming up with an design that is easy to learn and use. It should yield code that is easy to write and maintain. It is an API design challenge.
It is awkward to express layout using code no matter whether you use an auto-layout tool like iOS Auto Layout or WeView 2 or just work programmatically. Layout code quickly grows into an unmanageable mound of repetitious spaghetti code. In the interest of maintainability, WeView 2 is tightly focused on the goal of yielding concise, expressive code.
To this end, WeView 2 takes a number of unusual measures.
- Chaining. WeView 2 property setters like [setMargin:] and [setSpacing:] return a reference to the receiver whenever possible to allow chaining, ie. invoking multiple methods on the same instance. Chaining greatly reduces the volume of code needed to configure layout. Chaining doesn’t make for particularly idiomatic Objective-C, but it is a key mechanism for keeping layout code concise. Ultimately, chaining is optional - but if you don’t use it, your code quality will suffer.
- Redundancy. There are tradeoffs between the “There’s More Than One Way To Do It” design philosophy (as exemplified by Perl) and the “There’s Only One Way To Do It” design philosophy (as exemplified by Python). WeView 2 comes down firmly on the “more than one way” side of the argument in the interest of yielding concise code, for example by offering factory and convenience methods. Another example are the horizontal and vertical layouts which are simplified, streamlined versions of the grid layout.
Design Goals
- Concision, Concision, Concision. The downfall of layout code is its tendency to be extremely verbose. Avoid this by any and all means.
- Strive to be lightweight. Stay focused on solving a single problem. Add no third-party dependencies. Play nicely with other layout mechanisms.
- Lower the learning curve. Keep the barrier to entry low and ensure that the library is easy to master through conceptual simplicity, comments and documentation. Leverage existing understanding of HTML and CSS: container-driven, declarative layout. Provide a demo app that let’s users learn how layout works in an interactive sandbox.
- Optimize around the common case. Ground the design in classic use cases. On the other hand, make no assumptions and support unanticipated usage by being extensible.
- Prioritize developer time. Provide convenience accessors, factory methods etc. to make common tasks easier.
- Keep it simple. When in doubt, leave it out.
- Don’t Reinvent The Wheel. WeView 2 leverages and elaborates upon UIKit’s existing layout mechanism.
- Leverage XCode. Take advantage of XCode’s autocomplete.
- Transparency. Developers need to maintain a mental model of how layout works. Stick to a simple, understandable layout model (cell-based layout) and resist the temptation to get fancy.
- Small pieces, loosely joined. Don’t write a super-layout. Let users build complex layouts by composing containers & layouts.
And lastly: Use a Documentation-Driven Design process:
- A good design is easy to understand.
- A design that is easy to understand should be easy to explain using plain language.
- It is easier to spot complexity in the documentation than in the code.
- Write the documentation as you design the API.
- Whenever the documentation becomes complicated or involved, revisit the design.
API Design References
Next: What's New in WeView 2