Principles of Empathetic Software Design

Jimmy Alamparambil
10 min readDec 10, 2021

Or how to win friends in the app development community

Motivation

A lot has been written about user centric design for software and UX, using principles such as “Be empathetic towards the user of your software” and “Use it yourself as the user would to find pain points.” There is a general adherence to this currently for products and applications that face the consumer. But what about software libraries, SDKs and other software components that are targeted for use by other developers?

As an application developer who is a customer of such software libraries, I have been disappointed at how little these principles are being applied to this aspect of software. Perhaps it’s the assumption that application developers must be very technically adept and can figure out obtuse SDKs as part of their tasks, or perhaps the task of producing these SDKs is hard enough to not warrant putting in more effort to make it user-friendly. In any case, while producing such SDKs and libraries I have taken note of some small things that can be done to improve things, and have decided to list some principles that can be applied to such software libraries, SDKs and components that might help to improve their utility and usage in the industry.

Some of these might be obvious, others might have people who disagree with them. More of these could be added to make the list more complete. More detail could be added for ways in which some of these could be achieved, as well as real world examples. I hope this list is a starting point for discussion.

Easy to use

It should be easy to start using the software, with everything being set up well for the most general use cases. This is usually the first step in inviting users into your technology, so if they find their first experience with it to be inscrutable, they will be discouraged and many will not ever come back to it again. If there are things that need to be configured, make them as automated or pre-configured as possible. It should cater to developers with little technical knowledge about your domain and yet allow them to use it without too much tinkering. Minimize the cognitive load being expended to incorporate your software in the application, as there are so many other components and systems that they need to take care of as well. It must also be easy to use for more advanced purposes, and that ties in with the principles of being easily configurable and customizable that we will see later.

Powerful

Your software needs to provide functionality that is non-trivial for the developer to create themselves. The harder it is for the developer to replicate what you have provided for them, the more likely they will be to use your software if it simplifies this task for them. You should be providing value by solving a sizable problem for them. Of course the solution should be elegant as well.

Interoperable

More likely than not, your software library or SDK may not be the only one being used in an application. There may be several other pieces of software being integrated. You should make your software play nice with other software that might be used together with yours by providing common protocols and integration hooks, or by simply playing nice in the context of the namespaces, frameworks and build systems being used. One of the biggest frustrations as an application developer is to get multiple SDKs and frameworks to work together seamlessly. In many cases developers do not have a choice of changing the components they already use, and that means that it would be hard for them to integrate your software if it did not work well with the set of SDKs they already had.

Open source

This is controversial for various reasons, but have your source code be as open as possible. Even if there are reasons to provide only binaries of some portions of your software, open your source for the rest of the components of the software. Clients invariably encounter a special case of the application they are developing which needs changes in your software to make it work for their situation. If there is an easy way to make the changes locally for their use case so that they can carry on with their work, they will be encouraged to use your software to achieve their goals. Ideally they can contribute their improvements back into the main development effort.

Cleanly architected

Provide a clean architecture for your software because it achieves two things: it is easier for developers to understand how your software works at a high level, and it is easy to maintain and alter for specific needs as development matures. In addition, you should use a “clean as you go“ mentality as you develop and improve the software. Clean architecture goes along with many of the principles here including modularity, layered abstraction, extendability, testability, data-driven and collaborative.

Iterative workflow

Your software components and its associated tools should allow for an iterative workflow during development. Developers tend to make small incremental changes and see what happens to the application with those changes. If the turnaround time from making changes to seeing the changes in the application is too long, the development effort is impeded. So provide the right tools or framework enhancements to be able to carry out this workflow efficiently.

Layered abstractions

Your clients will have varied levels of technical knowledge and requirements to customize, so your software should provide abstractions for these different levels of customer. A low-level abstraction might be an API that does something basic but at high performance. A slightly higher level abstraction might be an API that uses the lower level APIs to implement a feature or functionality more concisely. A level above that might be some data driven component made out of the APIs that can be configured easily to use a feature. A level above that might be a collection of these components gathered to solve a specific use case. And so on.

Public APIs

Do not provide any internal or hidden APIs in your software — everything that can be utilized by apps must use a public API. This helps to make the public API more robust and prevent any undocumented behavior within the software component. As a corollary, each of the modules within your software should only interact with each other using the public API as well.

Data driven

Any configuration or feature parameter should not be specified in code, but rather have a file or memory block that can load up the values needed so that customization of features can be done without altering the code. It also makes the software more usable by non-technical people who are able to vary the parameters for their use cases easily.

Tools included

Provide tools that allow the developer to make changes to the parameters and configurations of your software. Other tools should help to improve the visualization of the data and state in your software components or to debug the operations that your software is carrying out. Tools are needed to automate various parts of your workflow, make it more iterative and help validate various parts of your pipeline. Tools should integrate well with any engines or frameworks being used.

Modular

Make your software modular so that each module only carries out one main responsibility (SRP). In addition if there is common functionality that is shared among multiple modules, pull that out into its own module so that you’re not repeating yourself (DRY). Keep the modules decoupled with well defined interfaces among them and between them and the application. All this makes it easy to take parts of your software apart and put them together in different ways, which is something your developers will eventually want to do.

Customizable

You will never be able to predict all the use cases that your software component will be used for, so provide a way for developers to customize the functionality easily so that it will be able to solve as many use cases as possible. This is associated with the configurable and extendable principles, but also with making it easy for developing customizations in code if necessary.

Extendable

Developers might want to extend the functionality of your software beyond the feature set that was originally shipped with the project. Providing a mechanism to create extensions to your components, and even encouraging the writing of such extensions will make the software rich in organic feature additions and improvements. The added or improved functionality could eventually find its way back into the main software when enough people need it for their work. This principle can help developers achieve their customized use cases more efficiently by leveraging extensions made by themselves or the community.

Configurable

It’s hard to create software that is “one size fits all”, so you should provide a way to easily configure your software to handle different use cases. The configuration should be easily editable via data driven parameters and well documented so that developers can set up their systems for their situation quickly. If there is an easy way to prove out the basic setup can work for their use case, developers will be more willing to put in the work to implement the rest of the components needed.

Testable

Ideally use test driven development, but otherwise make sure you have tests for your major functionality so that any regression of features will be caught quickly. Continuous integration and testing in your development cycle can help minimize hiccups in the progress of development. Developers will not appreciate having a bug being introduced in functionality that they were relying on when they upgrade to the latest version of your software.

Upgradable

As new innovations, features and improvements are made to the software, the APIs and data used might change. When developers upgrade to the next version of the API and data, your software should still work as expected. For this to happen, you should either guarantee backwards compatibility or provide an upgrade migration process to allow code and data to be upgraded seamlessly. This helps maintain confidence in your software as it matures and scales to more use cases. Developers will be confident enough to upgrade to the latest version.

Collaborative

For empathy towards developers, we certainly need to be collaborative with them to provide something that works well for them. But we also need to be collaborative internally across module teams and within project teams so that clients will have a unified coherent experience when working with our software. This might be one of the hardest principles to follow: you need to have a common holistic vision, and good communication between the collaborating teams.

Manages dependencies well

Provide default integration of required external components. Provide a way to manage the dependencies of your software, and keep the dependencies up to date when your software needs to be upgraded. The mechanism to achieve this should be automated and have a low impact on developers using your software.

Community focused

Using the collaborative principle, you should create and foster a community of developers that will help solve each other’s problems, and populate a knowledge base of topics that can answer most questions about this software component. This community can keep interest focused on the software component, contribute changes back for improvement and most importantly advocate for your software with people outside of the community who are not aware of the pros and cons. Answer as many questions as possible in public forums (omitting proprietary information) so that everyone can learn from issues and FAQ. Be actively involved in problem solving for developers in forums. Take back some of those learnings to incorporate in your documentation, and possibly make improvements to your software.

Feedback driven

In keeping with the community focused principle, you should keep your finger on the pulse of your developer community and record and discuss the feedback that is coming from them. This feedback is usually raw, and may need some further analysis to truly understand it. But once assessed properly, this feedback is useful in driving a part of the development process of the software to make improvements to the developer experience.

Showcase use cases

Once your software is being used by developers, you should provide showcases for people who use your software in innovative ways or to achieve something interesting (with the permission of the authors of course). This works in multiple ways, but mostly as a demonstration to others of what can be achieved with this software, and to give kudos to the authors on their skill and dedication used to build this showcase. The authors become instant celebrities in the community and become somewhat of expert advisors to others. Your software gets more traction with others in the community for what it can build.

Marketplace

As part of the involved community, developers would like to help their colleagues by providing extensions, tools, samples and templates that can help them complete their projects. If there does not exist an ecosystem to do this already, you should make it easy for people to be able to distribute their related assets to their colleagues, either for free or for commercial benefit. This encourages the growth of developers who are familiar with your software and are going to help others get familiar as well.

Well Documented

Document your software well, as it will help developers start up their application development with the resources needed to plan their project. It will also help them understand the relationship between the different components of your software and the APIs between them. The more they understand, the easier it will become for them to use your software. You should strongly consider hiring a technical writing team to enhance the documentation process as engineers can then focus more on the development effort and the technical writing team can help formulate the best way to convey the information to developers.

Provides Samples and Demos

Create a sample for each of the major features within your software, showing in detail how that specific feature might work in a real application. Combine some features together to show a demo of a simple application. Make demos as close to real use cases as possible. If possible, hire people outside your team so that they think of good ways to leverage your software to achieve their goals. Integrate other SDKs or libraries into your demo to show how well you are interoperable.

Summary

As mentioned before, this is mainly meant to start a discussion on this topic and does not claim to be a complete coverage of the subject. But hopefully, we can start being more empathetic of the development efforts of application developer folks who have to deal with a multitude of software libraries, components and SDKs in order to ship their applications. We can start using some of these principles when authoring SDKs and software libraries to improve the developer experience of creating applications.

Please provide any feedback you might have about solutions that have worked for your teams, about problems with any item listed above or about other principles that we may not have covered here.

--

--

Jimmy Alamparambil

Spatial Computing Technology Leader evolved from GameDev. Formerly @adobe, @magicleap, @unity, @ubisoft, @ea, etc.