Model identification strategy [Was: I need help with a design]

On 8 October 2010 14:48, Marnen Laibow-Koser [email protected]
wrote:

Colin L. wrote:


I think we are just going to have to agree to differ on this one,

I would rather not do that. In general, that’s a sign that more
discussion is needed, as one or both of us is probably missing
something. Certainly I’m learning a lot from this discussion.

However, I’m perfectly willing to start a new thread for this.

Done

I think I would like to start again as I realise (having been forced
to defend my corner and think more about what I am rabbiting on about)
that it not so much when the models are identified that is the issue
for me but how they are identified. To go back to your original
suggestion:

when I
put together an application, I usually think first about how I want it
to present itself to the user and what the user should be able to
accomplish (and write Cucumber scenarios accordingly). Only as a result
of making those scenarios reality do I write model classes or anything
else.

I read into this (possibly incorrectly) that the purpose of the models
is purely to satisfy the scenarios and they are identified by
examining the scenarios and generating a set of models to satisfy
them. I think that that is too narrow a view to take, particularly
considering that we are in the first phase of a project and we know
there will be many modifications and extensions to the requirements in
the future.

Generally an app is in some sense simulating or mapping things in the
real world (or some conceptual world), users, shopping carts, products
and so on. I suggest that one should examine the scenarios and
identify the underlying objects in that real world without worrying
too much about the details of the scenarios. The models then
represent those objects and one can work out how to satisfy the
scenarios using those models. I believe this should provide a better
base on which to build the app. Scenarios will be modified and added
to dramatically over time but the underlying objects in the
requirements are less likely to change (I don’t mean that their
behaviour will not change, but their existence). If the
identification of the objects is correct (or optimum or whatever) at
the start then this will minimise the effort in tracking the changing
requirements.

I am still not sure that I am expressing myself very well.

Colin

Colin L. wrote:

On 8 October 2010 14:48, Marnen Laibow-Koser [email protected]
wrote:

Colin L. wrote:


I think we are just going to have to agree to differ on this one,

I would rather not do that. In general, that’s a sign that more
discussion is needed, as one or both of us is probably missing
something. Certainly I’m learning a lot from this discussion.

However, I’m perfectly willing to start a new thread for this.

Done

I think I would like to start again as I realise (having been forced
to defend my corner and think more about what I am rabbiting on about)
that it not so much when the models are identified that is the issue
for me but how they are identified.

OK – and once again, thanks for making me really think about what I do!

To go back to your original
suggestion:

when I
put together an application, I usually think first about how I want it
to present itself to the user and what the user should be able to
accomplish (and write Cucumber scenarios accordingly). Only as a result
of making those scenarios reality do I write model classes or anything
else.

I read into this (possibly incorrectly) that the purpose of the models
is purely to satisfy the scenarios

Well, in a sense, I think that is the case. This may be a little bit of
a reductio ad absurdum, but bear with me (as I start inadvertenly
channeling Ron J. or someone :slight_smile: ).

The scenarios (ideally, though it’s debatable how closely that ideal is
ever achieved) describe all the functionality of the application – that
is, everything that is actually of value to the user. The user never
sees or cares about the internal workings of the application (except as
specified in his requirements); they are not of value to him. Only the
functionality is of value to the user.

Now, since only the functionality is of value to the user, from that
perspective it is clear that the only purpose of the application code is
to provide an implementation that delivers that functionality. If we do
anything else, we are not providing any particular value to the user.

Since the models are part of their app code, their only purpose is to
implement the functionality specified by the user (which is what is
captured in the scenarios). So yes, on balance, I think I would agree
with the contention you attribute to me.

Apparently you do not. What else do you think the models – or any of
the rest of the app code – is there for? I’m hard put to come up with
anything else…

and they are identified by
examining the scenarios and generating a set of models to satisfy
them. I think that that is too narrow a view to take, particularly
considering that we are in the first phase of a project and we know
there will be many modifications and extensions to the requirements in
the future.

But we don’t know what those modifications will be, and therefore (where
possible) we do not design for them. We design for what we have now,
and refactor later as necessary. Remember YAGNI.

(There are a few practical exceptions. For example, I usually put I18N
in right at the beginning even if it’s not a requirement, because going
back and wrapping all display text in translate functions later is a
pain in the ass.)

Generally an app is in some sense simulating or mapping things in the
real world (or some conceptual world), users, shopping carts, products
and so on. I suggest that one should examine the scenarios and
identify the underlying objects in that real world without worrying
too much about the details of the scenarios.

Precisely. That’s what I meant by business domain objects in my earlier
post. If we want the user to be able to purchase products, we know we
have “user” and “product” as business domain objects. We don’t know
(though we might strongly suspect) that we will have User and Product
classes in our program.

The models then
represent those objects and one can work out how to satisfy the
scenarios using those models.

In many styles of programming, this is the case, but it absolutely does
not have to be – see http://c2.com/cgi/wiki?OopNotForDomainModeling for
some discussion of this. This is an implementation detail, and as such
it is irrelevant right up till the moment we start implementing.

I believe this should provide a better
base on which to build the app.

But it won’t. It just forces you into prematurely making implementation
decisions on insufficient information, and perhaps slightly ossifies the
result of those decisions.

Why do you think there is any advantage to doing this.

Scenarios will be modified and added
to dramatically over time but the underlying objects in the
requirements are less likely to change (I don’t mean that their
behaviour will not change, but their existence).

That’s true with regard to the underlying domain objects. It is not
necessarily true with regard to the underlying program objects.

If the
identification of the objects is correct (or optimum or whatever) at
the start then this will minimise the effort in tracking the changing
requirements.

But that’s not even true. It assumes a degree of clairvoyance regarding
the future directions the project will take that we do not generally
possess.

I am still not sure that I am expressing myself very well.

I think you are…I hope I am too…

Colin

Best,

Marnen Laibow-Koser
http://www.marnen.org
[email protected]

On 8 October 2010 18:21, Marnen Laibow-Koser [email protected]
wrote:

else.
is, everything that is actually of value to the user. The user never
sees or cares about the internal workings of the application (except as
specified in his requirements); they are not of value to him. Only the
functionality is of value to the user.

I don’t entirely agree here. Firstly the scenarios only describe the
functionality of the current phase of development. The user has an
interest in the internal workings of the application in so far as he
expects there to be further phases and therefore expects the design to
facilitate later phases as far as possible, even though he may have
little idea what those phases may be. I know we don’t want to do
premature optimisation however, I will come back to this below.

Now, since only the functionality is of value to the user, from that
perspective it is clear that the only purpose of the application code is
to provide an implementation that delivers that functionality. If we do
anything else, we are not providing any particular value to the user.

Again I will quibble, slightly tongue in cheek, though not entirely.
The purpose of the code is to provide the implementation, as you
state, however the process of developing the application has other
purposes. Notably to provide us with a living wage and job
satisfaction. I believe that to some extent software development can
be an art as well as an engineering operation. Consider initially
just small sections of code. Often there are numerous ways of coding
a piece of functionality, with no difference in the result of running
the code. Usually one of these ‘feels’ right. Nothing in the
scenarios suggests one or the other but we code it the ‘right’ way
because we get satisfaction sitting back and savoring the design. OK,
I am getting a bit carried away here but I am sure you know what I
mean. In addition we may code it a particular way because we believe
it will be easier to maintain and is less likely to have unnoticed
bugs. I think these ideas also apply to the larger scale design of
the app, including the models and relationships. The overall design
can be aesthetically pleasing, or even a thing of beauty (I know, OTT
again, sorry). The scenarios do not address that aspect of the
design, only the designer can do that.

Since the models are part of their app code, their only purpose is to
implement the functionality specified by the user (which is what is
captured in the scenarios). So yes, on balance, I think I would agree
with the contention you attribute to me.

Apparently you do not. What else do you think the models – or any of
the rest of the app code – is there for? I’m hard put to come up with
anything else…

The purpose of the models is obviously to satisfy the scenarios, but
the purpose of the design is also to facilitate further phases, even
though we do not know what they will be (see later again) and to give
us satisfaction in the design as discussed above.

and refactor later as necessary. Remember YAGNI.
I am not suggesting adding extra functionality that may or may not be
required, but ensuring that the initial design provides a base that is
most likely to allow extra functionality to be added without major
re-structuring of the design.

identify the underlying objects in that real world without worrying
too much about the details of the scenarios.

Precisely. That’s what I meant by business domain objects in my earlier
post. If we want the user to be able to purchase products, we know we
have “user” and “product” as business domain objects. We don’t know
(though we might strongly suspect) that we will have User and Product
classes in our program.

I think now our ideas are starting to diverge. My initial assumption
would be that there will be user and product classes because they
are domain objects (unless the scenarios show that they do not
actually exist in the app).

The models then
represent those objects and one can work out how to satisfy the
scenarios using those models.

In many styles of programming, this is the case, but it absolutely does
not have to be – see http://c2.com/cgi/wiki?OopNotForDomainModeling for
some discussion of this.

I entirely agree there are different ways of doing things, I can only
describe the way that works for me.

This is an implementation detail, and as such
it is irrelevant right up till the moment we start implementing.

I am not sure what you mean here.

I believe this should provide a better
base on which to build the app.

But it won’t. It just forces you into prematurely making implementation
decisions on insufficient information, and perhaps slightly ossifies the
result of those decisions.

Why do you think there is any advantage to doing this.

See below.

Scenarios will be modified and added
to dramatically over time but the underlying objects in the
requirements are less likely to change (I don’t mean that their
behaviour will not change, but their existence).

That’s true with regard to the underlying domain objects. It is not
necessarily true with regard to the underlying program objects.

But that is the point, if the domain objects and program objects map
onto each other closely, then since the domain objects tend not to
change dramatically the program objects will also not change
dramatically (though their behaviour will be added to and modified of
course.

If the
identification of the objects is correct (or optimum or whatever) at
the start then this will minimise the effort in tracking the changing
requirements.

But that’s not even true. It assumes a degree of clairvoyance regarding
the future directions the project will take that we do not generally
possess.

Again, by mapping domain objects closely to program objects then
clairvoyance is not required as domain objects tend to be stable.

I am still not sure that I am expressing myself very well.

I think you are…I hope I am too…

Certainly.

Colin

PS My brain hurts.

Colin L. wrote:

On 8 October 2010 18:21, Marnen Laibow-Koser [email protected]
wrote:

else.
is, everything that is actually of value to the user. �The user never
sees or cares about the internal workings of the application (except as
specified in his requirements); they are not of value to him. �Only the
functionality is of value to the user.

I don’t entirely agree here. Firstly the scenarios only describe the
functionality of the current phase of development.

Which, at any given time, is all we care about.

The user has an
interest in the internal workings of the application in so far as he
expects there to be further phases and therefore expects the design to
facilitate later phases as far as possible, even though he may have
little idea what those phases may be.

No. The user wants the application to work. Other things being equal,
he doesn’t care how. The internal workings are irrelevant to the user;
the concern of further phases is one of project management, not
internals.

It’s to the developer’s advantage to structure the application so that
adding more value for the user will be as easy as possible – hence good
development practices – but the user sees and cares about none of this.

Don’t kid yourself that the user has any reason to care about what goes
on under the hood, as long as the application works as specified.

I know we don’t want to do
premature optimisation however, I will come back to this below.

Now, since only the functionality is of value to the user, from that
perspective it is clear that the only purpose of the application code is
to provide an implementation that delivers that functionality. �If we do
anything else, we are not providing any particular value to the user.

Again I will quibble, slightly tongue in cheek, though not entirely.
The purpose of the code is to provide the implementation, as you
state, however the process of developing the application has other
purposes. Notably to provide us with a living wage and job
satisfaction.

That adds value for the developer, not for the user. If all we care
about is running up the billable hours, there are lots of ways to do
that – and not all of them involve adding value for the user – and
soon the user will realize this and find a developer who can actually
add value for him.

Your user’s goals are not your goals.

I believe that to some extent software development can
be an art as well as an engineering operation.

Completely agreed. (My background is in musical composition, so I
would say that. :slight_smile: )

Consider initially
just small sections of code. Often there are numerous ways of coding
a piece of functionality, with no difference in the result of running
the code. Usually one of these ‘feels’ right. Nothing in the
scenarios suggests one or the other but we code it the ‘right’ way
because we get satisfaction sitting back and savoring the design.

Right. If we are good developers, we probably have a sense of the best
way to write something at the moment. Other things being equal, there’s
nothing wrong with that.

OK,
I am getting a bit carried away here but I am sure you know what I
mean. In addition we may code it a particular way because we believe
it will be easier to maintain

To a point. But not much. Do The Simplest Thing That Could Possibly
Work is an important principle. Don’t bend over backwards to
generalize; let the generalizations emerge.

and is less likely to have unnoticed
bugs.

That’s what tests are for.

I think these ideas also apply to the larger scale design of
the app, including the models and relationships. The overall design
can be aesthetically pleasing, or even a thing of beauty (I know, OTT
again, sorry). The scenarios do not address that aspect of the
design, only the designer can do that.

And the user will not care one iota about all that beauty. It, in and
of itself, adds no value for him at all.

The only thing adding value for the user here is that the beautiful code
makes the app easier to maintain – that is, to extend functionality
– that is, to do things that do add value for the user.

To reiterate: there is no user value at all in elegant code, except
insofar as the elegance makes future development easier. There is
developer value, but no user value.

Since the models are part of their app code, their only purpose is to
implement the functionality specified by the user (which is what is
captured in the scenarios). �So yes, on balance, I think I would agree
with the contention you attribute to me.

Apparently you do not. �What else do you think the models – or any of
the rest of the app code – is there for? �I’m hard put to come up with
anything else…

The purpose of the models is obviously to satisfy the scenarios, but
the purpose of the design is also to facilitate further phases,

No! The purpose of the design is to make the project as we know it
now
work. Further phases can take care of themselves when they come.

even
though we do not know what they will be (see later again) and to give
us satisfaction in the design as discussed above.

Since we don’t know what the further phases will be, we can’t design for
them. Period. You’re deluding yourself into premature generalization,
and apparently somehow think that your clients care what the source code
looks like.

and refactor later as necessary. �Remember YAGNI.
I am not suggesting adding extra functionality that may or may not be
required, but ensuring that the initial design provides a base that is
most likely to allow extra functionality to be added without major
re-structuring of the design.

That would require too much guesswork. There is no point in doing that
– you’ll probably guess wrong. Implement today’s requirements today,
and refactor for tomorrow’s requirements when you know what they are.

identify the underlying objects in that real world without worrying
too much about the details of the scenarios.

Precisely. �That’s what I meant by business domain objects in my earlier
post. �If we want the user to be able to purchase products, we know we
have “user” and “product” as business domain objects. �We don’t know
(though we might strongly suspect) that we will have User and Product
classes in our program.

I think now our ideas are starting to diverge. My initial assumption
would be that there will be user and product classes because they
are domain objects (unless the scenarios show that they do not
actually exist in the app).

That would be my initial assumption as well when I start to implement,
but that’s because I follow such a programming style in general.
Apparently not everybody does.

[…]

This is an implementation detail, and as such
it is irrelevant right up till the moment we start implementing.

I am not sure what you mean here.

I mean that the nature our object model should be of no concern to us at
all till the moment we start to write actual code.

�I believe this should provide a better
base on which to build the app.

But it won’t. �It just forces you into prematurely making implementation
decisions on insufficient information, and perhaps slightly ossifies the
result of those decisions.

Why do you think there is any advantage to doing this.

See below.

�Scenarios will be modified and added
to dramatically over time but the underlying objects in the
requirements are less likely to change (I don’t mean that their
behaviour will not change, but their existence).

That’s true with regard to the underlying domain objects. �It is not
necessarily true with regard to the underlying program objects.

But that is the point, if the domain objects and program objects map
onto each other closely,

Which there is no guarantee that they will. (There was an interesting
post from Jim Coplien a while back where he said that very few bank
systems actually have any sort of Account object internally, even though
there’s a business concept of an account.)

then since the domain objects tend not to
change dramatically the program objects will also not change
dramatically (though their behaviour will be added to and modified of
course.

Behavior is most of what program objects are about. That’s not really
true of domain objects. I guess – and I hadn’t realized this before –
that in that sense, the two are somewhat incommensurable. Perhaps this
is why some OO experts don’t like modeling domain objects with program
objects. I wonder.

�If the
identification of the objects is correct (or optimum or whatever) at
the start then this will minimise the effort in tracking the changing
requirements.

But that’s not even true. �It assumes a degree of clairvoyance regarding
the future directions the project will take that we do not generally
possess.

Again, by mapping domain objects closely to program objects then
clairvoyance is not required as domain objects tend to be stable.

Really? What happens when your client’s business model changes? Or
when you discover domain objects your client didn’t know existed? (Not
so far-fetched; see http://c2.com/cgi/wiki?WhatIsAnAdvancer for a
real-world example.)

I am still not sure that I am expressing myself very well.

I think you are…I hope I am too…

Certainly.

Colin

PS My brain hurts.

Mine too. :slight_smile:

Best,

Marnen Laibow-Koser
http://www.marnen.org
[email protected]

On 8 October 2010 21:58, Marnen Laibow-Koser [email protected]
wrote:

functionality of the current phase of development.

Which, at any given time, is all we care about.

My turn to say No! I agree that one should not do extra work to add
features that may never be required, but where choices exist that do
not add extra work then the design should be so as to provide the best
base for future extension and modification.

internals.

It’s to the developer’s advantage to structure the application so that
adding more value for the user will be as easy as possible – hence good
development practices – but the user sees and cares about none of this.

Don’t kid yourself that the user has any reason to care about what goes
on under the hood, as long as the application works as specified.

My experience does not match this. Most of my work has been in-house
developments where the customer and myself are the same company. In
my case management has been keen to ensure that the code base should
be well designed in order to minimise future costs. Perhaps in the
case of contract work things are different. I find it surprising
though that a customer would not be at all interested in this.
Perhaps I should not be surprised however.

Again I will quibble, slightly tongue in cheek, though not entirely.
The purpose of the code is to provide the implementation, as you
state, however the process of developing the application has other
purposes. Â Notably to provide us with a living wage and job
satisfaction.

That adds value for the developer, not for the user. Â If all we care
about is running up the billable hours, there are lots of ways to do
that – and not all of them involve adding value for the user – and
soon the user will realize this and find a developer who can actually
add value for him.

Oh no, you completely misunderstand me, I was not suggesting in any
way ‘running up billable hours’. I entirely agree that any such
practice is to be deprecated. That is not in the Rails sense where it
means it is ok to keep doing it for the moment but it should be phased
out when convenient. :slight_smile:

Your user’s goals are not your goals.

To a great extent I think you are wrong here. At first sight you
might say that my principle goals are to make a living and achieve job
satisfaction. However the best way to achieve that is to provide the
best product to the user with the minimum effort (always a compromise
of course) and hence minimum cost. The Users goal is to receive the
best product for the minimum cost. Hence the goals are pretty much
the same.

scenarios suggests one or the other but we code it the ‘right’ way

To a point. Â But not much. Â Do The Simplest Thing That Could Possibly
Work is an important principle.

Consider, for example, text formatting. If I want a bit of text
highlighted the STTCPW would be to use tags. It is more complex
to use css. So why do we use CSS? The scenarios do not require it,
but we know that it will be easier to maintain. Similary DRY is often
not the simplest way to do something. It is simpler to cut and paste
a bit of code rather than extracting it into a method. The same could
be said, I think, about Unobtrusive Javascript. These are all design
concepts that are intended to improve flexibility of the code, reduce
bugs, make the app more easy to understand and maintain and so on.

Don’t bend over backwards to
generalize; let the generalizations emerge.

Agreed, but there is nothing wrong with standing up and looking around
to check there is not a better solution nearby.

and is less likely to have unnoticed
bugs.

That’s what tests are for.

Hmm, did you really mean that? Tests cannot ever cover every
possibility, some bugs will get through. Coding so as to minimise the
likelihood of bugs is worthwhile. Also, even if the tests do point
out a bug, we have still wasted effort fixing it which would have been
saved if we had not introduced the bug in the first place.

 I think these ideas also apply to the larger scale design of
the app, including the models and relationships. Â The overall design
can be aesthetically pleasing, or even a thing of beauty (I know, OTT
again, sorry). Â The scenarios do not address that aspect of the
design, only the designer can do that.

And the user will not care one iota about all that beauty. Â It, in and
of itself, adds no value for him at all.

No, but it increases my job satisfaction, and if it does not cost the
customer anything then everyone is happy.

The only thing adding value for the user here is that the beautiful code
makes the app easier to maintain – that is, to extend functionality
– that is, to do things that do add value for the user.

To reiterate: there is no user value at all in elegant code, except
insofar as the elegance makes future development easier. Â There is
developer value, but no user value.

The fact that the elegance makes future development easier is of
value to the user as it will keep his future costs down. He may, or
may not, appreciate this but it is still true. It also adds value for
me as it will assist me in meeting future targets (in the in-house
case) or allow tendering at a lower cost (or higher profit) in the
contract case.

us satisfaction in the design as discussed above.

Since we don’t know what the further phases will be, we can’t design for
them. Â Period. Â You’re deluding yourself into premature generalization,
and apparently somehow think that your clients care what the source code
looks like.

I am not talking about generalisation, but basing the model
identification on those aspects of the problem domain that are least
likely to change. That is not a more general solution than purely
looking at the details of the scenarios and coming up with a set of
models that solves the problem but may not be based on those aspects
of the problem domain that is least likely to change. Though I
suspect that 90% of the time there will be little difference between
the two approaches.

and refactor for tomorrow’s requirements when you know what they are.
It is not gueswork, just a matter of mapping the problem domain
objects (where appropriate) to the models.

I think now our ideas are starting to diverge. Â My initial assumption
would be that there will be user and product classes because they
are domain objects (unless the scenarios show that they do not
actually exist in the app).

That would be my initial assumption as well when I start to implement,
but that’s because I follow such a programming style in general.
Apparently not everybody does.

I am not sure what we are arguing about then, we appear to be in
complete agreement. :slight_smile:

[…]

This is an implementation detail, and as such
it is irrelevant right up till the moment we start implementing.

I am not sure what you mean here.

I mean that the nature our object model should be of no concern to us at
all till the moment we start to write actual code.

Surely you have a phase where you sit back and consider the models and
their relationships before you start typing?

But that is the point, if the domain objects and program objects map
onto each other closely,

Which there is no guarantee that they will.

I believe that they should.

(There was an interesting
post from Jim Coplien a while back where he said that very few bank
systems actually have any sort of Account object internally, even though
there’s a business concept of an account.)

I can’t seem to find that. Assuming it is correct I wonder why that
is. It would certainly not be my starting point. In addition just
because it is true does not mean that it is ideal. Are banking
systems renowned for their good design or are they a hotchpotch of
legacy systems lashed together over the decades to more or less work?

then since the domain objects tend not to
change dramatically the program objects will also not change
dramatically (though their behaviour will be added to and modified of
course.

Behavior is most of what program objects are about. Â That’s not really
true of domain objects. Â I guess – and I hadn’t realized this before –
that in that sense, the two are somewhat incommensurable.

Can you give examples of this? I am not sure what you mean.

But that’s not even true. �It assumes a degree of clairvoyance regarding
the future directions the project will take that we do not generally
possess.

Again, by mapping domain objects closely to program objects then
clairvoyance is not required as domain objects tend to be stable.

Really? Â What happens when your client’s business model changes?

I did not say they never change, only that they tend to be stable.
Plus I am only talking about domain objects that appear in the problem
domain. If these change then I would expect the scenarios to change.

Or

when you discover domain objects your client didn’t know existed? Â (Not
so far-fetched; see http://c2.com/cgi/wiki?WhatIsAnAdvancer for a
real-world example.)

That is not a problem, it is immaterial who identifies the existence
of the objects.

Colin

Colin L. wrote in post #947005:

On 8 October 2010 21:58, Marnen Laibow-Koser [email protected]
wrote:

functionality of the current phase of development.

Which, at any given time, is all we care about.

My turn to say No! I agree that one should not do extra work to add
features that may never be required, but where choices exist that do
not add extra work then the design should be so as to provide the best
base for future extension and modification.

To the extent that we know the direction of future extension and
modification, I agree with you. However, my experience is that we
almost never do know that, so any work spent “future-proofing” now is
likely to be wasted.

In my experienced, the best future-proofing we can do is to write
maintainable code, and to refactor it as necessary so it stays that
way. After a few refactorings, the necessary generalizations will
emerge.

internals.

It’s to the developer’s advantage to structure the application so that
adding more value for the user will be as easy as possible – hence good
development practices – but the user sees and cares about none of this.

Don’t kid yourself that the user has any reason to care about what goes
on under the hood, as long as the application works as specified.

My experience does not match this. Most of my work has been in-house
developments where the customer and myself are the same company.

No. The customer is some specific department of that company –
probably one where the staff’s jobs don’t involve going through code.

In
my case management has been keen to ensure that the code base should
be well designed in order to minimise future costs.

Well, of course, but management generally has no way of verifying that
beyond asking the developers if they are following good practice.

Perhaps in the
case of contract work things are different.

It has really nothing to do with whether the work is free-lance. On
both my free-lance and (at least my current) office jobs, the customer
(my direct client in the former case; marketing, project management,
editorial, and finance people in the latter) is not particularly
technically minded. They wouldn’t know the difference between good and
bad Ruby code.

That’s why I have a job. If my customers were knowledgeable enough to
find out for themselves anything useful about the quality of the code,
they wouldn’t need me to write it!

I find it surprising
though that a customer would not be at all interested in this.

I find it surprising that a customer would have the necessary knowledge
to get any useful information from that interest.

Perhaps I should not be surprised however.

Again I will quibble, slightly tongue in cheek, though not entirely.
The purpose of the code is to provide the implementation, as you
state, however the process of developing the application has other
purposes. Â Notably to provide us with a living wage and job
satisfaction.

That adds value for the developer, not for the user. Â If all we care
about is running up the billable hours, there are lots of ways to do
that – and not all of them involve adding value for the user – and
soon the user will realize this and find a developer who can actually
add value for him.

Oh no, you completely misunderstand me, I was not suggesting in any
way ‘running up billable hours’.

Nor was I. I was saying that if we confuse our goal (making money) with
the client’s goal (having a usable application), then we make poor
decisions.

[…]

Your user’s goals are not your goals.

To a great extent I think you are wrong here. At first sight you
might say that my principle goals are to make a living and achieve job
satisfaction. However the best way to achieve that is to provide the
best product to the user with the minimum effort (always a compromise
of course) and hence minimum cost.

No, the best way to make money is to provide product with minimum effort
and maximum cost. (Minimum effort does not always translate to minimum
cost.)

Of course, neither you nor I would do that – we have too much pride in
our work. I suppose that’s where the job satisfaction comes in.

The Users goal is to receive the
best product for the minimum cost. Hence the goals are pretty much
the same.

No. You’ve found a pretty good way of aligning them – of giving
yourself incentive to meet the client’s goals – but the client’s goals
are different from yours.

That doesn’t mean I don’t see my client as a partner in the development
process, or that I don’t see my job as being the satisfaction of the
client’s dreams. Of course I do. But that’s a little different.

scenarios suggests one or the other but we code it the ‘right’ way

To a point. Â But not much. Â Do The Simplest Thing That Could Possibly
Work is an important principle.

Consider, for example, text formatting. If I want a bit of text
highlighted the STTCPW would be to use tags. It is more complex
to use css.

Arguable.

So why do we use CSS? The scenarios do not require it,
but we know that it will be easier to maintain.

CSS is not about maintainability. It is about separating logical
structure of the document from presentation.

Similary DRY is often
not the simplest way to do something. It is simpler to cut and paste
a bit of code rather than extracting it into a method.

Yes it is, and so I usually start with cutting and pasting to get tests
to pass. Then – and usually only then – do I refactor to remove the
duplication.

An oft-quoted set of steps:

  1. Make it work.
  2. Make it right.
  3. Make it fast.
    Do them in that order.

The same could
be said, I think, about Unobtrusive Javascript.

No again. This is about document structuring same as CSS, though in
this case some DRY is involved.

These are all design
concepts that are intended to improve flexibility of the code, reduce
bugs, make the app more easy to understand and maintain and so on.

Do The Simplest Thing doesn’t mean that you throw knowledge of good
practice out the window. And the definition of “simple” is often
unclear. There’s nothing simple about maintaining 24 copies of the same
function.

Don’t bend over backwards to
generalize; let the generalizations emerge.

Agreed, but there is nothing wrong with standing up and looking around
to check there is not a better solution nearby.

Right.

and is less likely to have unnoticed
bugs.

That’s what tests are for.

Hmm, did you really mean that?

Yes.

Tests cannot ever cover every
possibility,

True, but somewhat orthogonal to the issue.

some bugs will get through.

And when they do, you write more tests.

Coding so as to minimise the
likelihood of bugs is worthwhile.

What do you mean by that? I certainly don’t code that way as such.

I write code that I can read.
I write code that I believe will be maintainable.
I write code to pass my tests.

I think those three factors, taken together, minimize the likelihood of
bugs, but I don’t feel like I’m taking that as an explicit goal when I
write code. Why rely on likelihood when your tests will establish
certainty (at least in the areas they cover)?

Also, even if the tests do point
out a bug, we have still wasted effort fixing it which would have been
saved if we had not introduced the bug in the first place.

That’s an old, old fallacy. Of course you shouldn’t be sloppy, but you
can’t always get things right the first time. That’s why we have tests
and iterative methodologies. Particularly in uncharted territory,
sometimes we have to see how things go wrong in order to make them
right.

If we were doing formal methods and proof-carrying code, this would be
somewhat less so. But unfortunately, we’re not.

 I think these ideas also apply to the larger scale design of
the app, including the models and relationships. Â The overall design
can be aesthetically pleasing, or even a thing of beauty (I know, OTT
again, sorry). Â The scenarios do not address that aspect of the
design, only the designer can do that.

And the user will not care one iota about all that beauty. Â It, in and
of itself, adds no value for him at all.

No, but it increases my job satisfaction, and if it does not cost the
customer anything then everyone is happy.

Right. Just don’t pretend that it means anything to the client, except
insofar as it makes use of the app or future development easier.

The only thing adding value for the user here is that the beautiful code
makes the app easier to maintain – that is, to extend functionality
– that is, to do things that do add value for the user.

To reiterate: there is no user value at all in elegant code, except
insofar as the elegance makes future development easier. Â There is
developer value, but no user value.

The fact that the elegance makes future development easier is of
value to the user as it will keep his future costs down. He may, or
may not, appreciate this but it is still true.

Generally so.

It also adds value for
me as it will assist me in meeting future targets (in the in-house
case) or allow tendering at a lower cost (or higher profit) in the
contract case.

That may actually decrease value for you, if it means that your paycheck
won’t be as high. :slight_smile:

us satisfaction in the design as discussed above.

Since we don’t know what the further phases will be, we can’t design for
them. Â Period. Â You’re deluding yourself into premature generalization,
and apparently somehow think that your clients care what the source code
looks like.

I am not talking about generalisation, but basing the model
identification on those aspects of the problem domain that are least
likely to change.

But you can’t really know which aspects those will be. You’re heading
straight into premature generalization.

That is not a more general solution

Right – it’s just a more time-consuming one, and if you guess wrong,
the extra effort is wasted. Why do it?

than purely
looking at the details of the scenarios and coming up with a set of
models that solves the problem but may not be based on those aspects
of the problem domain that is least likely to change.

I don’t care (much) what will change in the future. I care what works
today, not after the completion of the Seventeenth Five-Year Plan. :slight_smile:

suspect that 90% of the time there will be little difference between
the two approaches.

and refactor for tomorrow’s requirements when you know what they are.
It is not gueswork, just a matter of mapping the problem domain
objects (where appropriate) to the models.

I think now our ideas are starting to diverge. Â My initial assumption
would be that there will be user and product classes because they
are domain objects (unless the scenarios show that they do not
actually exist in the app).

That would be my initial assumption as well when I start to implement,
but that’s because I follow such a programming style in general.
Apparently not everybody does.

I am not sure what we are arguing about then, we appear to be in
complete agreement. :slight_smile:

[…]

This is an implementation detail, and as such
it is irrelevant right up till the moment we start implementing.

I am not sure what you mean here.

I mean that the nature our object model should be of no concern to us at
all till the moment we start to write actual code.

Surely you have a phase where you sit back and consider the models and
their relationships before you start typing?

Yes – about 30 seconds before I start typing.

But that is the point, if the domain objects and program objects map
onto each other closely,

Which there is no guarantee that they will.

I believe that they should.

(There was an interesting
post from Jim Coplien a while back where he said that very few bank
systems actually have any sort of Account object internally, even though
there’s a business concept of an account.)

I can’t seem to find that.

http://www.ruby-forum.com/topic/203844

Assuming it is correct I wonder why that
is. It would certainly not be my starting point. In addition just
because it is true does not mean that it is ideal. Are banking
systems renowned for their good design or are they a hotchpotch of
legacy systems lashed together over the decades to more or less work?

He seemed to be quoting them as good design, and I gather that he knows
what he’s talking about.

then since the domain objects tend not to
change dramatically the program objects will also not change
dramatically (though their behaviour will be added to and modified of
course.

Behavior is most of what program objects are about. Â That’s not really
true of domain objects. Â I guess – and I hadn’t realized this before –
that in that sense, the two are somewhat incommensurable.

Can you give examples of this? I am not sure what you mean.

Let me try to come up with some concrete examples.

But that’s not even true. �It assumes a degree of clairvoyance regarding
the future directions the project will take that we do not generally
possess.

Again, by mapping domain objects closely to program objects then
clairvoyance is not required as domain objects tend to be stable.

Really? Â What happens when your client’s business model changes?

I did not say they never change, only that they tend to be stable.
Plus I am only talking about domain objects that appear in the problem
domain. If these change then I would expect the scenarios to change.

Right – and you don’t know in what direction.

Or

when you discover domain objects your client didn’t know existed? Â (Not
so far-fetched; see http://c2.com/cgi/wiki?WhatIsAnAdvancer for a
real-world example.)

That is not a problem, it is immaterial who identifies the existence
of the objects.

Right – but it means you may have domain objects that neither you nor
your client even know exist! Advancers only emerged from refactoring 2
years into the project; if the WyCash project had not been amenable to
refactoring their object model, they’d have missed the existence of
advancers entirely (or so they say).

Colin

Best,

Marnen Laibow-Koser
http://www.marnen.org
[email protected]