Databases and the D Standard Library
Nicholas Wilson via Digitalmars-d
digitalmars-d at puremagic.com
Tue Jan 3 01:53:19 PST 2017
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>
More information about the Digitalmars-d
mailing list