and then the compiler inserts the applier—in this case,
invoke.
If you look under the hood, the difference between
object-oriented programming and functional programming is not that big. It’s not some weird Frankenstein
monster. It really blends very nicely, and that is because
under the hood it just fits.
TC You’ve both been talking about layers of abstraction and the fact that there are these new layers in the
software. This is often challenging for programmers when
they try to performance-tune or debug systems, because
now there are these perhaps quite complex layers of software sitting underneath their code, and what those layers
of software are doing can matter to them from a debugging or performance-tuning perspective.
We use NHibernate where I work, and we’ve found
that even though we can see what the plans for the queries are, sometimes it’s difficult for us to understand how
what we did at the level of NHibernate turned into this
series of queries that we now see coming out the bottom.
From a tuning perspective, we can say, “OK, I can see that
I want to change this, but what do I do in the programming language to actually make that happen, because
there’s a layer in between now and we’re not sure what
it’s doing?” Is that a concern for you? Are you doing anything in particular in the context of LINQ and the Entity
Framework to help make those layers more transparent or
to enable the developer to inspect them?
JB One of the problems in NHibernate is that the mapping and the programming binding are all bundled
together. The specific algorithm that is used, for example,
to map a particular expression to inheritance is known
only by somebody who deeply understands the way in
which Hibernate has been implemented. That is not
the case in the Entity Framework, where the mapping
between tables and high-level concepts, entities, and relationships is defined declaratively through mapping view
expressions. It’s a view layer, so every single semantic
concept—entities, relationships, inheritance hierarchies—
is defined formally in terms of database views so there
is always a declarative mapping layer that the developer
has full control of. As you’re developing your entity data
model and the mapping to the underlying relational
model, the actual mapping is described openly in terms
of views. There is much more transparency in the way in
which the mapping operation is happening. That helps
the user in case there are problems.
For example, if your system supports inheritance,
some application developers may define very deep inheritance hierarchies. Mapping very deep hierarchies becomes
very complex, so when developers see the kind of view
expressions that are generated to map that deep hierarchy, they may realize that they should review the depth
of the hierarchy and use a different kind of mapping.
TC I understand that having the mapping materialized as
views certainly adds a layer of transparency to it, but even
so, as a programmer you would have to have a reasonable
knowledge of what is going on with that. For example,
if you have a deep inheritance hierarchy, that’s typically
going to show up as a deep set of joins to pull together
the data from the multiple tables in order to create that
finalized entity. But unless you understand that, unless
you have a sophisticated understanding of the fact that
inheritance and joining are related to one another, it’s
going to be difficult for you to improve the performance
of those things. Is it possible to create tools that help the
programmer more directly understand the connections?
It would be nice to have something that would tell
you that this portion of the LINQ query is associated with
this portion of the SQL that’s coming out the bottom.
The programmers don’t have to deduce it because the
system is actually telling them what’s going on there.
EM Let me give you a two-part answer. People probably
will now say, “Oh, Erik is just an academic.” But the thing
is, if you look historically, the kind of concerns that you
raise have always been there whenever a new level of
abstraction is introduced. When we moved from assembler to higher-level programming, people said, “I don’t
have all the control that I have on the assembly language
level and I don’t trust the compiler to do it, so I want to
look at the assembly.” How often now when you’re writing in high-level languages do you look at the assembler
code that the compiler is generating?
Over time, as the mapping from the abstraction to the
next layer down gets better, this concern will go away and
the tools will get better and people will get a better feeling
of what’s happening. The points you raise are valid, but I
think it shows that we are very early in this game. We’re
just introducing this level of abstraction and people are
not used to it, and the tools maybe are not very mature.
That’s where these concerns come from.
TC Where are developers going to get tripped up in LINQ
and the Entity Framework? We have some new technologies here, and they’re introducing relatively sophisticated
layers of abstraction. When developers start working with
these things and maybe haven’t had a lot of experience
with persistence or with databases or other things like
that, what should they be careful of? Where should they
be looking to avoid falling into problems?
EM I can give you a concrete example. When you’re