Thursday, August 3, 2017

Live Coding iOS and Android with Xamarin: Episodes 1 and 2

In case you've missed it I've started a new weekly show where I live code how to build a cross platform mobile app from scratch using Xamarin.  The show is call lprichar code hour and it's live cast to twitch every Tuesday at 9 PM EDT, UTC-4.  Recorded episodes are on my youtube channel where you can should subscribe to get notified of new episodes.  Here's a recap of the first two episodes:

Episode 1


The first episode I introduced myself and the show, explained what Xamarin is, and how to set up your development environment.  Then I build out a hello world app in Xamarin.Android and Xamarin.iOS.  I flushed out the UI for a calculator in the iOS app using auto-layout constraints.  I explained the pitfalls of using storyboards and showed the all-code alternative using EasyLayout.  Here's the 1st show:




Episode 2


In the second episode I built out a calculator UI in Xamarin.Android.  I explained axml files, LinearLayout's, device independent pixels (dp) vs scaleable pixels (sp), themes, styles, and appcompat.  I also explained some of the pitfalls of axml files in a cross platform architecture.



What's Next


In episode 3 I'll get into how to organize your code to share logic across platforms and how to unit test your logic.  In future episode I'll do page navigation, lists, memory management, and animations.

Call To Action


If this show sounds interesting, please subscribe to my channel on youtube or twitch.  I'd also greatly appreciate you sharing this with friends who might want to learn more about cross platform mobile.  Finally, please write me on twitter or in the comments to let me know how to make the show better or what topics you'd like to see for future episodes.

Wednesday, July 19, 2017

Your Code Sucks, Get Over It



Horrifying. That about describes my first art class. As a computer science major with virtually no art experience I was surrounded by students who had devoted nearly every waking moment to drawing, painting, sculpting, and bending metal into non-functional shapes.

The second class was the worst. Our assignment was to create something in Photoshop and print it out with virtually no instruction. Easy enough I chuckled to myself.

It was 1996, and the school computers had two browsers: Netscape Navigator 1.1, and Mosaic. There was no Wi-Fi, and the dorm rooms had no Internet hook up. Photoshop created files so big you needed Zip, or hot-off-the-press Jaz drives (remember those?) to store your massive 10 to 20-megabyte files! I smugly felt I had a huge leg up in owning my own computer, knowing how to use it, and having "hacked" the dorm phone system to get Internet in my room so I could more easily do research.

Upon entering class, the professor immediately instructed us to place our art at the front of the room.

Oh crap, I thought. Everyone's pieces were beautiful. They'd had no difficulty using a computer. They hadn't needed the Internet to figure out how to use non-dot matrix printers.

With heart in my mouth and head hung low I reluctantly placed by far the worst piece of crap the department had ever seen or will ever see, up for all to critique.

The class lightly critiqued the first several pieces. Minor adjustments, mostly.

When it was my turn there was an awkward silence. After an eternity, the professor let them off the hook by drawing attention to a 2cm square part of my piece as potentially interesting. He suggested I try again this time with a massive zoom. A polite way of saying: "you completely failed, try again".

Reckless Persistence


Despite the humiliation, for some reason I persisted. The group persisted too. Persisted in humiliating me again, and again, and again with constant criticism, three times a week for a semester.

Think your code reviews are bad? This was awful to a whole new level.

Except, at some point this thing happened. It became a little less awful every time. Toward the end I finally came to the realization: I am not my art. The class isn't criticizing me. Each comment of "it fails to engage the viewer's attention because it lacks [insert artsy term]" didn't require an emotional response.

Essentially, they were saying: my art sucks, but that doesn't mean I do.

This is described beautifully in this quote from Steven Pressfield in The War of Art, (a book I highly recommend):

A professional schools herself to stand apart from her performance, even as she gives herself to it heart and soul. … The professional loves her work. She is invested in it wholeheartedly. But she does not forget that the work is not her.

And, it was that realization that allowed me to grow exponentially as an artist. In fact, by the end I can confidently say I was not terrible. Here's one of my final pieces.


Go ahead and critique it in the comments. I would genuinely welcome any feedback. Because, just like the blogs I produce, the CAD models I design, or the code I write, I'll be the first to admit there's lots of room for improvement.

In fact, there're more than just room for improvement. I have proof that my code sucks. Every time I look at anything I wrote more than a few weeks ago I'm consistently embarrassed by it. Doesn't the same thing happen to you? Doesn't your code suck too?  Obtaining good, constructive, feedback just helps you discover sooner those ways in which your code can be improved.

Overcoming Criticism Anxiety


If criticism causes you anxiety, you're not alone. Whether the venue is code reviews, reddit comments, or performance reviews, anxiety is a normal reaction. Here's how Stephen Pressfield describes the problem:

Evolution has programmed us to feel rejection in our guts. This is how the tribe enforced obedience by wielding the thread of expulsion. … Resistance knows this and uses it against us. It uses fear of rejection to paralyze us and prevent us, if not from doing our work, then from exposing it to public evaluation.

If the thought of feedback makes you queasy, consider this idea I learned in the public speaking group Toastmasters: we all have a circle of comfort. We generally go out of our way to stick to the activities in that circle. But, the more time we spend on activities outside of the circle, the larger our circle grows.

While that was originally intended to encourage gaining comfort with public speaking by performing more public speaking, it could as easily be applied to fear of criticism.

If you have anxiety about feedback consider this: instead of avoiding the situation, next time try putting yourself out for feedback even more. Maybe decrease scope to limit exposure, but don't hold back. Try committing to writing a blog post once a month or once a week for a year. Apply for jobs with technical interviews.  Speak at user groups.

The more feedback you receive, the thicker your skin will grow, the more detached from it you will become, the less defensive you'll be, the more of it you can incorporate, and the faster you can grow.

I feel extremely fortunate to have taken that art class and for having chosen persistence over paralysis. It didn't just grow my art skills, it helped free me from anxiety about feedback in general. Because of that experience I honestly love receiving constructive feedback.

And, if increasing feedback frequency doesn't work, just envision your future-self looking back at your code from a few weeks in the future. Imagine your future-self telling you in all sincerity: "Your code sucks". Now it's time to get over it, and figure out how to make it better today.

Tuesday, May 30, 2017

Introducing ELXF: A UI Framework for Concise, Maintainable & Fast Programmatic UI's for Xamarin.Forms

ELXF is a new Xamarin.Forms UI framework that allows you to tap into the 2X speed increase possible with RelativeLayouts, while granting concise UI code, extra power, and improved maintainability.

Today I’m happy to announce a new UI framework for Xamarin.Forms. It’s called EasyLayout.Forms (ELXF) and is an alternative to XAML and to programmatic nested view creation. It's goals are:
    1. Maximize UI performance by reducing excess render cycles associated with traditional view nesting
    2. Increase maintainability and readability by removing ceremony and keeping layout code concise
    3. Simplify usage of RelativeLayout while increasing its power and abstracting away its quirks

    In this post I’ll briefly explain what it is, then get into why we need a new UI framework in the context of each of the above three goals. I'll finish with limitations, some history, and how to get started.

    What Is ELXF?


    EasyLayout.Forms (ELXF) is a C# Domain Specific Language that allows you to define the relationships between children in a RelativeLayout. For example to position one element 50px below another in XAML you would normally do this:

    <RelativeLayout>
        <Label
            RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToView, Property=X, ElementName=MainLabel, Constant=0}"
            RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToView, Property=Y, ElementName=MainLabel, Constant=50}"
            RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToView, Property=Width, ElementName=MainLabel}"
            RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToView, Property=Height, ElementName=MainLabel}"
            Text="RelativeLabel"
            />
    </RelativeLayout>

    With ELXF you can do the same thing like this:

    _relativeLayout.ConstrainLayout(() =>
        _relativeLabel.Bounds.Top == _mainLabel.Bounds.Top + 50 &&
        _relativeLabel.Bounds.Left == _mainLabel.Bounds.Left &&
        _relativeLabel.Bounds.Width == _mainLabel.Bounds.Width &&
        _relativeLabel.Bounds.Height == _mainLabel.Bounds.Height)

    There's a handy self-documenting page that summerizes all of the options on github in LayoutExamplePage.cs.



    But what's wrong with the regular way of doing layouts? Why do we need a new framework?

    Maximize Performance


    Today, regardless of whether you choose to layout UI with XAML or programmatically, the path of least resistance is to create nested view layouts with several levels of StackLayout’s, Grid’s, TableView’s, and custom views.

    This creates a performance problem that Michael Ridland explains extremely well in his article Hacking the Xamarin.Forms Layout System for Fun and Profit. It’s worth reading the article a couple of times if you haven’t, but here is one of his key points:

    A child of a stacklayout will always cause a full layout cycle, there’s no way a StackLayout can short circuit this cycle.

    The solution is described on the Xamarin.Forms documentation on ListView performance:

    AbsoluteLayout has the potential to perform layouts without a single measure call. This makes it very powerful for performance. If AbsoluteLayout cannot be used, consider RelativeLayout.

    To better illustrate the problem and its solution I created two Xamarin Forms pages, one using view nesting, and one using a RelativeLayout with ELXF. The page simply shows some products (from Northwind) and you can tap one of them to select and then confirm the choice.



    The nested view version goes four levels deep on the header and three levels deep in the ListView.


    This may look complicated in a single image, but I honestly feel this is fairly typical if not actually simpler than what a real-world app might do.

    To compare the performance, I counted the number of measure and draw cycles for each label after performing the same set of steps on each version of the page (scroll, select 3 products, update text in all labels 3 times aka click calculator button 4 times). I then gave a score to each label based on roughly how expensive it was to draw, and set colors to show a heat map.

    Here's the traditional page:


    And here’s the RelativeLayout with ELXF version:



    The numbers in parenthesis are the number of measure operations and the number of draw operations. As you can see the 2nd one is roughly twice as fast.

    If you want to check these out yourself* the main pages are at: TraditionalPerformancePage.xaml and ElxfPerformancePage.cs and the custom views are in the Controls folder. There's a lot more to this topic such as the importance of fully constraining your views that I'll save for a later post.

    For now we've confirmed the Xamarin documentation and know RelativeLayout’s generally outperform nested views. But why not just use RelativeLayout’s in XAML or programmatically?

    * fyi there's currently an issue in Xamarin.Android 7.3.1 for Visual Studio users that causes RelativeLayouts in ListViews to load extremely slowly on Android. The current workaround is to build from a Mac.

    Increase Maintainability


    Consider the following example in XAML:

    <RelativeLayout>
        <Label BackgroundColor="Aqua"
            Text="Main Label"
            x:Name="MainLabel"
            RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToParent, Property=X, Constant=10}"
            RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent, Property=Y, Constant=10}"
            RelativeLayout.WidthConstraint="{ConstraintExpression Type=Constant, Constant=100}"
            RelativeLayout.HeightConstraint="{ConstraintExpression Type=Constant, Constant=40}"
            />
        <Label BackgroundColor="OrangeRed"
            RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToView, Property=X, ElementName=MainLabel, Constant=110}"
            RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToView, Property=Y, ElementName=MainLabel, Constant=50}"
            RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToView, Property=Width, ElementName=MainLabel}"
            RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToView, Property=Height, ElementName=MainLabel}"
            Text="RelativeLabel"
            />
    </RelativeLayout>


    This renders two labels like this:




    I don’t know about you, but I find that code very hard to read. The ELXF version of that looks like this:

    relativeLayout.ConstrainLayout(() =>
        _mainLabel.Bounds.Top == relativeLayout.Bounds.Top + 10 &&
        _mainLabel.Bounds.Left == relativeLayout.Bounds.Left + 10 &&
        _mainLabel.Bounds.Width == 150 &&
        _mainLabel.Bounds.Height == 40 &&

        _relativeLabel.Bounds.Top == _mainLabel.Bounds.Bottom + 10 &&
        _relativeLabel.Bounds.Left == _mainLabel.Bounds.Right + 10 &&
        _relativeLabel.Bounds.Width == _mainLabel.Bounds.Width &&
        _relativeLabel.Bounds.Height == _mainLabel.Bounds.Width
    )

    It’s concise, powerful, and the syntax is always verified by the compiler. It also fixes a duplication problem in that XAML example. Can you spot the issue?

    Simplify RelativeLayout


    While Xamarin.Forms RelativeLayout’s aren’t exactly broken, they are far less powerful than iOS’s Autolayout or even Android’s RelativeLayout with it's fairly extensive set of LayoutParams. The good news is Xamarin realizes this and have plans to introduce a more powerful version in Xamarin.Forms 3. The problem today, however, is that they essentially only allow you to control the top left pixel.

    For example if you look again at the XAML above you’ll see that to align RelativeLabel to the right of MainLabel we had to add 110 (the width of MainLabel plus a margin) to RelativeLabel’s X. What we really want is an attribute like RelativeLayout.RightEdgeConstraint instead of the RelativeLayout.XConstraint attribute.

    As it stands if we ever change MainLabel’s width, we must remember to increment RelativeLabel’s XConstraint. That's the kind of duplication that hides bugs and complicates maintainability. However, even without ELXS we can do a little better.

    If we write this in code it looks like this:

    relativeLayout.Children.Add(mainLabel,
        Constraint.RelativeToParent(rl => rl.X + 10),
        Constraint.RelativeToParent(rl => rl.Y + 10),
        Constraint.Constant(100),
        Constraint.Constant(40)
        );

    relativeLayout.Children.Add(relativeLabel,
        Constraint.RelativeToView(mainLabel, (rl, v) => v.X + v.Width + 10),
        Constraint.RelativeToView(mainLabel, (rl, v) => v.Y + v.Height + 10),
        Constraint.RelativeToView(mainLabel, (rl, v) => v.Width),
        Constraint.RelativeToView(mainLabel, (rl, v) => v.Height)
        );


    Better, right? RelativeLayouts in code have more power. So maybe we don't need a new framework after-all.

    Except, even if you don't agree that the ELXS version of

    _relativeLabel.Bounds.Left == _mainLabel.Bounds.Right + 10

    is easier on the eyes than

    Constraint.RelativeToView(mainLabel, (rl, v) => v.X + v.Width + 10)

    the code-behind version still has serious limitations when it comes to Centering elements.

    The Centering Problem


    Suppose we want to center-align a 3rd view under the 2nd one. If we attempt something like this:

    relativeLayout.Children.Add(centerLabel,
        Constraint.RelativeToView(relativeLabel,
            (rl, v) => v.X + (v.Width * .5f) – (centerLabel.Width * .5f)),
        Constraint.RelativeToView(relativeLabel,
            (rl, v) => v.Y + v.Height)
        );


    We’ll discover that it renders like this:


    Why didn’t CenterLabel pull further left? It’s because when the XConstraint lambda was evaluated, 'centerLabel' hadn’t been rendered yet. A non-rendered view gives a Width or Height of -1. The solution, documented nicely in this StackOverflow post, is this:

    Size GetSize(VisualElement ve, RelativeLayout rl) =>
        ve.Measure(rl.Width, rl.Height).Request;

    relativeLayout.Children.Add(centerLabel,
        Constraint.RelativeToView(relativeLabel,
            (rl, v) => v.X + (v.Width * .5f) - (GetSize(centerLabel, rl).Width * .5f)),
        Constraint.RelativeToView(relativeLabel,
            (rl, v) => v.Y + v.Height + 10)
        );

    That GetSize() local function (some C# 7 sugar) solves the problem by calculating what the width of centerLabel will be after it’s rendered. That renders nicely like this:


    While that works, perhaps you’ll agree that it's difficult to discern intent among all that math. A complex page with a lot of this style code is liable to hide bugs and obfuscate intent.

    Worse, it’s not always this easy. What if we want CenterLabel to have a width relative to MainLabel. If we do this:
    relativeLayout.Children.Add(centerLabel,
        Constraint.RelativeToView(relativeLabel,
            (rl, v) => v.X + (v.Width * .5f) - (GetSize(centerLabel, rl).Width / 2)),
        Constraint.RelativeToView(relativeLabel,
            (rl, v) => v.Y + v.Height + 10),
        Constraint.RelativeToView(mainLabel,
            (rl, v) => v.Width)
        );

    We end up with this:


    The problem is our GetSize() method is calculating the width of the label prior to any RelativeLayout width constraints.

    This is the point at which we’re stuck with the solution of hard-coding (duplicating) MainLabel’s width.

    ELXF to the Rescue


    EasyLayout.Forms can solve the centering problem. It translates LINQ expressions into Children.Add() calls with the correct parameters, it incorporates calls to a GetSize() type function when necessary, and in many cases it can solve the GetCenter() problem from above by searching back through prior LINQ expressions to determine what height or width the current element should be.
    The final solution turns into this:


    relativeLayout.ConstrainLayout(() =>
        _mainLabel.Bounds.Top == relativeLayout.Bounds.Top + 10 &&
        _mainLabel.Bounds.Left == relativeLayout.Bounds.Left + 10 &&
        _mainLabel.Bounds.Width == 150 &&
        _mainLabel.Bounds.Height == 40 &&

        _relativeLabel.Bounds.Top == _mainLabel.Bounds.Bottom + 10 &&
        _relativeLabel.Bounds.Left == _mainLabel.Bounds.Right + 10 &&
        _relativeLabel.Bounds.Width == _mainLabel.Bounds.Width &&
        _relativeLabel.Bounds.Height == _mainLabel.Bounds.Height &&

        _centerLabel.Bounds.GetCenterX() == _relativeLabel.Bounds.GetCenterX() &&
        _centerLabel.Bounds.Top == _relativeLabel.Bounds.Bottom + 10
        );

    Limitations


    ELXF makes the RelativeLayout more powerful, but it can't patch over all of the issues. Until Xamarin.Forms 3 comes out, the following are a few of the known issues:
    • If you update the text of a view with Right or Center constraints, the relative layout doesn’t know to redraw it. To force the redraw you have to call relativeLayout.ForceLayout() twice
    • You can’t currently constrain a Left edge to one view and a Right edge to another view the way you could with iOS Autolayout. The workaround is to set the width just like you would with a regular RelativeLayout
    • Unlike the iOS version of EasyLayout, be aware that ELXF has no less than or greater than constraints

    A Brief History

    Speaking of the iOS version of EasyLayout, I must give credit where it's due and provide some context. EasyLayout is a UI framework originally developed by Frank Krueger (@praeclarum) to simplify doing programmatic Autolayout in Xamarin.iOS. It does this by creating a simple DSL using the awesome Expression Trees feature of C#. EasyLayout for iOS is so powerful that I wouldn’t start a Xamarin.iOS project without it, and I honestly feel sorry for traditional iOS developers for not having anything like it. But it was only for Xamarin iOS.

    Then, earlier this year, my team decided to move away from AXML files on our Xamarin.Android project. They did this because on our large project AXML files take a very long time to generate and significantly slow development. I took the opportunity to port EasyLayout to Android in the form of EasyLayout.Droid. This turned out to be a fantastic solution for our team, and I now wouldn’t do a Xamarin Android project without EasyLayout.Droid.

    While ELXF is not yet as mature as its predecessors, I did at least have the opportunity to bring in lessons learned from two mature projects.

    Getting Started


    If you'd like to give it a spin you can install it via nuget into a project with:

    Install-Package EasyLayout.Forms

    The source code is all at GitHub and there are an extensive set of examples in the source code like here and here. And as mentioned there is a self documenting page. Also if you clone source there is a playground page where you can experiment.

    What's nice is that if you like it you can adopt ELXF on your existing projects on a page by page basis. In fact, you can even use it for just a single view in a single relative layout. There's no obligation to adopt it everywhere. Just don't be surprised if, like me, you grow to like it enough to want it everywhere.

    Summary


    If you end up using and liking EasyLayout.Forms please shoot me a note on twitter @lprichar, I'd love to hear from you.