On Tuesday, 3 January 2017 at 08:09:54 UTC, Chris Wright wrote:
On Mon, 02 Jan 2017 21:25:42 -0800, Adam Wilson wrote:
As far as I am aware, the only way to meet those requirements is to use a base-class model. Is there something I am missing?

Templates. Templates everywhere.

Every method in your application that might possibly touch a database, or touch anything that touches a database, and so on, needs to be templated according to what type of database might be used.

That limits you to one DB per compilation or craploads of template bloat.

There are a number variables here: the number of DB backends you wish to support (b), the number of DB backends you actually use at runtime (r), the number of symbols (not quite the word I'm looking for but, oh well) you need to represent an abstract backend API (s),the number of class types you use to abstract the backend (c) and the number of template you use to abstract the back end (t).

b is ideally fixed at "all the backends"
r is variable and dependent on the application (e.g. I may only care for Postgres, but someone else may wish to support many SQL DBs). If r == 1 then a template approach is acceptable.

s is a function of the dissimilarity of the backends you wish to support. Breaking the problem up into SQL like, graph-like and KV-store is a tradeoff somewhere between having "one DB (interface) to rule them all" and one interface for each backend.

c + t = s

What this represents is a tradeoff between compile time dispatch and runtime dispatch. As s moves from being all classes to more templates + structs (from the "bottom up"), the last layer of dynamic dispatch before the static dispatch of the templates becomes an algebraic type selection (i.e. check the tag, choose the type, and then static dispatch).

I believe the sweet spot for this lies at the point where the dissimilarity of similar backends becomes apparent after the start of a logical operation. Or put another way the point where I know the result that I want and no longer care about any implementation details.

As an example using a compute API (sorry I don't know much about DBs): launching a kernel represents a single logical operation but is in fact many driver calls. If one wishes to abstract the compute API then this point becomes the point I would choose.

Finding those points will probably not be easy and may be different for different people, but it is worth considering.

</ramble>

Reply via email to