We are very happy to unveil Praxis today. Praxis is a framework that takes a different approach to creating APIs, an approach that treats both designers and implementors as first class citizens throughout the API building process.
With Praxis you create an API by going through the design, review and implementation phases and iterating over them as necessary. Each phase is done independently, and possibly by disjoint sets of people. For example architects could design it, developers implement it and both can review it alongside the customers. Building APIs with Praxis leads to better designs, faster developer times and precise documentation that is apt for both human (web browsable) and machine consumption (JSON definition files).
Below is the a depiction of the Praxis workflow containing minimal, yet real examples.
A key differentiating feature of Praxis is that while the design and implementation phases are done independently, Praxis ensures that they are always consistent and enforced at all times. This enforcement automatically holds true throughout any number of iterations of the design-review-implementation phases. With Praxis you can say goodbye to the headaches of merging automatically generated code with your real code every time your API definition changes.
##Motivation and Goals
Praxis was born after many years of collective API experience seeing our effort continually wasted in fighting and bending existing frameworks, rather than working with them and investing our engineering time in what matters: the application logic.
Praxis is built on a set of goals that we believe any API framework should assist with:
###Separation of concerns
Designing and implementing APIs are very different things which require very different skill sets. A framework must allow both of these tasks to be performed independently, potentially by completely different sets of people. An architect or designer should be able to complete a full API specification without having a single line of real implementation code written down. The resulting assets from the design phase must be directly usable for reviewing and refining the design, as well as used as an API contract to the final implementor.
While the design and implementation are separate concerns, it is absolutely essential that they are always consistent and enforced as a single unit. This means that an API framework must ensure that at runtime, the final implementation of the service always enforces all of the client-facing API specifications agreed upon in the design phase.
###Precise and ready-to-be-used documentation
The framework must allow the creation of precise and complete API reference documentation that can be handed to the consumers of the service. This must include documentation that can directly be consumed by humans wanting to interact with the service, as well as computer-parseable assets that allow for automatic generation of client software.
API services are built to be consumed, so their usability is paramount. An API framework should favor and encourage API designs to follow consistent, common and repeatable patterns. Doing so enables an easier and faster adoption path by reusing already existing client software, and shortens the ramp-up time for building new tools against it.
###Focus on application logic
The goal of building an API is to enable your customers to execute your application logic through a well-defined and controllable remote interface. The goal is not to dedicate valuable engineering resources to battling web-related technical issues. Therefore, an API framework should remove any non-essential web and boilerplate code from the hands of the implementor so he can focus on real application logic. This must include things such as handling API transport, parameter coercion, parameter validation, versioning, etc.
Deploying an API should be as easy as possible. An API framework should favor reusability and integration with deployment tools by encouraging a consistent and repeatable set of patterns in application configuration and packaging. Packaging APIs in a repeatable manner makes your operations team happy, makes it easier to integrate with systems such as Continuous-Integration or Continuous Deployment, and reduces overall time for getting your API out in the wild.
APIs come in all shapes and sizes, and the amount of help and features that any API framework could provide is virtually unlimited. Features that are crucial for some APIs might be completely useless for others. Since there is not a single correct way to build an API, frameworks must be both modular and extensible. Modularity is important to reduce code so applications can include only the pieces of the framework they care about. A the same time, extensibility is critical so new features or integrations with other tools can be easily added without changing the core of the framework.
Anybody that has done any API development at all should be very familiar with these goals. The framework that we are unveiling today we built from the ground up to tackle every single of these goals, and we believe this first release of Praxis already provides substantial support for each of them. There is, however, a long way ahead of us (all of us!) to improve Praxis in not only the above areas but also in new areas to come.
##Software and documentation
Praxis is written in Ruby and it consists of a suite of libraries that you can reach through their repositories and corresponding gems. These are all free and open source:
- Attributor - A powerful attribute and type management library which we use throughout the framework to document, coerce and validate type structures such as parameter definitions or media type representations.
- Praxis-blueprints - A library that allows for defining reusable, typed attribute structures and sets of related views with which to render them. Blueprints are the backing to Praxis media types.
- Praxis-mapper - A completely optional library for Praxis that takes quite a different approach to loading large amounts of data from for a tree of associated models, while minimizing requests to external services.
- Praxis - The API building framework itself.
Each of these related projects are very powerful pieces of software on their own and deserve individual blog posts.
An introductory post makes it difficult to include many details about how the framework is used. Rather than trying to cram incomplete information into an already long article, instead I am going follow up with a series of posts. In them I will cover how to build a complete API using Praxis, guiding you through the steps of designing it, generating documentation, all the way to implementing the business logic. Stay tuned for that.
For the impatient, I recommend that you look at the getting started guide and the extensive reference documentation.
###Why another framework?
While this also might deserve an article of its own, I do want to briefly cover why we built Praxis from the ground up rather than using any of the other excellent frameworks that exist today.
The short answer is that an API engine that tightly integrates the design and runtime enforcement of an API is not something that can be easily bolted onto an existing framework after the fact. It requires a seamless and tight bidirectional integration that goes from design to implementation as well as from implementation to design. In fact, the first version of Praxis was initially built on top of Sinatra, a fantastic and lean Web framework. One can argue that it was a success as there are still many sub-systems in production at RightScale today using that older incarnation. The reality, though, is that to hook-in and enhance Sinatra the way we wanted meant rewriting and monkey patching too many core Sinatra components, and even then, it still prevented us from doing and exposing constructs the way we really wanted. So we decided to re-write the underlying engine from scratch to achieve a much crisper and pluggable framework. The result is what Praxis is today.
A similar answer applies to the question, “Why not use some of the great API documentation frameworks that already exist?” In this case, we decided that rather than picking sides and choosing one of the many formats/syntaxes that exist today, we should instead focus on creating a Praxis DSL that was powerful enough to allow conversions to and from any them. In other words, we want to be consistent with our ‘extensibility’ tenet and provide more options for Praxis users.
We’re very much looking forward to many integrations in the near future.
RightScale has been using earlier versions of Praxis for over a year, and the development speed, documentation and robustness of the resulting services have been phenomenal. So, we are very excited to share the Praxis suite of libraries with the community so you can also start building your APIs in the same way and enjoy all these benefits. While the core of the framework has been battle-tested, this first initial open source release has undergone a heavy rewrite to simplify, clean up and remove dependencies. For that reason, I wouldn’t consider it production ready quite yet.
While Praxis is currently written in Ruby, we believe that it offers a new way to develop APIs that goes beyond the language itself, and can be easily adopted by others. We are really hoping that with your help, we can not only spread the joy to other languages, but also integrate with many of the other great documentation and API framework tools that exist today.