>> Hello, everyone, welcome back. Up next, we have the wonderful Leigh Brenecki, who attendees
of past PyCons may recognize. Leigh is from Melbourne and Adelaide. She was the conference
director of PyCon AU. She's passionate about API design, cycling and snacks. Everyone, we will
be taking questions, if there is time at the end. So, remember the handy, little questions tab.
And remember that there is a little bit of a delay from when we're talking to when you hear us so
make sure you get in your questions before Leigh finishes up the end of her talk.
All right. Take it away, Leigh. LEIGH BRENECKI: Thanks, Betsy. So,
before we begin, I want to acknowledge that I'm presenting this in the [Indiscernible]. I also
want to highlight there's a lot of information and a small amount of time, here, between my time
and on screen text. The URL on the screen has the link. You need the "www" at the beginning.
So, this is a talk about design and often when we think about design, we think about websites,
arm chairs, calculators and radios. We think of color and shape and materials and texture. This is
also a talk about APIs, the way that one piece of software works. As for color and shape and so on,
they don't apply to our API, which are expressed in plain text. Design doesn't really have much to
offer us. But they're just the tools of design. Design is about making things for people to use.
I said that APIs are for one part of the computer. APIs are for people to interact with software by
creating more software. Dieter Rams active from the 60s to 80s, who made far more than razors,
his armchairs and calculators were an inspiration and it's not hard to come
by an analysis for his 10 principles of design. They are a set of aphorisms for furniture,
design is more than just furniture and stuff. We're going to explore five different ideas
about API and software design and how they relate to the ten principles of good design.
Something you can't touch and sit on, but developers interact with every day.
So, I've got problems. Rams' first principles is design is iterative. Rust,
Swift is more expressive than Java, which was popular. New language features like pattern
matching for bug matching. But to an even greater extent and to give you a level of expressiveness
that can approach languages like Python. What's interesting is they're innovative.
When introduced Rust to the world, the second sentence was just that, nothing new.
Rust has changed a lot. But what makes Rust interesting are features not invented from
[Indiscernible]. Many other system languages are better than newer ones and Rust draws from
languages of the 80s and 90s. Programming language live in two different worlds and
Rust innovates by bringing it to a more mainstream industry context.
If you explore with Rust our TypeScript is built, you'll see the real source of the innovation,
people are figuring out how to make it easy and understand to use, make it accessible
and to communicate them so they can be best used and best taken advantage of.
Rams said it developed in tandem with innovative technology. That's what's happening here. It was
developed in all those research languages and Rust innovation is largely designed,
language and API design, making innovative technology useful. Rams' talks about it being
[Indiscernible] it can feel like there's a tension between that and innovation. He compares against
fashionable design. Of course, the JavaScript ecosystem seems like everyone's go to cycle.
The tools du jour to get changed. If you step back and look at the web itself, that's a low lasting
design. Here I am, I have a career building things for it and I'm here talking about them.
So what is it that makes the web long lasting? It's not a piece of software. Nobody sets down
and opens up Worldwide Web anymore. HTTP, XML wouldn't have [Indiscernible] they
need to evolve. The web is lucky on this one. Some time ago, Internet Explorer 6 had won the war
and Firefox came along. It had tabs. It let web developers do more by pushing the standards
forward. It had the backing of Google, IE wasn't [Indiscernible] Google's financial support and ad
space on the most visited page on the entire web. We've lean less lucky with chat. [Indiscernible]
has been stagnant for a while. Proprietary have been adding emoji reactions. If you posted a non
ASCII text, you'd get yelled out because other people's client didn't support Unicode.
There's talk on the social and political. Free software is largely dead and [Indiscernible] is
why. It is making deeply disturbing jokes and not understanding why they're put off by the deeply
disturbing jokes. You can exchange for a shiny box that the audio and WiFi worked on day one.
On that other side of the fence, we have Slack, which has been supplanted outside of the business
by Discord. So, we can't talk about software being long lasting without acknowledging
there's market working against that very thing and our substantial paychecks come from that.
There is kind of hope, though. My house is illuminated [Indiscernible] for disposable
hardware that becomes useful when a vendor releases a new model. I use Lifx because
they can be used by a documented API. And it's a cottage industry that work with that API.
It's hardly open standards and it's something. So, there's two keys, here, to making long
lasting technology. One is continuing to evolve and progress and innovate.
Next, I want to talk about learnability, Rams' words about a good design seem like they were
written with code in mind. Such a common goal, self documenting coders [Indiscernible] to say
ironically is to tempt fate. Learnability is a critical part of what makes an API useful.
We know how it works because we're writing it. We can't [Indiscernible] into our users' heads.
If I'm using a library to use Excel files, I don't want to deal with the intricacies.
Penetration testing and [Indiscernible] learnability is one of the key things that makes
a API useful. APIs are hard to navigate, offering too much or not enough or not being set up in a
way that makes sense. This is in documentation. What anybody tells you about documentation,
tutorials, how to guides, discussions. The most important, for your API's [Indiscernible].
The talk is well worth it. The critical parts are about providing a sense of achievement,
avoiding abstractions and giving the minimum necessary explanation.
We can give our users less to learn. When I was doing frontend work, I was doing ES Modules and
doing things using the tools and conventions. Then I use a Google library. They're in their
own world of tooling. You have to load and give it a callback and [Indiscernible] API global scope.
I can't use the import key with the Google APIs, but I can't use my pre existing knowledge.
I have to figure out how to get this weird, Google tools. Their docs are like that,
too. Details you need to know in order to make the API, hidden in the foot note. Details you might
just know if you worked at Google, but this is a public API that's literally made for non Googlers.
When we start talking about things like that, it often sounds like we're talking about aesthetics.
Code isn't particularly visual, it's just plain text. There's not a lot of flexibility or control,
but we have a sense of aesthetics. If you go to the Powerhouse Museum in Sydney,
it has objects designed and you can see the resemblance, the shared values and priorities.
You can also see a really interesting contrast. You can see this refined minimalist, everything
is precise, there's whites and grays and silvers. Very German. Typewriters and calculators. Mostly
designed by [Indiscernible]. I absolutely adored them. They had lots of curved shapes around edges,
colors and loud and fun and very Italian. The Germans creating a [Indiscernible] and the user
of a calculator. Across communities, we have different sets of shared ideas of what good code
looks like. Good design is aesthetic and writing [Indiscernible] that fit in with the value system.
In Python we talk about this so much, Pythonic, which includes underscores and goes deeper.
In this talk, fabulous blocks and where to hide them, Christopher Neugebauer talks about
anonymous code blocks that Ruby has and custom syntax for particular use cases, like context
managers, async and await. My television is about to turn itself off so I need to find my television
remote which is a thing I was really hoping wouldn't happen. But there we go, I fixed it.
[Laughter]. These things are Pythonic,
not like TVs and so is using them. If you have a resource that opens and closes, make it a context
manager. If you have something that's conceptually an ordered collection, make it a [Indiscernible]
surroundings with the norms of the ecosystems. If it can use your API, they don't have to remember
extra details. They might try applying that and go, sweet, that works. This is hard to do
if you're not immersed in that ecosystem. It might use expectations in subtle ways,
like a staircase that has fewer stairs than you're expecting. You need to be a part of it,
interact with it. Every ecosystem, there's these shared values and norms and understanding
them is key to understanding how the users of your APIs are going to feel when they use it.
The next thing that I want to talk about is containing complexity. This is the longest
section of this talk because computers are incredibly complex. And, at one end, we've
got CPU operations that happen quickly and those are composed into tasks. The middle is the bulk
of our job as technologists. It can be really hard to builds something that's unobtrusive and let our
users do whatever they set out to do. I used to do a lot of work with content management systems and
all those platforms [Indiscernible] some of them set out to be simple. They followed a process
of building 10% of features that 90% of users want. They're perfect, so long as you're within
that 90%. If you want to make something slightly different, you're out of luck.
They've got [Indiscernible] tables and a checkbox for everything. They feel enterprise y.
There's a Django based CMS called Wagtail. Most of the other CMSs, they gave you something out
of the box. Wagtail's not like that. It assumes you know Python and Django
and makes you do coding to set up your page types. A few different places you can fit things. Or you
can make your own when you needed to. The others were products with an API. But Wagtail was an API.
You get all the bits you need to assemble a website with comprehensive instructions.
The other critical thing about Wagtail, there's a few places you can snap in components
and the interfaces are expected to provide a minimal and well documents.
So, it is with APIs designed around this. By using this, also using restraints with
a number of moving parts, you can make an API to enable your users to build what they want.
This is one approach we can take to contain the complexity of our systems. One of many ways and
make them fit in your brain. Is it possible to go too far? I don't have a black and white answers,
but there are definitely abstractions. Rams talk about trying to manipulate
the users that trick you into accept all or [Indiscernible] subscription boxes that are pre
ticked. Without that element of intent, but can lead users down the [Indiscernible] APIs that go
further than simplification. If they try to make a facade, I'm going to talk about ORMs, Object
Relational Mappers. [Indiscernible] as soon as I said good design is honest, the first thing that
came to his mind. They are a popular abstraction layer. He described their role as constructively
lying to you. When you use an ORM, you have your data accessibility as if it's a graph of objects
and you can jump between objects and walk around in an ad hoc way. But that's not really the case.
In reality, your data accessibility is sort of structured like that, as [Indiscernible] within
a relationships with foreign keys linking them. The way you create a relationship database
is wildly different. When you create a relational database, it has rows and columns
and unless you're using SQLite, you are talking over the network. ORMs have a lot to do behind had
scenes, they transfer to SQL and get it split and out and link them together, constructing
this graph they present to you as they go. They're laying down track ahead of the train, like Gromit,
trying to make it seem like it was there all along. And they work. Everything's fine.
More complex queries are not harder to write in ORM than SQL. You have to understand the SQL
you want to generate and what the characteristics are and the ORM to produce the SQL you want.
The ORM lets you do complex queries. Then, once you sent out your query,
there's the illusion of the data accessibility being right there.
This is a trap that's so common, so easy to fall into the, N+1 problem. What you can't see, author
isn't really there yet. When you access the author, the ORM goes off and finds
an entirely new request, constructs an author object and pretends it was there all the time.
You're hitting the network every iteration, that's going to slow things down.
You have this API that's lying to you, to try to make it simpler. You have to break the illusion.
You have to know about a lie. Know about the circumstances when it's lying and code around it.
This is one of those headaches for people building the library. Andrew Godwin has spent
the last few years trying to make Django Async. This might hit the network at surprising time
through attribute access, doesn't really work with Async. And this talk, Andrew revealed is
you have to use select related. The N+1 doesn't work in async mode. We need to have caution.
Are we simplifying or constructing a facade? Django's ORM is very, very good. To implement
things the way that Django has decided to do requires doing this deal with the devil.
Django is pretty easy to provide custom sequence. And that's a good lesson to take away,
too. It may be constructing a facade, but at least it's thorough about it. How's that for a segue?
The most thoroughly designed software is [Indiscernible] through every path you might
take as a user. [Indiscernible] focus on the most common use cases or expected outcomes. And
similarly, it's easy to end up designing an API with a lovely thought through happy path,
but not even think about errors, straight from the library you're depending on and the library and
framework. The design of the [Indiscernible] is left the chance and the inner complexity links out
to users. A thorough API will not only handle it as well, but for each of the errors that happen,
what circumstance it might happen in and how to handle them. It will have good error messages.
Rust is really good at this. When you get a compile time error in Rust, there's a lovely,
pretty clear error message. It tells you where it found the error and it gives you a hint as to what
you might have done wrong. Sometimes there's enough information to know what you did wrong.
React has an interesting approach, too. When you use React on your website, every visitor has to
download all of React. So, they don't have big, long, error messages, they have error codes. This
is one of the cases where it makes sense to use error codes other than, say, microcontrollers.
In React, it is embedded in the URL and you get a clickable link and when you visit that link,
that's where you'll get all the detail. You get a description of what the error means,
some common courses and links to documentation to learn more and this is really neat approach
that I'd really love to see in both web frontend. Yesterday's education track talked
about Python traces, which touches on the things I've talked about here.
The other case where it really shows an API is well thought through, when it
has polished out the caller cases and you can polish out the corner cases in your own work.
Accessibility features are [Indiscernible] collectively, a decent amount of us use one
or the other. And more importantly, rarely used by develops [Indiscernible] and your API can make
it easier for your users to build accessible software, more of them will actually do that,
which is a win for their users and theirs. Complexity, the best we can do is contain and
decompartmentalize it. And thoroughly designing our edge cases can contain that and reign it in.
[Away from mic] sip of water. [Laughter].
So, we've talked about three key things, protocols and protocols and evolution,
learnability, containing complexity and we've touched on eight of Rams' 10 principles. I want
to talk about the one I left out, good design is environmentally friendly. It's as important
as ever. But unfortunately, I couldn't find a way to do it justice so I'm going to recommend
[Indiscernible] from 2019. It's linked in the resources and a really well put together topic.
I think it's possibly the most important. Good design is as little design as possible.
Definitely not as little work, but an end result that's minimal and focused.
It translates really well to API. It translates to me as really important,
something I think about a lot when I'm designing APIs. Cognitive overhead. Nothing is infinite.
The machines that run our software have limited resources. We optimize how much we use. We might
try to write code that runs faster, using less RAM or uses less battery and we use different tricks.
If we can avoid doing something entirely, we will. We look for opportunities to use something
for more than one resource. Maybe there's a component that might not be needed at all, or
maybe there's 20 eventually. We might pre compute we might know or think we might need later.
Nothing is infinite. And that applies to developers, too. There's a limited amount
of things we can remember and there's an even more limited amount of ideas. There's a limited number
of hours in the day and time. It might seem kind of [Indiscernible] to say the human brain is just
like a computer. When you think about API design, optimizing your API design is optimizing your code
to run faster. The solutions sound similar in an abstract sense and you end up using the creative
problem solving. You might try to use similar concepts. You might design your API to use certain
concepts in certain places and they only have to certain places. You might use concepts or patents,
like languages and frameworks. I didn't talk about a thing that
I'm saying so we'll skip that. All of the ideas we've talked about [Indiscernible] protocols,
evolution, long lasting technology create a shared language, creates that shared aesthetic.
Learnability and understandability go hand in hand, being unobtrusive and thorough.
How we make our designs as little design as possible, it feels weird talking about APIs
being for people. We have this divide in how we think about people. We have users, commoners who
need help and developers, the smarter, superior class. It feels weird because of contempt culture.
And so we think we don't need design. We think about the people that use our API and think,
they're developers, they know computers, they don't need help. They already know this.
Or perhaps we think about code is something we're building for the computer.
Unless you're fiddling with binaries, there's layers of abstraction between what you write.
Computers are dumb machines, they don't need abstractions, the abstractions are for humans.
The code we write is mostly for humans. [Indiscernible] I may be able to take one
or two questions if I step out of my graphic. I'm not going to take questions even if they are
[Indiscernible] questions. Comments, feedback, want to say hi, I'll be in Venueless. There's
contact information on the screen, as well. I want to thank [Indiscernible] and Benno Rice. So, if we
have some questions, I would love to hear them. >> Hi. Okay. So, we have some questions.
Half of them are about your presenting setup. So, I while they're very good questions,
and I want to know the answers, I'm going to leave those aside. Everybody is
absorbing all of that and coming up with their questions and you have a moment to breathe, Leigh.
Sorry. I just want to take a moment for a round of applause for the stenographer,
well done. Whichever of the stenographers is doing the live captioning for this. You're a champion.
Great work. [Laughter].
Okay. So, we have some questions and we have one minute.
LEIGH BRENECKI: Lightning round. >> How do you manage principles and
prioritize something over another? LEIGH BRENECKI:
It depends. It's one of those things where you sort of got to think about I guess
it depends on the specifics of what trade offs you're making, who your audience is and stuff
like that. I think it's one of those situations where the better you have an understanding of
who's going to be user your APIs, you know the trade offs. I don't think there's a
one size fits all answer to that one. >> All right. And we are at time,
so there is another excellent question there, that I will copy across to the chat, if that's
all right with you, Leigh. So, we will move this over to the text chat, the Curlyboi Theatre chat,
in the channels part of the menu, on the left I have no idea if I'm getting off to the left
of your Venueless. Thank you again, Leigh. And we now have a little bit of a break. We'll be back
here in 15 minutes, at noon, for our next talk. LEIGH BRENECKI: All right. Thanks, everyone. Bye.