Shift Left – a presentation by Melanie Sumner
A presentation at #PerfMatters in March 2020 in by Melanie Sumner
Shift Left – a presentation by Melanie Sumner
My name is Melanie Sumner. I am a senior software engineer at LinkedIn and work on the internal accessibility-focused tooling that our developers use to make LinkedIn products. I’m also a core team member for the Ember JavaScript framework, and a judge for CSS design awards (and yes, I run accessibility checks on all sites that I judge) …but before that I served as an intelligence analyst in the U.S. Navy.
One of the ways we introduce ourselves at work is to share something about ourselves that isn’t on our LinkedIn profile.
For me, it’s usually one of two things- first, that I met my husband in a video game called Final Fantasy XI The other is that one of our favorite video games is Portal, and we named our cats after characters in the game- Atlas and P-body.
Today we’ll talk about how people learned to code, pattern documentation and how to make sure your documentation is up to par, ways that you can adopt the “shift-left” mindset, and how I think this will not only improve the quality of our codebases and prevent regressions before they happen, but also help you level up your craft.
First, a story. My son brought home some coding homework the other week. I was excited. Dangerously excited.
Since he was born, programming books have just been around. Casually. No pressure. Maybe a few hints. No pressure though.
Anyway, his homework was kind of like that Lightbot code game- learn about procedures, loops and conditionals while helping a character move around a map and turn lights on and off. I helped him get through his homework but…he’s 13 and it was homework. He wasn’t as excited about it as I’d been. No, I didn’t cry bitter tears of disappointment, but I did start to think about how I learned to code…which, of course, led to me thinking a lot about how other people learn to code.
And the different kinds of learning paths there are and how that really effects our work.
So how do folks learn? I’ve seen a few different paths: Maybe it’s a hobby that was turned into a career. Maybe it’s a degree in computer science. Maybe it was a second career after a coding bootcamp. Or maybe it’s a self-taught learning path. All of these ways are equally viable- but they are all unavoidably incomplete when you’re building for the web-
if the past 31 years of the web have taught us anything, it’s that change is constant and that means any learning path you choose is going to inevitably leave something out. This is especially true when it comes to crafting accessible, performant experiences for the web.
Continuous learning is a must, and I don’t mean in a theoretical sense. There is always something new to learn for front-end web development, and excellence goes beyond lines of code. And to be clear, I don’t think that there’s just one way to do this. I think really depends on what part of the stack you’re focused on, how you learned to code, and what your interests and goals are. For example, If you have a computer science degree but you’re building UI components for a living, additional study will be necessary in user experience and design. If you’re a bootcamp-trained developer who finds themselves writing tools, additional computer science study will likely be necessary to improve the tools you create. And no matter what kind of education you have gotten, you will likely need to study assistive technology since it’s not included in most curricula.
An example of this in another field is in soccer. Or football if you name things correctly. It’s okay. Naming things is hard. Anyway. Usually, players will develop the basic skillset of the game- endurance, ball handling, and game strategy. Then players will find their niche – the kind of position they play- offense or defense
and an area of the pitch- left, right, or center. As a result, you can end up with different play styles – or career tracks, if you will- I’ve identified three of them.
There’s the kind of player that develops as an all-around player on either offense or defense but can play on any area of the pitch- someone like Thomas Mueller, who plays offense but can do it from any area of the pitch - left, center, or right. His specialty is finding whatever space exists.
Sometimes, even after they’ve trained for their niche, a coach can ask them to switch things up- and a left back like Gareth Bale became left wing instead.
Other times, players develop their niche and stay with that no matter what kit they are wearing. Fernando Torres was a striker for his entire career.
No matter what kind of developer you are- think about the position you’re playing right now, and further develop your skillset accordingly. Some percentage of your time must involve either deeper knowledge of the niche you already are in or balancing out your skillset by increasing your knowledge of the domains that will be affected by your work.
So, here’s a tip for you, especially if you work in the front-end: Think beyond the words of the task you’ve been given. There are a lot of other things that we should automatically be applying to our work. Excellence cannot be spelled out in every single JIRA ticket. Let’s look at this painting called The Milkmaid by Johannes Vermeer. Let’s imagine this as a JIRA ticket. It’ll have the EPIC, the user STORY, the SUB-TASKS, and Story Points- five, obviously. Let’s look at these sub-tasks: gather materials, paint the picture, bring picture to gallery.
It didn’t include “use superb lighting techniques to create depth” or “use perspective correctly” – those are just part of what it means to be an artist.
While there’s not a direct 1-1 parallel since we have user experience and visual designers to support us as developers, I think the point still holds up- there are parts of our expertise that we must bring to every task, every day. These things should not have to be spelled out every time, but I think that sometimes it’s easy to forget what they are in the hustle and bustle of shipping that feature by last week.
To help us remember, we can use checklists- For example, here are some questions we can ask ourselves questions to help us keep our users in mind. Would I enjoy this user experience? Could I perform this workflow with my eyes closed? Could I still complete this workflow with only my keyboard? If I blurred my vision and looked at the screen, could I still tell where the focus outlines are as I TAB through the interface? If I pulled this up on my mobile device, what happens when I have the accessibility settings turned on? Do I know what this looks like in high contrast mode? For every new feature request that comes in, do a self-check. Do you know how that new feature request will affect your user experience?
I want you to especially think about that the next time you start to engage with a designer on a new feature. One way to do this is to find a common shared understanding through UI Patterns. But when we think about patterns, what comes to mind?
A typical pattern looks something like thisBasic examples that show how to use it Variations on the basic example to demonstrate some flexibility A rendered sample of the pattern so you can get an idea of what it should look like Some way to copy the code so you can paste it into your own IDE. These patterns are typical, but I believe they are missing the essentials. Now maybe you’re thinking, yes, this is enough for me to ship a feature.
Maybe you think that it’s someone else’s job to consider performance or accessibility, which can help to rationalize any given number of realities we face on a daily basispoor management, general a11y ignorance, even sometimes our own laziness. The thing is, even the most concise framework code in the world will not matter if we’re not thinking about the feature code that we create.
The patterns we create should be beautiful.
They should be easy for developers to use with step-by-step instructions.
But if it’s missing essential information, it can be unusable for a sizeable portion of your userbase!
We can confirm this with some math: What’s an optimal DOM tree look like? Less than 1500 nodes Max depth of 32 nodes No parent node with more than 60 child nodes. Not only will the “non-optimal” experience feel sluggish- which really should be enough for us to re-visit implementation –
it will also make screen readers outright crash. If we are working on any kind code that needs to scale globally, we must be especially aware of this.
So what are we missing in our patterns?
We must not accept the quick answer with the complete answer. It’s great that we can find solutions quickly on places like StackOverflow, but that is simply not enough.
Patterns should tell us what to do- and give some reasoning as to why. This will help our brains with long-term learning.
Patterns should also include anti-patterns. What not to do- and why not to do them. By investing the effort to create patterns that are the complete answer, we give ourselves the right tools to craft better solutions for our users. By understanding both the pattern and the anti-pattern, we will have better intuition for to raise a red flag on a new design or a prototype. No more of that “deer in the headlights” kind of feeling- you know what I’m talking about, right? When you know the feature isn’t going to work but you’re not quite sure why, so you ship it anyway, and sure enough, there are issues with it later. Understanding the patterns and their anti-patterns will make this go away, because it helps us to get to the finish line, instead of stopping at an incomplete solution.
Here’s the thing- If it’s missing information about things like performance and accessibility, then it’s not a complete solution. This is not meant to make anyone feel bad but rather should be a signal that we’re not finished thinking about the problem YET. Don’t stop until you get there- I’ve seen too many features need a complete re-write after the fact, because they decided to delay accessibility audits until later. If you think about a11y and performance as core requirements, you’ll have a better MVP instead of technical debt to pay off later.
By equipping ourselves with a more holistic view of our digital products, we enable developers to stop issues sooner. Prevent bugs before they even start. We can increase the percentage of our codebase that doesn’t regress in the first place.
Do you know how many accessibility issues your product has? If you don’t, do you know how to find out? What about performance issues? If you don’t know, you need to find out. While audits can help with this, they are only part of the answer.
Tooling is what helps us to shift this work left- directly into the developer workflow. In some cases, they might be tools we’re still trying to create, but first let’s look at the ones we already have. We have linting tools, we have testing tools, and we have performance analysis tools. These tools can help us before we ship code to production. I’m going to say this again for the folks in the back- we can prevent many regressions before they even happen.
Because we can have template linters like eslint and ember-template-lint to help us statically analyze or template code. And these days, we even have it available to us via language servers in popular IDEs.
With these linters, we can analyze our code. We can customize what we analyze. We can even fix issues through our linting tools.
Why else should we use tools like this? Because it’s okay to not know everything. It’s okay to accept that there are things you don’t know- and depend on your tools to help you out. Linters can provide you with the support for some things you might not even know yet.
For example, Did you know that you don’t always need to add ALT text to images but that the attribute always needs to be there? If the image is purely presentational, the role of presentation or none should be added.
If the image is essential, then appropriate alt text should be provided. And A rule like “require-valid-alt-text” will help you out there. And not just you- but your whole team. No matter what their skill level. No matter where they are in the world.
Did you know that every input needs an associated label? There are ways to do this- with the associated label element, or with an aria-label, or even aria-labelledby if it’s a search. Again, there are rules that help catch this issue before you submit lines of code.
By actively using a linter, we benefit from actionable insights that we can use to make our work better – in the moment that we are doing the work. We can increase our own confidence.
But this isn’t the only way to get actionable insights- performance analysis tools can also give us these. Kris Selden at LinkedIn created a tool called TracerBench out of a desire to have more accurate performance analysis through macrobenchmarking. Developers can struggle to find and analyze performance regressions in a way that would allow them to make iterative changes within their local development environment, especially if working in an app that is scaled for global use. Macrobenchmarking is about holistically evaluating an app’s performance. Performance at load time needs to consider a lot of interdependent, concurrent things, and this is just the sort of benchmarking that TracerBench focuses on. It allows you to reliably test the performance implications of a change to your app by running a series of automated Chrome traces for each version, collecting a dataset of performance metrics. Not only does this provide low-variance performance data, it also introduces more statistical rigor in the benchmarking process. It encourages peer review by packaging a runnable benchmark. No more “it’s fast on my machine!”
And it’s not just our apps that can benefit from this- in the EmberJS framework, we have used TracerBench to ensure that new framework features don’t cause regressions in existing applications- which is important in Ember because we have a backwards-compatibility guarantee.
Proactively generating more elevated, quality code before you push code means that we can reduce the number of JIRA tickets. Which will give you more time for your next big idea. I think this is the best reason for using these kinds of tools- you’re giving your future self the gift of more time to spend on the next idea.
Challenge alert! Mia wants to know, do you know what will happen if you ran a linter on your codebase right today? Try it and see! Next time you’re in your code base, run it and see what kind of issues it reports. Audits will reveal these issues and more- why not take care of the ones we know about now? We’ve started working on ways to test the common failures, and that’s something that hasn’t existed yet. As we work out how to put these automated tests into place, every Ember developer will be armed with better decision-making support from the moment you start writing code. But we still have a long way to go.
Now, I know we’re focusing on performance today, but some of you have heard me to refer to accessibility as the final frontier of the web, and here’s why.
Intent matters. Accessible interfaces are ones that can be used in the way they were intended to be used. But, We still don’t have a great way to say “here’s the intent of this piece of code”. Until we can programmatically assign intent in our code, we will have gaps in our automated testing. Until we have had to really look at the full scope of the accessibility test automation problem we face today, we will not be willing to say “this is how you do it, and this is how you don’t.”
And this is what I mean about the need to shift left. Don’t wait for the audit - move linting and performance analysis into the development workflow. I genuinely believe that understanding the needs of users – especially users with assistive technology will not only show us the clear path forward for the web, but also increase our holistic understanding of what our code needs to look like in order to create the next generation of user experiences for every device.
Here’s the thing. To me, accessible code is performant code is valid, semantic codeand this kind of code has a higher degree of quality to it. An elevated level of craft. Whether you started writing code knowing about these kind of quality standards or not, it should be your eventual goal.
I want you to go home and try something. Set a meeting on your calendar or an alarm on your phone, something that allows you to set up a weekly check in. Take a little time for some self-reflection. Did you have a TIL moment this week? If you didn’t, figure out why. Challenge yourself to make this idea happen. Keeping the today I learned mindset is essential for success in our field.
Maybe you do this by reading a new book. Maybe you do this through daily challenge exercises to warm up in the morning. Maybe you do this by trying out some assistive tech on features as you build them. Maybe you do this by reading spec.
Maybe you do this by thinking about what spec doesn’t exist yet, but needs to. I asked someone once what the difference was between Java and JavaScript- and the best answer to this question was this: Java versions are Java’s way to become more spec-conformant JavaScript is still evolving and deciding what that specification should look like. This means that until the web as a platform is a lot more stable, we will be required to continually grow our knowledge and skills so we can contribute to specification that doesn’t yet exist but needs to.
I hope I’m not the one breaking this news to you, but our chosen career path requires passion, patience and persistence.
The thing is, Conference talks can be really inspiring! They call on us to imagine the future, show us the bleeding edge of tech, and inspire us to reach for excellence. But what happens when we go back to work the next day, and we’re faced with the reality of the codebase we work in? Figuring out how to turn that conference inspiration into reality can be challenging. Reality is usually a bummer. The great news is that we can influence that reality.
Accessibility is a journey.
Performance is also a journey.
Let’s take that journey together.
Thank you for the gift of your time. I hope to hear from you- feel free to send me a Tweet or DM me on the Ember.js Discord and let me know what you thought!