You can become a serverless blackbelt. Enrol to my 4-week online workshop Production-Ready Serverless and gain hands-on experience building something from scratch using serverless technologies. At the end of the workshop, you should have a broader view of the challenges you will face as your serverless architecture matures and expands. You should also have a firm grasp on when serverless is a good fit for your system as well as common pitfalls you need to avoid. Sign up now and get 15% discount with the code yanprs15!
This excellent book by Steve Krug was a real eye opener when I chanced upon it a few years ago.
I’m not a UI/UX designer by trade or by training, and as a backend developer my appreciation for UI/UX has very little outlet in my day-to-day job either. But still I find plenty of symmetries between UI/UX design and API/library design.
Don’t Make Me Think
When it comes to API design, I always cast my mind back to this talk by Joshua Bloch.
In this talk, Joshua outlined a set of characteristics of a good API:
- easy to learn
- easy to use, even without documentation
- hard to misuse
- easy to read and maintain code that uses it
- sufficiently powerful to satisfy requirements
- easy to evolve
- appropriate to audience
Reading between the lines, the first 4 points essentially boil down to a simple rule – that we should appeal to human intuition, and closely resembles the usability study concept of affordance.
An affordance is a quality of an object, or an environment, which allows an individual to perform an action. For example, a knob affords twisting, and perhaps pushing, whilst a cord affords pulling.
or in other words, the easiest and most obvious way to do something should also be the right way to do it.
Just as a great UI guides you towards your goal – be it buying a flight ticket or finding a hotel – a great API design should also guide you towards meeting your data needs.
However, just as in the real world, Software is full of failure examples…
and some advices in Software are just as applicable in UX too.
Explicit is better than implicit.
Flat is better than nested.
– Zen of Python
Just as UX experts can conduct UX studies by watching users interact with a UI and tracking their eye movements, etc. Perhaps as an industry, we should also conduct usability studies on our API offerings? We can measure how quickly developers are able to successfully perform a set of tasks that require them to interact with the API in various ways. For instance, how many attempts it takes them to correctly retrieve the data they’re after.
Type Directed Development
In a statically typed language, good use of types goes a long way towards expressing and communicating the assumptions and limitations we as API designers have made. Many functional languages such as F# are very well suited in this regard thanks to their power type systems.
For inspirations on what’s possible and how to apply them in practice, see the following talks.
Scott Wlaschin on DDD with the F# type system
Edwin Brady – State, Side-effects and Communication in Idris
Edwin Brady – Verifying Stateful and Side-Effecting programs using Dependent Types
Joshua also talked at length on a number of principles you should follow to help you design a good API. Whilst the talk is based on Java, many of these principles would be familiar to any functional programmer too.
- API should do one thing and do it well
- API should be as small as possible but no smaller
- Implementation should not impact API
- Minimize accessibility of everything, maximize info hiding
- Minimize mutability
- Subclass only where it makes sense
- Design and document for inheritance or else prohibit it
- Don’t violate the principle of least astonishment
- Fail fast – report error ASAP after they occur
- Use appropriate parameter and return types
- use most specific possible input parameter type
- don’t use strings if a better type exists
- Use consistent parameter ordering across methods
- Avoid long parameter lists
- Avoid return values that demand exceptional processing
- zero-length array, not null
Many others have said before that good OO is very similar to FP, but the problem remains that mainstream OO languages such as C# and Java doesn’t do a good job in guiding you towards writing good OO.
As software developers, we’ve all been taught that maintainability is important but so often I find it difficult to think about maintainability in clear, unambiguous ways since complexity itself is in the eye of the beholder. We have invented many tools and metrics to help us measure complexity, but none gives us a complete and accurate view of it.
Furthermore, software engineering is not only an engineering activity (in fact, Alan Kay argued that our standards and practices fall way short of those expected of an engineering discipline) but also a social activity.
Organizations which design systems … are constrained to produce designs which are copies of the communication structures of these organizations
– M. Conway
Adam Tornhill also demonstrated a number of techniques that use our commit histories to unveil hidden complexities that arise from the way people work together.
If you have dependency between software components developed by different people, then you essentially have dependency on people. Just as the communication between software components is a source of complexity, so too is the communication between people responsible for these software components.
Complexities can creep into your API in any number of ways, e.g.
- complexities with the underlying domain leaking through
- impedance mismatch between the API’s designed use case and users’ actual needs
Having worked with no less than 25 of AWS’s APIs, we have encountered a number of such complexities. And since we are not in control of the APIs themselves, so we do the best we could to manage and mitigate these complexities with the use of DSLs.
Take a look at the following slides on some of these complexities and the approaches we took.
- Joshua Bloch – How to design a good API and why it matters
- Alan Kay – Programming and Scaling
- Takeaways from Adam Tornhill’s Code as a Crime Scene
- Sandro Mancuso – Functional is cool, but do we know OO?
- Seven ineffective coding habits many F# developers don’t have
Hi, I’m Yan. I’m an AWS Serverless Hero and I help companies go faster for less by adopting serverless technologies successfully.
Are you struggling with serverless or need guidance on best practices? Do you want someone to review your architecture and help you avoid costly mistakes down the line? Whatever the case, I’m here to help.
Skill up your serverless game with this hands-on workshop.
My 4-week Production-Ready Serverless online workshop is back!
This course takes you through building a production-ready serverless web application from testing, deployment, security, all the way through to observability. The motivation for this course is to give you hands-on experience building something with serverless technologies while giving you a broader view of the challenges you will face as the architecture matures and expands.
We will start at the basics and give you a firm introduction to Lambda and all the relevant concepts and service features (including the latest announcements in 2020). And then gradually ramping up and cover a wide array of topics such as API security, testing strategies, CI/CD, secret management, and operational best practices for monitoring and troubleshooting.
If you enrol now you can also get 15% OFF with the promo code “yanprs15”.
Check out my new podcast Real-World Serverless where I talk with engineers who are building amazing things with serverless technologies and discuss the real-world use cases and challenges they face. If you’re interested in what people are actually doing with serverless and what it’s really like to be working with serverless day-to-day, then this is the podcast for you.
Check out my new course, Learn you some Lambda best practice for great good! In this course, you will learn best practices for working with AWS Lambda in terms of performance, cost, security, scalability, resilience and observability. We will also cover latest features from re:Invent 2019 such as Provisioned Concurrency and Lambda Destinations. Enrol now and start learning!
Check out my video course, Complete Guide to AWS Step Functions. In this course, we’ll cover everything you need to know to use AWS Step Functions service effectively. There is something for everyone from beginners to more advanced users looking for design patterns and best practices. Enrol now and start learning!
Here is a complete list of all my posts on serverless and AWS Lambda. In the meantime, here are a few of my most popular blog posts.
- All you need to know about caching for serverless applications
- Lambda optimization tip – enable HTTP keep-alive
- You are wrong about serverless and vendor lock-in
- You are thinking about serverless costs all wrong
- Just how expensive is the full AWS SDK?
- Check-list for going live with API Gateway and Lambda
- How to choose the right API Gateway auth method
- CloudFormation protip: use !Sub instead of !Join
- AWS Lambda – should you have few monolithic functions or many single-purposed functions?
- Guys, we’re doing pagination wrong
- Top 10 Serverless framework best practices
- How to break the “senior engineer” career ceiling
- My advice to junior developers