10 Design Principles for Distributed Blockchain Apps
Blockchain technology is a disruptive, transformative approach to the way we manage data. It promises to radically change how we carry out tasks that handle sensitive information in shared environments. Critical operations on sensitive data historically required a strong central authority to convince data owners to trust the environment enough to allow it to manage their data.
One of the more difficult obstacles that every blockchain dApp must overcome is building trust. Users have to trust that the software running on the blockchain includes solid measures to provide security and protect privacy before they’ll supply sensitive personal and business data.
You can go a long way toward building this trust by adhering to several basic design guidelines. If you follow the ten design goals for blockchain applications that you find here, you’ll help encourage your users to trust your application enough to use it and rely on it.
Design blockchain apps for trust
One of the primary reasons most organizations move toward blockchain solutions is its capability to share data among nodes that do not trust one another. If you think about it, that really sets a high bar for dApp developers. To develop a successful dApp, you have to convince your users to trust your software with their data as you send it to a large number of other nodes that you don’t trust (and they don’t trust, either).
Trust is normally (but not always) transitive. (Yes, you’re headed back to math class. If A = B, and B = C, then A = C. You’re welcome.) This is the most common way we, as humans, deal with trust.
If you trust Mary, and Joe trusts you, then Joe is probably fine with trusting Mary. Let’s assume you’re a food critic. Joe trusts that you recommend good food. If you post that you really like Mary’s peach pie, then Joe will be more likely to try her peach pie since Joe trusts your taste in food. But that doesn’t track with a trustless environment. In the case of blockchain dApps, your users trust you, but you don’t trust others in your own blockchain network.
Your first design goal is a high-level objective that you have to keep as a top-of-mind motivator for all decisions. Many of the subsequent design goals support this one: Design your dApps for trust. That goal means you want to consider what your users wan, and what makes them feel that they can trust your dApp.
Users have to know that you’ll take care of their data. Your dApp should not hide anything and should make it easy to check up on what’s happening. It should clearly communicate good and bad information and provide an overall sense of well-being. Although that’s a tall order for software, it’s necessary to build trust.
The most important aspect of designing for trust is understanding who your users are and what makes them feel comfortable. In short, know your users. Know what they want and how you can convince them that you aren’t going to waste their time or take advantage of their trust in you.
Enforce consistency in blockchain apps
One of the easiest ways to avoid confusion is to limit the options and conflicting experiences in your dApps. Microsoft learned long ago the power in consistency. They developed standards for how to interact with users, and explored and defined every aspect of creating a user interface. That’s why Microsoft applications feel similar to one another.
If you’ve used one Microsoft application, you’ll recognize at least the general user interface in other Microsoft applications. (And if you’ve used Microsoft products for a while, you’ll remember the huge disruption Microsoft caused when they converted to a tile-based user interface — largely because everyone was so comfortable with the legacy Microsoft interface.)
For example, if you want to find the current version of a Windows program you’re running, you can almost always click or tap Help, then click or tap the About menu item on the Help menu.
The image below shows the About menu item in VS Code. The About menu item exists in pretty much every Windows application and shows basic information, including the version number, of the program you’re running. That simple example of user interface consistency makes it easy for anyone to find application information without having to hunt for it.
The following image shows the About dialog box in VS Code. You’ll find release information for most Windows applications by clicking or tapping Help → About. That’s the power of consistency.
Your dApps should define clear standards for every user interaction. When you ask your users to provide input, do it in the same way throughout your dApp. When a user enters a product ID in multiple places, the input field should look the same in each location. Use the same colors, fonts, and input method to give your dApp a consistent look and feel.
Another area in which you’ll find consistency in GUI apps is keyboard shortcuts. You can almost always use Ctrl-C to copy highlighted text and Ctrl-V to paste that text in a new location. Consistent keyboard shortcuts make it even easier to learn and use new software.
In the same way, standardize all output. Error messages and alerts are prime areas for standardization. When possible, use common input and output layers, so that all input and output uses the same set of functions. The entire dApp will look more consistent.
You’re trying to encourage your users to keep using your dApp. A dApp that presents a consistent user interface is one the builds trust. Consistency also makes it easier for your users to learn how to use your software, and an application that is easy to learn is one that users will likely prefer and accept.
Remove doubt from blockchain apps with transparency
One of the reasons why users distrust an application is that they don’t really understand it. The users provide their data but aren’t sure what happens after that. They don’t know where their data goes, and whether it’s even still somewhere in the system. This feeling of putting data into a black box can be even stronger with blockchain dApps.
As blockchain technology becomes more popular, overall awareness of its features is increasing. That means many of your users will know that your dApp sends their data to many other computers, potentially all over the world. One of the hurdles you will have to overcome is convincing your users that you are protecting their sensitive data.
Clearly communicate what data your dApp needs, why it needs each type of data, and what you do with it. You won’t need to convey this information every time you prompt for data, but it should be available the first time you interact with a new user and on demand thereafter.
You should also make it easy for users to see what they have done (and what your dApp has done with their data.) Providing transparency at each step gives users a sense of confidence.
Make it easy for your users to drill down and get verification of actions. This level of transparency gives users the confidence that your dApp is doing what it claims to do, and can reduce the concern that your dApp is hiding something. Depending on the level of user concern and your own design guidelines, you can build transparency into each workflow or into on demand functions to allow power users to drill down at will.
Provide feedback, guidance, and setting expectations for your blockchain apps
The next design goal you need for you blockchain app is providing feedback and guidance and setting expectations. This goal is a logical extension of transparency. Whereas transparency makes transaction and workflow details readily available to users, feedback, guidance, and expectation setting puts transparency into the normal workflow. Instead of just allowing users to see what happened, you should present them with informative feedback at every significant workflow step.
For example, if you are a manufacturer and have just transferred the ownership of a new tractor to a shipper, your new supply chain dApp may give you a message “You just transferred tractor with serial number ABC-12345 to Unified Shipping — Transaction number 456778.” Of course, you’d probably get more details for a capital item transfer, but you get the idea. The dApp provided feedback that essentially says “Hey, good job. Here’s what you did.” Informative feedback is the first step in convincing users to trust your dApp. The feedback gives them the assurance that they’re using the software correctly.
You can extend the feedback example to inform users of the next step as well. In the tractor example, your feedback message could also include a “Do you want to release the title now?” message with the option to click or tap a button to go to the next step. End-of-task prompts like this help to ensure that users understand the proper workflow and give them the impression that the software is helping them do their jobs correctly. When software makes users more effective, it goes a long way toward building trust. Everyone loves software that makes them look good!
Handle mistakes in your blockchain app with class
Face it, errors happen. And sometimes those errors are big ones. Hopefully you found all the big errors in your software during testing. (You did test exhaustively, right?) If you did, most of the errors you encounter in production will be user errors.
When you handle user errors, try to avoid any notifications that subtly say “You messed up!” Focus on resolving the situation, not placing blame.
You probably remember using your first GPS device in a car. In the early days of GPS, if you deviated from the suggested route, you heard a fairly stern “Rerouting” message. The voice might as well have said “You’re not going where I told you. Hang on, I’ll tell you how to get back to what I told you in the first place.” Error messages should inform users as to what has happened but focus on what to do next. Yes, the GPS did that, but it was generally after a subtle scolding. Don’t scold your users.
On the other hand, don’t spend too much time focusing on errors. Overly verbose error messages can be confusing and take too long to read. Get to the point. Always design error handling from the user perspective. Give users everything they need to respond quickly and decisively to errors, and nothing more.
Error messages help end users understand what is happening, and also help support personnel when they’re troubleshooting. Design your error messaging system so that it provides necessary user messages as well as more verbose messages on demand for troubleshooting and investigations.
Remember that the blockchain is immutable, so any errors that make it into a block will always be there. Your dApp should resolve user issues with data before storing that data to the blockchain. The trick to handling errors is to guide users to the right solution without slowing them down. That requires attention to who your users are, how they use your dApp, and what they need to resolve a problem. One of your design goals should be to provide error handling that meets your users’ needs in all cases.
Design functions in your blockchain app that focus on user actions, not data
Functions provide the actions of your smart contracts. One way to look at smart contracts is that they are made up of data (nouns) and actions (verbs). Framing smart contracts in this way makes it easier to describe and design them, and generally results in an application that flows well from a user perspective.
Because all applications exist to meet some users’ requirements, it makes sense to design software in light of the user. At the highest level, if a user wants to create a new order, your should start with a function named createNewOrder(). You might change things as you refine your design, but starting with a user perspective helps to maintain authenticity with the software’s goals. Designing technical components that fulfill user goals also helps to avoid deviating too far from high-level functional goals.
Many of today’s software development organizations depend on methods that start with user stories. As a developer, you’ll be asked to produce software that fulfils a requirement that looks like “As a user, I want to ____.” Starting your smart contract with a function that matches what users want to do (that is, the filled-in blank from the preceding statement), is a good design strategy for making user-friendly software.
Every function doesn’t have to map directly to user actions, but your high-level functions should look like they satisfy user stories. You will always need lower-level task-oriented or data-oriented functions to carry out the technical steps of any task. It’s okay if those functions don’t map directly to user stories. But your lower-level functions should all play parts in the functions that users interact with. As a very general rule of thumb, your public functions should look a lot like user story responses.
Store blockchain app data based on user actions, not data structures
Users may not interact directly with data, but you should still attempt to organize data based on user requirements. This general goal is more a rule of thumb. Use this goal when initially designing your smart contract data requirements. You’ll likely need to refine the design and change it, but starting with data mapped to user requests helps your software stay true to user requirements.
For instance, if you’re designing software to create and maintain orders, start with a Solidity struct statement that defines an order the way a user sees it. An order can be a collection of fields that describe it, such as order number, order date, customer order, instructions, and a list of order lines. Order lines contain fields such as product number, price, and quantity. You can define this as a struct of variables and a list of order line structs.
Regardless of the technical details of how you define data, the main purpose of this goal is to consider how users will use data, and try to present the data that way. If you make orders directly available to users to promote transparency in your software, you want to make the orders as easy to access as possible. You don’t want to promote transparency and then make users work hard to figure out what your data means. Making data easy to access and understand will build even more trust.
Keep your blockchain app simple
You have many things to consider when designing a dApp. Although focusing on users should help direct design decisions, the tendency is to attempt to meet every user need. If left unchecked, this desire to do it all will make your software overly complex and difficult to use. Giving users lots of choices sounds like a good goal at first, but an overwhelmed user is not going to like (or use) your software.
The general-purpose adage “keep it simple, stupid” is still relevant. It’s a stern reminder that simplicity is far smarter than complexity. You may have heard that “a confused mind always says no,” but you want your users to accept and use your dApp. You want them to find that your software makes them more effective and efficient. To achieve those goals, you have to make understanding and using your software easy and clear.
Simplicity starts with the user interface, but it doesn’t stop there. Every aspect of your application’s functional and data design must be as simple as possible. Don’t try to do too much. Instead, determine what your users need and want most, and do that. Prioritize the functionality that will make your software stand out. Keeping it simple takes more work, but often results in a focused, consistent product that users will use.
Expect blockchain access to be expensive
Another handy design goal that will help you avoid post-development rework is pretending from the beginning that storing data on the blockchain is expensive. Because in reality, it is. For many who started programming way back when Y2K was far in the future, storage is much cheaper today than it used to be. Most developers today don’t have to worry about data size or where to store it. Blockchain is changing all that. Now, instead of having tons of cheap and fast storage available, you have to pay as you go.
Expensive storage isn’t a new thing in blockchain, but it can be easy to forget. If you remind yourself that storage is expensive early on, you’ll be more likely to think about storage options more thoroughly.
For example, do you need to store the city and state where a product will be shipped? City and state are both dependent on zip code (or postal code in more generic settings.) You can store the zip code in the shipping address, and then just look up the corresponding city and state using an online API at runtime.
Separating data such as the zip code example may not make sense for your application, but you’ll always benefit from thinking through your data storage options. The most expensive storage options are almost always the result of poor design planning. Don’t design blockchain dApps the same way you design traditional database applications. They just aren’t the same. Design with a different mindset and you’ll end up with a better software product.
Stay out of the blockchain app user’s way
A good blockchain application meets the most important user needs in a way that helps them be more effective and efficient. However, your design should consider not only what your application does but also what it doesn’t do.
Every application has constraints and limitations. This design goal focuses on another thing that your application doesn’t do: It doesn’t get in the user’s way. Simply put, your application should help users, not slow them down. Your user interface should help users do their jobs, and the transitions between user interface elements should be intuitive and instructive when necessary.
Sometimes you’ll have to take data from users, and then store it on the blockchain. (You remember that this is expensive, right?) Because you know that you’re going to make users pay to store data on the blockchain, don’t make them wait for it as well. Whenever possible, let your users do something productive while the function that handles their data operates in the background. This might be a good place in your code to use events.
Do everything you can to avoid becoming an obstacle to your users. Nobody likes to wait. Design with thought and your product will have a much better chance of meeting your users’ needs.