Developer Center Resources

cancel
Showing results for 
Search instead for 
Did you mean: 

Strategy for Designing an API

NI Tools Network Developer Center » Creating and Managing Reusable Code » Strategy for Designing an API

 

An API, or Application Programming Interface, is a set of public functions that interfaces to some set of underlying code that already exists.  With an API, a developer can programmatically access existing functionality within their own application. One common example of an API in LabVIEW is the NI-DAQmx Driver API.  This API accesses NI-DAQmx compatible hardware and includes functions such as Read, Write, Start, Stop etc.  The user of the API usually does not care about what happens inside of the DAQmx VIs, just as long as they complete the function that they want. 

 

In this document we discuss a few things that a developer should consider when designing an API.

 

 

Simplicity

One important aspect of a good API is simplicity.  There can be hundreds of functions that are available for your application, however not all of them may be completely useful to the end user.  It is important to consider which are the most important functions that a developer would want to access to include in the API.  You may also include advanced functions, but it can be helpful to make these less prominent to the average user.

 

api-simplicity.png

Consistency

Another important consideration of designing an API is consistency.  It is important that the different functions within the API have a consistent look and feel so that a developer can easily understand how to use it.  Icons should have a consistent look using the same header, color scheme, glyphs, etc (more information on best practices for creating icons can be found here).  Connector panes should all have the same or similar pattern (i.e. 4x2x2x4 or 5x3x3x5).  VIs should use consistent data types throughout such as type-definition clusters, references etc.  All of the VIs in the API should take the common data as an input, modify it if necesary and then output the same data type.  Finally it is important to use consistent VI names within the API.  Including the name of the API in the VI name can help keep this consistency, and using common terms such as Read, Write, etc can help users easily determine their functionality.

 

api-consistency.png

Adaptability

The third consideration for an API is adaptability.  It’s important to plan for future expansion and changes to an API.  Using typedefs allow changes to enums and clusters to propagate throughout the API without having to modify every individual VI.  Also if possible, you should leave some empty connector pane terminals so you can add controls and indicators in the future.  Finally it is important to ensure that future additions or changes will not break existing code.  For example renaming VIs or rearranging connector panes may make more sense for future development, but will most likely cause any code that calls it to no longer work.  More discussion on how to handle these changes can be found here.

Usability

The most important consideration for designing an API is usability.  If an API is confusing to a new user, it will be much more difficult to get developers to make use of the API.  One thing to think about regarding usability is the logical organization of palettes.  If you have open and close functions, the open should be on the left and close on the right.  Keep the most commonly used VIs at the top of the palette and lesser common or advanced palettes at the bottom or right. 

 

The functions must also be intuitive to use.  Make sure that the user can easily determine what the function does based on the name.  Use logical names and placement of controls and indicators of the function so that users can easily wire it up and understand what data the function uses.  For example, use the word "Channel" instead of "Ch" and use "in" and "out" to help clarify the direction of data flow.

 

Finally it is extremely important that your API is well documented.  Again ensure that you use intuitive control and indicator names, and list default data in parentheses.  Functions should have a short description listed in the context help and detailed help should be available for more complicated functions.  For more information on this documentation, see Documentation Best Practices.

 

api-usability.png

 

Next: Best Practices for Creating Icons in LabVIEW

Return to: Creating and Managing Reusable Code

Comments
Daklu
Active Participant Active Participant
Active Participant
on

David,

I think this and the other documents you've been releasing are a great start to sharing information the Labview tools community can benefit from. I assume this is a living document and it is intended to help developers learn how to design an api. With those assumptions in mind, I'd like to give some feedback. I hope it doesn't come across as overly critical.

The article is titled "Strategies for Designing an API," but the content doesn't really reflect that. It reads more like an assortment of ideas that are important, but many of them don't address the core concepts of api design. For example, the Simplicity section focuses on palette presentation, a concern to be sure, but entirely secondary to the api design itself. A well designed palette cannot turn a poorly designed api into a well designed api. Same with the Consistency section. Consistent icons and connector panes improve a user's experience with a well designed api, but do little to help a poorly designed api. To me, the content of both of these sections is better suited to a Tips section at the end or in another document altogether.

Adaptability (or compatibility) is absolutely appropriate in a strategy document. It does needs a much more detailed discussion than the 5 or 6 sentences currently there. There are lots of decisions an api developer must make. What are the caveats and consequences of those decisions? How will the api user be affected?

You mention using typedef clusters because they are easy to update. For an api developer publicly exposed typedef clusters come with a whole host of concerns the average Labview application developer may not be aware of. Using typedef clusters is an easy and fast way to update an application when you can be certain all the vis that use the typedef are loaded into memory when the changes are made. When they are not loaded into memory, it is an easy and fast way to introduce unexpected bugs.

Because typedefs do not contain a mutation history, it is surprisingly easy for the user's bundle and and unbundle nodes to access the wrong elements when certain changes have been made to the typedef. (Using bundle/unbundle by name often does not help with this problem.) Things best avoided if your api exposes typedef clusters and you don't want to have unhappy users: Renaming elements, reordering elements, and removing elements. The effect of this on your api is the cluster grows over time as needs change since there is no way to remove the deprecated data elements. They stick around cluttering up the data structure and confusing new users trying to learn the api.

I agree Usability is extremely important when designing an api. Since usability includes concepts such as learnability, flexibility, extendability, compatibility, and a host of other -ilities, it is arguably the only thing an api developer needs to consider. It doesn't make sense to me to list it as a subsection at the end. Good usability occurs when a good api design, good documentation, good palettes, etc all come together. It isn't a step along the way to designing a good api.

If a good api design is the first step towards good usability, what is the first step towards good api design?

Keep the model in mind - One of the most important things to writing a good api is maintaining an api model that is as simple as possible (but no simpler) and communicating that model to the user. What is an api model? It is how the user should *think* about the api to explain it's behavior without actually *knowing* how it works. Similar to how the Bohr model lets us explain certain atomic behaviors even though it doesn't reflect reality. Models describe relationships between the api elements and explain how tweaking element A affects element B.

An api (any code, really) has many different models. A dependency model shows sub vi calls, class inheritance, and other static dependencies. A communication model shows which parallel api elements are communicating with each other and how messages flow through the system. A behavioral model maps api calls to specific behaviors. Complex apis have complex or irregular relationships and require remembering lots of details, making it is hard to create mental models for them. Simple apis have simple and consistent relationships. Mental models are easy to create.

A few things I do to try keep the api model as simple as possible include:

- Make the api calls orthogonal with respect to the behavior they invoke. Each behavior that affects something the user can observe should only be invoked by a single api call. In other words, if I have a vi to "Save" a file to disk, I don't also include a "Save and Close" vi, and "Save and Open New File" vi, or a "Save if File Changed" vi. Inexperienced api developers often think these kinds of composite behaviors are helpful, but usually they just make the model harder to understand. If the user wants a "Save and Close" vi, let him create it himself.

- Define abstraction levels within the api. An api is a form of abstraction, and all abstractions trade away flexibility in exchange for simplicity. As an api designer, it is hard to know how much flexibility to give up. A "thick" api (one that wraps many individual behaviors into reletively few api calls) risks not providing the user with enough resolution to do what they need. A "thin" api may not provide enough benefit to justify the cost of using it.

I think of abstraction levels as the kid brother of abstraction layers, though there isn't a clearly defined distinction between them. An abstraction layer is a high level concept used to describe the big functional parts of a system. It may include many components and apis. An abstraction level has a smaller scope; it exists only in an api. Its purpose is to give users more control over specific behaviors when they are required. A simple api usually only needs a single level. Complex or thick apis often need two levels. Rarely does an api benefit from three public levels, though the api designer may want additional private levels to simplify api maintenance.

Labview's File I/O palette is a pretty good example of api levels. The main palette contains the high level api: Open, Read, Write, Close, etc. The advanced palette contains the lower level api allowing the user the flexibility to fulfill their requirements. (Note: Behavioral orthogonality within an api level is a key factor in creating simple models. I'm a little looser about behavioral orthogonality between api levels.) The reason the I/O palette works is because of the api model, not the other way around.

In the end, the quality of the api is directly related to the quality of the model. If your model is inconsistent or unorganized no amount of documentation, palettes, or icons will make your api "good." Learning how to do it well takes time. Unfortunately there are very few books that talk about the challenges of designing reusable code. One interesting one is Practical API Design: Confessions of a Java Framework Architect. Reading it will help new api designers get started on the right foot.

David_L
Active Participant
Active Participant
on

Hi Daklu,


Thank you very much for your feedback.  I'm glad to see that people are not only reading the documents but seeing value in it and starting conversations about it.

I agree with all of your comments.  This document definitely is a living document, but know that it's intention is a place to start.  By no means was the implication that this is the all encompassing guide for creating an API.  In fact, the LabVIEW Tools Network Dev Center as a whole is intended for that, and many of the specific topics we've written over the past few years hopefully address a lot of the specifics that may be missing from here.  If not, there are many places to grow and I assure you we aren't done creating new topics.  Feedback like this is what sparks the ideas for new content and I will definitely use it going forward.

This all in mind, the Dev Center is an open community and we fully welcome input and content from everyone.  If you have ideas on how to add valuable information, we encourage and welcome you to create your own documents or work with us to enhance what is already there. 


Thanks again,

David

crelf
Active Participant Active Participant
Active Participant
on

Since this is a living document, it'd be an awesome fit for the LabVIEWwiki.org - any chance we could put it up there so we all can improve it?





Copyright © 2004-2020 Christopher G. Relf. Some Rights Reserved. This posting is licensed under a Creative Commons Attribution 2.5 License.
Active Participant
Active Participant
on

You can improve this one: Just click "edit" in the upper-right. Personally, I vastly prefer the WYSIWYG on NI Community to a wiki-based editor.

Daklu
Active Participant Active Participant
Active Participant
on

I prefer WYSIWYG editors also, but the one advantage LabVIEWwiki has is that the content is clearly not "owned" by anyone.  I have always read NI community documents written by NI employees with the idea that person who originated the document is responsible for it and working from a larger overall plan to deliver a consistent message to the community.  Completely rewriting content in a way that makes more sense to me could disrupt the message NI is trying to deliver.  That's been my line of thinking anyway and why I've always added comments instead of editing documents directly.

*If* these documents are intended to be more wiki-ish in nature I might just go on a writing binge and not surface for weeks. 

(I really hate writing; please say they're not wiki-ish...)

crelf
Active Participant Active Participant
Active Participant
on

DavidStaab wrote:

You can improve this one: Just click "edit" in the upper-right. Personally, I vastly prefer the WYSIWYG on NI Community to a wiki-based editor.

Awesome - I didn't see that before.  Thanks!





Copyright © 2004-2020 Christopher G. Relf. Some Rights Reserved. This posting is licensed under a Creative Commons Attribution 2.5 License.
David_L
Active Participant
Active Participant
on

Since this discussion is valuable, however tangent to this document, I decided to start up a new discussion and reply here.

Contributors