Skip to content
Alice Zoë Bevan–McGregor edited this page Aug 10, 2016 · 1 revision
  • Native support for type annotation. Some users complain that Python is a dynamically typed language. Have no fear, WebCore allows you to annotate arguments to your endpoints, where it really matters, to automatically enforce typecasting of data coming in from the web. Additionally, you can use typeguard to apply the practice of strict typing more generally to your code, however WebCore is more permissive than typeguard and treats the annotations as callbacks for casting, not just type enforcement.

  • What's boilerplate? Wherever possible boilerplate has been reduced or eliminated, and the use of sensible defaults further reduces the developer headspace overhead when getting started by eliminating even more; object dispatch, for example, eliminates the need to explicitly declare and maintain a routing table. The recommended template engine cinje similarly removes the usual boilerplate involved in utilizing templates.

  • Speed is nice, but not the goal. WebCore aims to allow you to build complex applications in an expressive, but controlled and understandable way. That it happens to trounce a number of competing frameworks in benchmarks is nice (since, with any framework, there will always be an upper limit to performance) but is ancillary to having a rock-solid internal design.

  • Your code should be Python, not a framework-specific DSL. There is a strong case to be argued that megaframeworks like Django don't represent Python applications, instead, you are opting into an isolated subset of the Python ecosystem tied heavily to the framework. WebCore takes the exact opposite approach: your application should be plain Python, able to use any package in the entire Python ecosystem at will, with the ability to use components of your application outside the context of the framework. This has some interesting, and beneficial, consequences, such as vastly improved code readability and testability, and the ability to trivially expose chunks of your "web application" as command line scripts, as examples. The use of dispatch protocols to isolate endpoint lookup which may have framework-specific ties from your actual endpoints, as well as the view registry to apply endpoint return values to the web response are further examples of this. Your controllers need not have any particular dependency on the context of a web request.

  • Helpful in development, optimized for production. WebCore is the only (that we are aware of) web framework to make use of Python's optimization levels. When run in production (with -O or PYTHONOPTIMIZE set) expensive checks are deleted from the compiled bytecode by Python. This, of course, assumes you test your application in development before deploying! Two examples of this include the complete removal of debugging-level logging statements—no debug logging overhead in production—and elimination of the test for matching endpoint arguments, useful in development to identify exactly what the problem is, but such introspection is generally too slow for production use.

  • A light dusting of magic, but only where it's needed. In order to facilitate some of the more common features of web frameworks, there's a tiny bit of magic sprinkled into the codebase. Magic in the framework is preferable to magic you need to integrate into your application code, and such magic (if configurable and optional) should never have a strong impact on applications. An example of how not to introduce magic would be Django template handling of None values, which are treated as empty strings by default. If you enable strict handling, you utterly break Django's automated administration interface. Faces can't even.

  • Small is good, simple is better, elegant is best, and reverse dependencies are complex. WebCore (and all Marrow projects) attempt, with extreme effort, to elegantly solve their respective problems. This is a slower way to develop, requiring much meditation and evaluation over competing alternate approaches before settling on one, but the results almost speak for themselves. The web.core package is less than 400 source lines of code, and contains more lines of docstring and comments than executed statements. Other byproducts of simplicity are reflected in the modularity and pluggability of components, punting many concerns from the core framework into independently testable packages, such as the dispatch protocol. A lack of reverse dependency means that the components built don't actually depend on the framework making use of them; the core dispatchers of object dispatch, regular expression routes, and traversal, to continue the example, are wholly independent from WebCore and usable outside the context of web requests.