class Polygraph extends Component {
bdElements(){
return svg({width: 200, height: 200},
svg("g",
svg("polygon", {bdReflect_points: [this.kwargs.stats, pointsToPolyPoints]}),
svg("circle", {cx: 100, cy: 100, r: 80}),
e(Collection, {root: svg("g"), childType: AxisLabel, collection: this.kwargs.stats})
)
);
}
}
See it in a Pen or in your browser
Does it look familiar? But Backdraft is dramatically different:
Small
~10x smaller than competing frameworks
Fast
faster than competing frameworks
Easy to Use
no compilation step required
Easy to Understand
zero dependencies
Declarative Composition
Backdraft's API includes declarative composition, but doesn't invent yet another markup language to do it...it's all done in pure JavaScript. Ask yourself, "do I instantly understand the example code?" If the answer is yes, then ask yourself another question: is using a markup language to express an application worth the cost in complexity?
A declarative, compositional API does not require a virtual DOM. The two concepts--how a program is expressed compared to how that expression is implemented--are orthogonal.
Backdraft does not employ a virtual DOM. This design decision results in several significant advantages. Teams are right to ask the question: is the cost in space, performance, and complexity of a virtual dom design justified?
dialogBody(){
this.title = "Rename";
return e("div", {className: "rename-dialog"},
e("div",
e(Labeled, {label: "Current Name"},
e(Input, {
value: this.kwargs.currentName,
disabled: true
})
),
e(Labeled, {label: "New Name"},
e(Input, {
bdAttach: "newName",
value: this.kwargs.currentName,
placeholder: "enter new name",
style: "min-width:20em"
})
),
),
e("div", {className: "bottom-buttons"},
e(Button, {label: "Cancel",
handler: () => this.onCancel()}),
e(Button, {label: "OK",
handler: () =>
this.promise.resolve(this.newName.value)})
)
);
}
This is code from the rename dialog example.
Small Code Stack
Backdraft's code stack is about 2000 lines of pure, modern JavaScript with no dependencies. Backdraft is not new. It's been used in various incarnations in private, for-profit projects for over a decade. And during that time, Occam's razor has been continually applied. Backdraft is order(s) of magnitude smaller than competing solutions. And the cost of size is pervasive:
Big libraries cost more for engineers to understand--both the API, and, perhaps even more important, the side effects of using that API.
Big libraries increase debugging cost. Groking a couple hundred lines of library code to understand a defect is doable. Groking thousands of lines under the pressure of a delivery schedule is a completely different matter.
Big libraries cost more to download. This is particularly important--perhaps in terms of keeping customers--when targeting mobile platforms.
Big libraries are often computationally expensive. Once again, this is particularly important when targeting mobile platforms.
Backdraft is order(s) of magnitude smaller than the competition...
Approximate kilobytes of downloaded code (application + library) for a small "todo" application. See the Backdraft example for details.
Backdraft applications never require more code and often requires less...
Approximate lines of client code for a small "todo" application. Note that the Backdraft example is not as small as possible, but rather was built to demonstrate Backdraft's abstraction mechanisms and includes serveral, generic, reusable components built from scratch. These kinds of comparisons can be rigged: our point isn't that the competing frameworks are bad in this respect, but rather to demonstrate decreasing library complexity does not, ipso facto, result in increased program complexity.
Minimal Computational Complexity
Backdraft minimizes computational complexity and Backdraft's API design makes it hard to use incorrectly. Assuming no library design or library usage errors, it's hard to imagine any user interface library implying such computational complexity that the computational resources of an average computer would be stressed.
But there are three assumptions in that statement:
- What if the program uses the library improperly?
- What if the library contains a design flaw?
- What if the target device is a ~$200 Android device on a 400Kbps link with a 400ms round-trip-time (“RTT”)?
Libraries implementations are often overly complex and then used improperly because the complex implementation causes severe side-effects if used wrong. Paradoxically, libraries that employ complex designs to "simplify" usage are often the same libraries that are easy to misuse, resulting in new problems.
There is an obvious approach to controlling these risks:
Define an API that is hard to misuse; design and implement with simple algorithms.
For example, many modern JavaScript libraries rely on a virtual dom. Why? What, precisely, are the benefits of such designs? Is the computational complexity implied by a virtual dom design justified by its benefits? We think not.
And if virtual dom is great and the computational complexity insignificant, then why did the number one product in this space recently decide that it needed to replace it's implementation and provide proof that the new solution was, at least, better?
Backdraft applications are fast...
append
update
reorder
Approximate times for tests described in a simple benchmark for several javascript frameworks. The Backdraft example tested can be found here. These times show order of magnitude comparisons; they are not intended to show high-precision times.
All the Normal Requirements
Baseline requirements aren't particularly interesting. But, they are requirements nevertheless. Backdraft fulfills them.
- Free and open source: All code is licensed under The 3-Clause BSD License.
- Fully documented: here are the docs.
- Fully tested: here are the tests.
- Commercial support is available from its creators.