Larry Price

And The Endless Cup Of Coffee

XML Parsing in Go

| Comments

Need to parse an XML file in go? XML (en|de)coding is build into go’s standard library. Basic parsing of nodes and embedded nodes is straightforward, but there are some interesting things to think about when you need to parse attributes, lists, and if you don’t want to create new structs all over the place.

For this exercise, let’s look at the following XML document:

1
2
3
4
5
6
7
8
9
10
11
12
13
<person>
  <name>Luann Van Houten</name>
  <addresses>
      <address type="secondary">
          <street>321 MadeUp Lane</street>
          <city>Shelbyville</city>
      </address>
      <address type="primary">
          <street>123 Fake St</street>
          <city>Springfield</city>
      </address>
  </addresses>
</person>

Defining a Data Structure

The simplest node to parse is going to be <name>. We’ll need an object to unmarshal the XML into, which we’ll call Person. Every field on Person will be evaluated by the XML encoder to be populated based on the field’s name. However, our struct field names and node names don’t usually correspond that simply. Because of this, we’ll use xml struct tags to identify how to map each node to a go field. Here’s an example for <name>:

1
2
3
type Person struct {
  Name string `xml:"name"`
}

The next node contains a list of <address> nodes. For an address node, we’ll have to create a similar struct with City and Street fields:

1
2
3
4
type Address struct {
  Street string `xml:"street"`
  City string   `xml:"city"`
}

While parsing each Address, we also want to find the type of address, which can be found as an attribute on the <address> node. By adding attr to our XML struct tag, we can properly parse the type field as well:

1
2
3
4
5
type Address struct {
  Street string `xml:"street"`
  City string   `xml:"city"`
  Type string   `xml:"type,attr"`
}

A Person has a list of Addresses. Since we know that address is a direct descendant, we can use the > keyword to parse each <address> from <addresses> into an embedded struct on our Person struct.

1
2
3
4
type Person struct {
  Name string         `xml:"name"`
  Addresses []Address `xml:"addresses>address"`
}

This code will work to parse the original document, but do we really need to define a formal struct for addresses? If there was only one address, we could put all the fields directly on the Person struct. However, since we’re dealing with a list, our best option is to use an anonymous struct:

1
2
3
4
5
6
7
8
type Person struct {
  Name      string `xml:"name"`
  Addresses []struct {
      Street string `xml:"street"`
      City   string `xml:"city"`
      Type   string `xml:"type,attr"`
  } `xml:"addresses>address"`
}

Binding the Data Structure

We can use the encoding/xml package to decode the given XML. Given that our raw XML document is stored in a []byte called document, we’ll use xml.Unmarshal to bind our data structure to the XML document:

1
2
var luann Person
xml.Unmarshal(document, &luann)

Final Code

Let’s put it all together, including a main function that will use fmt.Println to print the results of binding the data structure to the XML document. Unmarshal could return an error, but we’ll ignore it in this case.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package main

import (
  "encoding/xml"
  "fmt"
)

var personXML = []byte(`
<person>
  <name>Luann Van Houten</name>
  <addresses>
      <address type="secondary">
          <street>321 MadeUp Lane</street>
          <city>Shelbyville</city>
      </address>
      <address type="primary">
          <street>123 Fake St</street>
          <city>Springfield</city>
      </address>
  </addresses>
</person>`)

type Person struct {
  Name      string `xml:"name"`
  Addresses []struct {
      Street string `xml:"street"`
      City   string `xml:"city"`
      Type   string `xml:"type,attr"`
  } `xml:"addresses>address"`
}

func main() {
  var luann Person
  xml.Unmarshal(personXML, &luann)
  fmt.Println(luann)
}

I’ve posted this code as a gist in the go playground so you can see it in action.

Responsible Responsive Design

| Comments

The Gist

In this modern age of infinite internet-capable devices, web developers have found a “silver bullet” which we call responsive design. Unfortunately, responsive design is often coupled with large CSS files, delayed element styling, and an overabundance of javascript. Scott Jehl has penned Responsible Responsive Design to help us make the web better. The strategies outlined in this book will make your web pages smarter, faster, and lighter.

Takeaways

We are spoiled by 4G, unlimited data, fiber, and the latest smart devices. Most of the world does not have the same luxury as the majority of web designers. We severely limit our userbase when we consider our own lifestyles as the norm. If you want any chance of obtaining a global audience, your site must be able to deal with slow connections, data limits, small screens, and outdated browsers.

The average site still takes 10 seconds to load. Despite generally better network speeds, we have started delivering more CSS, javascript and markup; bigger, higher res images when they aren’t always necessary; and long-running javascript to take advantage of the latest and greatest framework. We can and should work to deliver only the content users need.

We can load the top part of the page a user will see before loading the rest of the page by pulling some of our styles into the <head>. In doing this, we can prevent a Flash of Unstyled Content (FOUC) when the user first visits the page. There are tools to do this mentioned in the book, such as criticalcss. You can go a step further and load the rest of your CSS at the end of the event queue. Even better: only deliver that experience the first time the user visits that page, after which the browser will have cached the CSS and you can load it through the usual means.

Design your first drafts as naked HTML and CSS. This will be the base experience for a user having a really bad day. Users using old technology, block or fail to load javascript, or experience a bad connection will be able to experience a decent version of your site. Iterate to add a better experience for users who can load javascript. Iterate again to add HTML5 or CSS3 features which may not be available in all browsers. The important aspect is that the app will always degrade gracefully.

Start with the mobile version. If you can design for a small screen with weird gesture inputs, you should be able to translate that to a tablet and desktop machine. Use @media magic to deliver the right content.

Use HTML5 elements when possible. <picture> and <video> can be very efficient in choosing which images or videos to load from the server, preventing the client from downloading the 1x, 2x, 3x versions of your images. Don’t forget about <svg> either for handling vector graphics.

Screen readers read everything visible. This can cause a lot of bad things to happen. Using display: none will prevent screen readers from telling the user about your collapsed items (think of all the wasted hamburgers). Elements strategically hidden with z-index are listed by the screen reader as a visible element, potentially misinterpreting your intent. Markup created dynamically could have a drastic effect on that user’s experience. We should be diligent with our markup to remain inclusive.

Polyfill, shims, and shivs are some common terms to refer to libraries which fake modern browser functionality into older browsers. html5shiv, selectivizr, and modernizr can be described by these words.

My Action Items

  • Start Small. Although I’ve had several projects where I/we start out saying we’ll be mobile first, I don’t believe this has ever actually happened to me. Next time I start a web project I want to start with mobile and expand.
  • Degrade Gracefully. I’m notably terrible at this. I don’t think I’ve ever created a site which will respond well with javascript disabled let alone any HTML5 features which may be missing. I always design my websites with my own devices and connection speeds in mind. For the time being, I will also put this item off until I have the chance to start a project from scratch.
  • Pay Attention to Accessibility. Accessibility hasn’t been on my mind much when throwing together web sites. If I get some time, I’d like to look into adding better screen reader attributes into a live web application like Ollert.
  • Page load budgets. Jehl discusses getting strict about page load time. Keep it low and weigh load time effects heavily when deciding to add new features to a site. When I add new features to pages, I intend to keep this in mind. Look for this to affect something like Ollert if I ever get around to redesigning the dashboard.

Noty for Easy, Breezy, Beautiful Flash Messages

| Comments

Noty is a jQuery plugin for showing flash messages. Noty is easy to use and creates great-looking flash notifications with little customization.

What’s a flash message?

Flash messages are used to display small bits of information to a user without changing existing page content. If there is an error making an AJAX request, we can display an error flash message to let the user know to try again later. If there is a new shortcut available, we could let the user know with an information flash message.

Example Time

You’ll need a copy of Noty. As of this time, I haven’t seen a CDN hosting the minified version of Noty, so you can download it directly from Github and put it somewhere nice. Add a <script> tag to your HTML including the library and let’s start using it.

Let’s create a single button on our HTML page that, when clicked, will create a new Noty error flash message in the top left.

Cool, right? Break it down:

  • text
    • Obviously, this is the text that will be displayed
  • layout
    • This allows us to change the position of the flash message. In this case I chose topleft, but other options include top, topCenter, topRight, center, centerLeft, centerRight, bottom, bottomLeft, bottomCenter, and bottomRight
  • timeout
    • How long the notification will stay on the screen (in milliseconds). false for a permanant notification.
  • type
    • Style of notification to display. Options include error, success, alert, warning, confirmation, and information.

Let’s add some more so we can see the difference.

Three notifications, one which stays up for 500ms, one which stays up for 5000ms, and one which stays up indefinitely. I also set the killer property to true on the error notification such that the error notification will close all other notifications. Additionally, I added the closeWith property to the success message to close it by clicking. All of these notifications come up in different locations on the page.

We should also think about theming our notifications. To create a “full” theme for Noty is a lot of Javascript - the odds are pretty good you just want to change the color. We can essentially inherit from the default theme and change the colors of the error and information notifictaions in our new theme like this:

testtheme.noty.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
$.noty.themes.testtheme = Object.create($.noty.themes.defaultTheme);
$.noty.themes.testtheme.name = 'testtheme';
$.noty.themes.testtheme.style = function () {
    $.noty.themes.defaultTheme.style.apply(this);
    switch (this.options.type) {
        case 'error':
            this.$bar.css({
                backgroundColor: '#DC569F',
                borderColor: '#DC569F',
                color: '#F5F5F5'
            });
            break;
        case 'information':
            this.$bar.css({
                backgroundColor: '#ABABAB',
                borderColor: '#DC569F',
                color: '#F5F5F5'
            });
            break;
        default:
          break;
    }
    this.$message.css({
        fontWeight: 'bold'
    });
};

We create our new theme testtheme from the defaultTheme prototype and change the name and style properties. Within our custom style function, we go ahead and apply the default theme’s style. Then we add a few more adjustments based on the current notification type. Thank goodness it’s javascript. Don’t forget to include your testtheme.noty.js file in a <script> tag in your HTML. We can apply this theme to any of our notifications by adding the theme property to our call to noty with a value of ‘testtheme’ (which is the name of the theme we just created). Here’s the fiddle showing off our new theme:

There are many other customization options for the brave, including custom animations and callbacks when the notifications are dismissed. See the full documentation site for more details.

Extreme Programming Explained

| Comments

The Gist

Extreme Programming Explained is the de facto book on XP written by Kent Beck. In the world of XP, software development is fun and efficient. Communication is open between all parties, pair programming is mandatory, builds are short, and tests are written before production code. Beck invites the reader to apply bits and pieces of XP to the development process to see incremental improvements, which is a very XP way of implementing XP.

Takeaways

XP is about solving people problems. Nearly every challenge we face during software development is caused by dealing with people. Communication is key to fixing most of these problems. On a developer level, pair programming and colocation form closer relationships and cause more conversations to occur.

Do everything in small chunks. Whether you are designing a user experience, architecting a system, or estimating stories you should only address as little as responsible at a time. This means architect a small system first and adapt as a more complex architecture becomes necessary instead of doing it all at once. Create a user interface for the next week’s worth of work instead of the whole project. Small chunks means tighter feedback loops and less wasted effort when specs change (and they will change).

Software is built by people. People don’t like to be referred to as “cogs in a machine.” People make mistakes and people create (process) waste. People like to think they are contributing to the success of the company and they like to feel good about what they are creating.

10-minute builds. Beck claims that the perfect build takes 10 minutes; anything more makes people not want to wait for it to finish and anything less isn’t enough time to take a coffee break. This concept is not for your constant, at-your-desk 10-second build. When I push my code to the server, it will compile a clean build and run every regression and integration and UX test within 10 minutes. If your regular, 100 times a day desktop build takes more than 10 minutes, you may want to see a shrink.

Teammates should have disagreements but not knife fights (at least not while on the clock). If there are no dissenting opinions about how to implement something you may never find the most efficient answer.

Automated tests are a man’s best friend. Tests are a contract describing what the code currently does. Tests can be run by any programmer to verify a working system.

Did I mention test-first development? I’ve been through TDD trainings and found testing first difficult to follow strictly. The point of writing your tests first is to prevent any unwanted or undocumented side-effects in the code you just wrote. If you can delete a line of code and the tests still pass, that line of code is either unnecessary or untested.

Taking baby steps is okay. It’s unlikely you’ll be able to institute all the great changes recommended by XP. Start by figuring out how to get your 15-minute build under 10 minutes. “Force” your usually unwilling teammate to pair with you when working on a piece of code within said teammate’s area of expertise. Take a piece of untested code and wrap it in tests.

My Action Items

  • Write more tests. I’ve been having a tough time getting tests written in this current project because it’s largely UI and initializing a provided library. This week I want to come out net-positive on tests.
  • Test first. I’ve accomplished this on a few occasions, including a recent bug fix I pushed to an open-source library I created. But this is hard. I have a tendency to dive in headfirst when a test could help set the stage for a simpler design.
  • 1-week iterations. I have pushed against 1-week iterations because I often found them to be “too short,” but I’m starting to come around to the idea of getting 1-2 items done per developer (or pair) per iteration. Other benefits include shorter feedback loop and less estimation required. My current project is a team of one, so this action item might have to sit on the backburner for a few months.

Muck With History Using the HTML5 History API

| Comments

Congratulations! You just made a single page web application [SPWA] to do All The Things. What happens when you hit the Back button in the browser? Oops.

The Back button is the most used navigation button in the modern browser. SPWA often break the functionality of the Back button. We can fix this using the HTML 5 History API.

For this demo, I’ll make a simple web page starting with the text “Page 1” and a “Continue” button. When I click the “Continue” button, “Welcome” will change to “Page 1”; when I click “Page 1”, I change to “Page 2”; ad infinitum. My initial page looks like this:

index.html
1
2
3
4
<span id="content" style="margin-bottom: 1.5em;">Welcome</span>
<button id="continue" onclick="nextPage()">
  Continue
</button>
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
// ...
function nextPage() {
  var content = document.getElementById("content");
  if (content.innerHTML === "Welcome") {
    updatePageContent(1);
  } else {
    updatePageContent(parseInt(content.innerHTML.slice(5))+1);
  }
}
function updatePageContent(pageNumber) {
  document.getElementById("content").innerHTML = "Page " + pageNumber;
}
// ...

Running this code and clicking “Continue”, the user has no way to go back. He or she would need to start over from the beginning, which is bad for the user and bad for us too. We can update the browser’s history using pushState and popState commands from the History API. For this contrived example, I’ll add my pushState call in the nextPage function:

index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// ...
function nextPage() {
  var content = document.getElementById("content"),
      nextPage = 1;
  if (content.innerHTML === "Welcome") {
    updatePageContent(nextPage);
  } else {
    nextPage = parseInt(content.innerHTML.slice(5))+1;
    updatePageContent(nextPage);
  }

  history.pushState(null, null, "?page=" + nextPage);
}

// ...

Now the site will add ?page= to the URL whenever we update the page number. This happens when we call history.pushState. In the call to history.pushState, the first argument is some data identifying the state, the second argument is the title of the new page but is currently unused by all the major browsers, and the third argument is the URL of the new state.

In doing this, the Back button has become enabled in the browser. However, it still doesn’t work. That’s where popState comes in. popState is the other side of the equation which figures out how to change the page when the user hits the Back button. I’ll update the call to pushState to include the page number in the state arugment so we can use it.

index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// ...

function nextPage() {
  var content = document.getElementById("content"),
      nextPage = 1;
  if (content.innerHTML === "Welcome") {
    updatePageContent(nextPage);
  } else {
    nextPage = parseInt(content.innerHTML.slice(5))+1;
    updatePageContent(nextPage);
  }

  history.pushState(nextPage, null, "?page=" + nextPage);
}

function updatePageContent(pageNumber) {
  var content = document.getElementById("content");
  if (pageNumber === 0) {
    content.innerHTML = "Welcome";
  } else {
    content.innerHTML = "Page " + pageNumber;
  }
}

window.onpopstate = function(event) {
  updatePageContent(event.state || 0);
}

// ...

Now your history should be mostly working. Hitting Back should take you to the previous page, then hitting Forward should take you to the next page.

There is currently a bug in the version of webkit Safari uses which causes a popstate event to fire on initial page load. We can try to fix this using the replaceState call on page load to set our history’s state to the initial value. You can add this event to the bottom of your javascript:

index.html
1
2
3
4
5
6
7
// ... 

window.onload = function() {
  history.replaceState(0, null, "");
}

// ...

Of course, I want my web page to be smarter than this. If the user explicitly visits “mysweetpage.com?page=3” I want the user to be presented with page 3’s epic content. Let’s modify that onload function to check the current URL state and figure out which page the user has visited:

index.html
1
2
3
4
5
6
7
8
9
// ...

window.onload = function() {
  var currentPage = parseInt(window.location.search.slice(6)) || 0;
  updatePageContent(currentPage);
  history.replaceState(currentPage, null, window.location.search);
}

// ...

History changed. Forever. Changing history is a good idea but can easily lead to an even more confusing user scenario. Choose when to change history based on when your application would traditionally need to bring up a new page. Once you have Back working, make sure Forward also acts as expected. Thinking about how you’ll integrate the History API into your web application can help you write more sensible, modular code.

If you’re looking for the full code that we created above, check out this gist.

<3 HTML5