Colin Law wrote in post #947005:
> On 8 October 2010 21:58, Marnen Laibow-Koser <li...@ruby-forum.com>
> 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 <b> 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. :)

>
>>> 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. :)

> 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. :)
>
>>
>> [...]
>>>> 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
mar...@marnen.org

-- 
Posted via http://www.ruby-forum.com/.

-- 
You received this message because you are subscribed to the Google Groups "Ruby 
on Rails: Talk" group.
To post to this group, send email to rubyonrails-t...@googlegroups.com.
To unsubscribe from this group, send email to 
rubyonrails-talk+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/rubyonrails-talk?hl=en.

Reply via email to