Peter, I'm going to be a bit harsh in the following text. I
don't mean it to
you personally, it's just that sometimes, enough is enough
when it comes to
the BS spread around about software engineering with respect
to databases.
> What it sounds like to me is that you want to utilize
agile software
> development techniques. One tenet of this is to keep
coupling very low.
> This follows the basic OO principle or single
responsibility (SRP). Said
> in another way: a class should have only one reason to
change. If you're
> modeling a domain object and the implementation of the
class must change
> when the DB changes, you're violating SRP and have
tight-coupling.
Of course there's coupling, they represent the same
thing!
So you have this:
Abstract entity E
-> is represented in the relational schema by 1-n
tables/views
-> is represented in the class model by 1-m
classes.
So the point isn't 'when the db changes a class has
to change and oh
boy this implies coupling and therefore it's bad'. The point
is: E changes! So
E's changes should be reflected in its physical
representations: both in the
DB and in the class model. How, that's up to the context of
how the entity is
represented. Perhaps a change has no effect in code but does
in the DB, or has
an effect in code but no effect in the DB.
So the coupling isn't between table and class, the
coupling is between
abstract entity E and class, and also between E and table,
simply because E is
the source and both class and table are projections of E's
definition. The
class and the table aren't standalone items which fell out
of the sky.
If the class isn't representing E, how can you make
any decisions on
instances of E placed inside an instance of the class?
Because if the class
doesn't represent E, the data inside the class instance
isn't an E instance,
it's just data. You have to give it meaning, and you don't
do that by looking
at the class, you do that by looking at what the class
represents, which is E.
That's also why O/R mapping theory even works:
because class and table
(or tables) represent the same thing, you can pass data in
class instance to
table and vice versa. If class and table wouldn't represent
the same thing,
don't give meaning to the data that the data is an instance
of the same
entity, you can't use an O/R mapper at all, because you're
passing data back
and forth but the data suddenly gets completely different
meaning, or better:
it has meaning in a table row, but has no meaning in the
class instance, or
vice versa.
One of the critical points about using a database is
that the tuples
of data inside the database are just bits and represent
something as soon as
meaning is given to them, e.g. they're seen as entity
instances in a table
(rows)
> Can software that works be written this way? Of course
(so, yes, this isn't
> really about capability, its about responsiveness to
change). But, it
> means changes to one aspect of the system ripple
through the rest of the
> system. This makes it difficult, costly, and
time-consuming to make
> changes.
Of course not. Only people who have no clue what the
entity class and
the table in the schema represent suffer from this.
> The drawback of generating types from DB schema is your
are effectively
> coupling modeled types to the DB. Do all changes to DB
schema ripple
> throughout the system? Of course not; but when they do
you can't make
> changes in a timely fashion. Using OO principles and
implementing the
> Repository pattern means most changes to the DB ripple
only into the
> Repository implementations.
Not true, any change to an entity could ripple
through in your code,
using repositories or not, after all: you consume the result
objects a
repository produces in code outside the repository. Don't
think that that code
is safe from a change in an entity, it's not. Even worse: if
you think you can
avoid it, you run the risk that the code you wrote LOOKS
like it contains data
which are instances of a given entity, but in practise
that's not the case.
Though you again seem to miss the point: a DB schema
change doesn't
fall out of the sky: an abstract entity definition has
changed and it has had
an effect on how the relational model representation of this
entity: some
changes are necessary. To be able to work with the changed
entity (which is
the abstract definition) in your code, you too have to check
if the
representation of the entity (in one or more classes) needs
a change. That's
not a given. If it does, you have to make the change there
too. That's not
strange, as both represent the same entity, and THAT entity
got changed.
This has NOTHING to do with 'creating types from db
schema'. It has
even LESS to do with 'data oriented' or 'data driven' (as
there's 0.0 data
involved!). It has everything to do with the concept of what
an entity is.
> I honestly don't think you can be agile in the long run
with round-
> tripping code from DB schema. It's one thing to start
with DB schema,
> generate domain classes from them then they live on
their own. But,
> coupling all the domain types in your business layer
directly to DB schema
> (by way of generating code from schema) means, at least
some, changes to
> the DB have to much of an effect on too much of the
system to make it
> easily maintainable.
Nothing personal, Peter, but when will this bullshit
train from the
alt.net 'databases are evil' movement finally come to an
end?
Changes to class types, tables, views, procs which
produce entity
instances at runtime, they aren't the ROOT source of the
change, they are the
RESULT of a change somewhere else: in the abstract entity
definition.
Again, it has nothing to do with 'coupling all your
domain types to db
types'. The coupling isn't between them. It's indirect, due
to the fact that
they BOTH are a projection of the abstract entity definition
onto different
domains (code and relational schema).
It would be good if more people in the Agile world
would read Halpin's
books, where they'll learn that an entity definition at the
NIAM/ORM (object
role modelling) level has nothing to do with a table, and
you can use that
definition for both tables AND classes.
As you mention maintainability, let's discuss that a
bit. You mention
that apparently creating types from db schemas is less
maintainable. But let's
tell the whole story, ok?
Say I have a NIAM model (and I assume you know what
NIAM is, because
you have a lot to say about maintainability and databases),
and I create
tables AND classes from it. When I have to change an entity,
I change just the
entity in the NIAM model and I produce changes FROM that
model for the
relational schema AND the classes. Less maintainable? I
don't think so,
there's 1 source of information where changes happen.
Ok, back to the db schema. It's possible to reverse
engineer a db
schema to the abstraction level of a NIAM model. If I don't
have a NIAM model
(because changes to a db schema are made direct to tables),
I can reverse
engineer the schema and create classes from it. For example
I can use a system
where I first reverse engineer the db schema to a NIAM model
abstraction,
create inheritance hierarchies between entities etc. etc.
and every db change
is migrated to that model.
When I then generate classes, is it then less
maintainable? If so, you
have to show me why that is less maintainable. After all, I
have a single
source of change.
Alternatively, I can ignore the database and just
create classes.
These too are physical representations of entity
definitions. I then define a
conversion ruleset (mapping definition) how class
definitions should be
converted to table definitions. (equivalent to
Nijssen-Halpin's NIAM to db
schema conversion method See Conceptual Schema and
RElational Database
Design). Again a single source of change.
But make no mistake: the true source for BOTH (and
not just for the
classes or just for the tables) is the abstract entity.
There the changes took
place which were reflected into classes.
This can have different effects on classes and
tables. For example
removing an inheritance link between entity A and B has no
effect on the
tables but does on the code.
> Do some projects work this way? It depends on what you
call "works". I
> find in situations like that there's lots of push-back
from the devs when
> the customer wants changes. The devs know the changes
will ripple through
> the entire system, be difficult to do, time-consuming,
affect quality,
> etc. If they do make the change, quality usually
suffers and the customer
> isn't happy. If they don't make the change then the
customer doesn't have
> what they want, and they're not happy. So, not being
agile can affect
> capability.
I don't think what you describe in the above
paragraph has anything to
do with how you create classes for entities. Being 'adaptive
to change' is
what 'Agile' is about, nothing more, nothing less (hence its
former name
'Adaptive'). The core point of having maintainable software
is that you know
what the software, the code + the relational schema + the
data in the database
+ all other cruft required for running the application,
represents and what
all parts represent, why they're there and why they don't
have a different
shape, form, contents than they do now. THAT's maintainable
software.
Therefore, having a single entity definition which is the
source for BOTH
class AND table means two things:
1) there's a theoretical base for class AND table, so why
the class is there
and why the table is there and why they have the form they
have is based on a
foundation.
2) there's a single source to change. Its changes will have
their effect on
the projections of the definition, but in the context of the
result of the
projection (i.e. class and table).
personally, I find the tremendous amount of FUD
produced by a small
group of people (not directly pointing at you Peter, you're
just the guy
posting here ;)) who think that by using agile manifestos
and avoiding that
big fat server in the corner with 'DB' on it will bring them
glory and
success, getting a bit too much lately. Especially the
people who think that
it has anything to do with 'data driven', as if 'data
driven' means anything,
because there's no data in sight!
You can't abstract away databases for the simple
fact that the
application will spend a lot of time inside them and every
decision has a
direct effect on the application's behavior. You also can't
ignore that
databases live much longer than the software consuming them.
It's therefore
fundamental that, to produce maintainable software, a
relational schema is
based on reality. Only then new software can be written on
top of the
relational schema. Funny thing is, those same reality
elements can be used in
the code, as one can re-use the discoveries which were the
source of the
relational schema inside the code, so there's less (0.0)
ambiguity about what
a row in table T represents.
FB
===================================
This list is hosted by DevelopMentorŪ http://www.develop.com
View archives and manage your subscription(s) at http://discuss.develop.com
|