By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
424,846 Members | 1,680 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 424,846 IT Pros & Developers. It's quick & easy.

Open question - leverage all features liberally, or be selective?

P: n/a
In a recent thread, RKC (correctly, I believe), took issue with my use of
multiple parameters in a Property Let procedure to pass dimensional
arguments on the basis that, although it works, it's not obvious how the
code works if you don't know the intricacies of the Property Let/Get
syntax. Likewise, I dislike (and code to minimize the use of) the VB/VBA
syntax of returning a value by referring to the function name as if it were
a variable because this is too similar to the syntax for a recusrive
function call. I had to do some experiments to find out for sure what
happens in all cases with or without the parentheses after the function
name (David Fenton points out that there is no technical ambiguity here,
but I think this is another case of needing arcane knowledge to read some
code, and it interferes with my refactoring practices).

So, although all the features of a system (Access/VBA in this case) were
put there to add some value, perhaps it is best to come up with development
strategies and idioms that make use of only certain subsets of features in
certain clear ways to end up with code that's simpler and easier to
maintain.

OK, Me Aculpa - that's not a question, that's a soap box. Still, opinions?

I guess the opposing argumnent would be that, when a feature of the system
or language provides something you need, why not leverage that right now
rather than take time thinking of a code-around or adding extra lines of
code to a procedure (such as dimentioning a return variable which actually
adds duplication of the return type spec) or skipping a dimensional
property Let at the expense of using a function syntax rather than the more
obvious array syntax to set a value in an indexed list property.

I guess the opposing argument sounds pretty good, too - hmm?

- Steve Jorgensen
Nov 12 '05
Share this Question
Share on Google+
55 Replies


P: n/a
On Thu, 18 Sep 2003 21:04:43 GMT, dX********@bway.net (David W. Fenton)
wrote:

....
Refactoring doesn't just have to be for old code that has become
messy, though. It can be an integral part of a development
process so that, if at any point, the project has to be dropped
for 2 weeks, the existing code is as clear and concise as it can
be for what it does so far.
That's a good goal, and really I don't see it that different from
what I'm doing, since I choose my structures on the front end to
try to get it closer to a state where it is clear.


What I'm talking about is a greater division of labor between the tasks of
making it work and making it right. You first make it work because now you
have a sense of accomplishment and and a scaffolding to work from. You aim
for the specific case because the next thing you'll do is factor out
duplication. If you have much code already, there will be duplication to
factor out. If there is not much code already, you will soon have new code
duplicating something here and can refactor it out then.

When duplication is factored out, generalization of the code magically
arises. When a 3rd case arises, it can use the refactored portion directly
because that is now the simplest implementation.

Now, it is starting to sink in (like mollasses into concrete <g>) how I've
been been somewhat incorrigible in this discussion. I do acknowledge that
there are frequent cases in which there is an -equal- amount of effort in
putting a piece of functionality in one place vs another, and why put it in
the one that's less likely to be useful later? And yes, if you already
know which one is more likely to be more flexible, why do it the other way
on purpose? Still, if you get one "wrong" through lack of knowledge or
through inadequate forward thinking, but you make the code clear and
straightforward enough before calling it done, it should be a trivial
matter to rearrange it when it needs to be more general later on.
....
That's why I'm saying out mechanical procedures probably don't
differ much, but I think changing the thought priorities has been
very helpful to me. Why clean this code? Because it's messy. If
it's clean, but doesn't handle every case I think it should
eventually be able to do, I leave it alone even if I think it's
easy. . . .


But you'd design it right the first time you encountered an
opportunity. Don't you do skeleton code with comments in places
where you know you're going to build something later but are not
implementing it yet? I do that all the time!


If it falls into the category of mere notes, sure. For one thing, putting
a clever idea down in black-and-white in a comment lets me forget about it
safe in the knowledge that the thought is preserved. More than half the
time, when I reread such notes, I discard them as "clever" which is why I
think it's better not to do these things as code up front.
. . . Why?

1. There's a finite chance that I'm wrong about it being easy,
and once I start, I won't want to let it go.
2. There's a finite chance that something will come along before
the other case is needed that the extra code I wrote simply makes
harder to figure out how to factor in (cart before the horse -
sofa in the room before I know where it's going).


I'm talking about building structure. If you build a building that
you are contemplating adding 10 stories to, you'd better build the
foundation to allow for it, even if the 10 stories are never added.


If you'll excuse the pun, I think the building model falls down. If code
is complex and hard to work with, it cannot be easily changed, and then it
-is- like a foundation that must be adequate at the beginning. If we can
make our code more clear and easy to modify, then "foundations" are less
applicable metaphors. We both agree code must be flexible, but I think
more of the flexibility should evolve by flexing it rather than by
pre-planning for every kind of flexing that is predictable.

....
Of course, once the code is written and works, then it's a
candidate for refactoring, but it would be well down my priority
list.


That used to be how I felt, but this is what is known as a
technical debt. If you have code that was not made as clear as it
could be when you were clear on how it worked, yuo have just cost
yourself extra time the next time you have to work with it. . . .


Or, you can follow the Larry Linson rule: Don't dink with working
code.


I have come to think this is wrong. Dink with working code so it evolves
to a state where it doesn't break when you dink with it. If you can write
test batches to prove this as you go, that's even better.

....
But, Steve, you'd never create your Person class, because you'd
never be able to justify all that work for no purpose, no? ;)


It would be justified as soon as I had the second or third use
case. I would refactor the code, and move most of it to the class
module.


So, I take it, then, that you already have a working Person class?
;)


Well, I haven't been coding this way very long, but as a matter of fact, I
do have a clsPerson in the newest project I'm working on. It was a very
big help in terms of keeping code simple.
Nov 12 '05 #51

P: n/a
rkc

"Steve Jorgensen" <no****@nospam.nospam> wrote in message
news:hd********************************@4ax.com...
On Thu, 18 Sep 2003 23:00:59 GMT, "rkc"
<rk*@yabba.dabba.do.rochester.rr.com> wrote:

"Steve Jorgensen" <no****@nospam.nospam> wrote in message
news:7c********************************@4ax.com.. .
On Thu, 18 Sep 2003 01:36:32 GMT, "rkc"
<rk*@yabba.dabba.do.rochester.rr.com> wrote: ...
I believe delegation and containment are two terms that mean the same

thing.You delegate a task to an object contained in another object.


Well, I think you got it right and wrong at the same time. Delegation and
containment are not the same thing since you can contain without
delegating. By delegating, I mean that you wrap functions from the
contained class in simple forwarding functions with identical signatures.
You "expose" the methods of the contained object.


O.K. You are right about that. There is a distinction between the two terms.
An object can contain other objects that are used without exposing calls
to their properties and methods to outside code.
Nov 12 '05 #52

P: n/a
rkc

"David W. Fenton" <dX********@bway.net> wrote in message
news:93*********************@24.168.128.78...
rk*@yabba.dabba.do.rochester.rr.com (rkc) wrote in
<A_********************@twister.nyroc.rr.com>: My final implementation ended up being based on a single form that
is dynamically changed when loaded, according to which type of
Person is being added. This means that the AddPerson subroutine
could have retained its dependency on the form dlgAddPerson without
breaking. However, by removing that dependency, I left myself the
*option* of adding a person from more than one location. Indeed,
after meeting with the client yesterday, it became pretty clear
that I am likely to need to create a more elaborate dialog for
adding a person because there is a less specific context in which
I'll be adding people than the two contexts I've already
implemented.


I understand all your decisions and the reasons for them. I find no
fault with any of them. There are a few issues I try to avoid. Optional
parameters driving decisions in a procedure is one of them.

Here's a first draft of a class based solution. The class depends on
any form being passed to it to include at a minumum FirstName and
and LastName properties. A SchoolID property if it is required. That
decision is made by the method called.

I'm not posting this because I think it's briiliant. It's just a different
approach. You and Steve are two of the few people in this ng that
are willing to expose the thought process behind what you do. I
learn as much, or more, from that as I do from a post describing how
to format a report.

I have a thick outer shell so if this blows, tell me why.

<clsAddPerson>

Option Compare Database
Option Explicit

Const sqlInsert = "INSERT INTO Persons (Columns) Values (Data);"
Private m_Values As String
Private m_Columns As String
Private m_Form As Access.Form

Public Function AddNewParent(frm As Access.Form)
'expects frm to include FirstName, LastName properties
Set m_Form = frm
Call BuildInsertStrings
Call AddNewPerson
End Function

Public Function AddNewStudent(frm As Access.Form)
'expects frm to include FirstName, LastName & SchoolID properties
Set m_Form = frm
Call BuildInsertStrings
Call AddSchoolIDToInsertStrings
Call AddNewPerson
End Function

Private Sub BuildInsertStrings()
With m_Form
'<!>add quotes to string values</!>
m_Values = "'" & !FirstName & "','" & !LastName & "'"
m_Columns = "FirstName, LastName"
End With
End Sub

Private Sub AddSchoolIDToInsertStrings()
With m_Form
m_Values = !SchoolID & "," & m_Values
m_Columns = "SchoolID," & m_Columns
End With
End Sub

Private Sub AddNewPerson()
Dim sql As String

sql = Replace(sqlInsert, "Columns", m_Columns)
sql = Replace(sql, "Data", m_Values)

MsgBox sql
'CurrentDb.Execute sql, dbFailOnError

End Sub

Private Sub Class_Terminate()
If Not m_Form Is Nothing Then
Set m_Form = Nothing
End If
End Sub

</clsAddPerson>


Nov 12 '05 #53

P: n/a
no****@nospam.nospam (Steve Jorgensen) wrote in
<h2********************************@4ax.com>:
On Thu, 18 Sep 2003 21:04:43 GMT, dX********@bway.net (David W.
Fenton) wrote:

...
Refactoring doesn't just have to be for old code that has become
messy, though. It can be an integral part of a development
process so that, if at any point, the project has to be dropped
for 2 weeks, the existing code is as clear and concise as it can
be for what it does so far.
That's a good goal, and really I don't see it that different from
what I'm doing, since I choose my structures on the front end to
try to get it closer to a state where it is clear.


What I'm talking about is a greater division of labor between the
tasks of making it work and making it right. You first make it
work because now you have a sense of accomplishment and and a
scaffolding to work from. You aim for the specific case because
the next thing you'll do is factor out duplication. If you have
much code already, there will be duplication to factor out. If
there is not much code already, you will soon have new code
duplicating something here and can refactor it out then.


I think this is a dumb way to do things, as it's pretty easy to not
use brute force techniques on the front end.
When duplication is factored out, generalization of the code
magically arises. When a 3rd case arises, it can use the
refactored portion directly because that is now the simplest
implementation.

Now, it is starting to sink in (like mollasses into concrete <g>)
how I've been been somewhat incorrigible in this discussion. I do
acknowledge that there are frequent cases in which there is an
-equal- amount of effort in putting a piece of functionality in
one place vs another, and why put it in the one that's less likely
to be useful later? And yes, if you already know which one is
more likely to be more flexible, why do it the other way on
purpose? Still, if you get one "wrong" through lack of knowledge
or through inadequate forward thinking, but you make the code
clear and straightforward enough before calling it done, it should
be a trivial matter to rearrange it when it needs to be more
general later on. ...
The practice I've been recommending is not in any way contradictory
of that goal.
That's why I'm saying out mechanical procedures probably don't
differ much, but I think changing the thought priorities has
been very helpful to me. Why clean this code? Because it's
messy. If it's clean, but doesn't handle every case I think it
should eventually be able to do, I leave it alone even if I
think it's easy. . . .


But you'd design it right the first time you encountered an
opportunity. Don't you do skeleton code with comments in places
where you know you're going to build something later but are not
implementing it yet? I do that all the time!


If it falls into the category of mere notes, sure. For one thing,
putting a clever idea down in black-and-white in a comment lets me
forget about it safe in the knowledge that the thought is
preserved. More than half the time, when I reread such notes, I
discard them as "clever" which is why I think it's better not to
do these things as code up front.


Well, some of it is code, some of it comments. The more the idea is
complete and necessary for the task at hand, the larger portion is
code and not comments.

Either way, it's designing *structure*, which is almost the only
thing I've been talking about in this discussion.
. . . Why?

1. There's a finite chance that I'm wrong about it being easy,
and once I start, I won't want to let it go.
2. There's a finite chance that something will come along
before the other case is needed that the extra code I wrote
simply makes harder to figure out how to factor in (cart before
the horse - sofa in the room before I know where it's going).


I'm talking about building structure. If you build a building
that you are contemplating adding 10 stories to, you'd better
build the foundation to allow for it, even if the 10 stories are
never added.


If you'll excuse the pun, I think the building model falls down.
If code is complex and hard to work with, it cannot be easily
changed, and then it -is- like a foundation that must be adequate
at the beginning. If we can make our code more clear and easy to
modify, then "foundations" are less applicable metaphors. We both
agree code must be flexible, but I think more of the flexibility
should evolve by flexing it rather than by pre-planning for every
kind of flexing that is predictable.


Why do you insist on casting my position as planning for "every"
eventuality? I've never suggested anything of the sort -- not even
close. I think you're being rather unfair in the way you're
treating my argument in that you always take an extreme case as
your reason for rejecting what I'm saying.

Some structures are simply de facto more flexible than others. The
example of the hardcoded form/control references is a perfect
instance of this. Doing it right doesn't take more time and it
produces better code. I'm arguing for thinking about that issue
before you start coding and doing what you can to make your code
modular and not dependent on the specifics of outside objects. That
is something you can do that makes the code more adaptable without
you're needing to know all the eventual contexts in which it will
be used.
...
Of course, once the code is written and works, then it's a
candidate for refactoring, but it would be well down my
priority list.

That used to be how I felt, but this is what is known as a
technical debt. If you have code that was not made as clear as
it could be when you were clear on how it worked, yuo have just
cost yourself extra time the next time you have to work with it.
. . .
Or, you can follow the Larry Linson rule: Don't dink with working
code.


I have come to think this is wrong. Dink with working code so it
evolves to a state where it doesn't break when you dink with it.
If you can write test batches to prove this as you go, that's even
better.


I don't have time to do that, myself.

And you're basically contradicting yourself here: I said that I
dink with it only when I need to change it, you're saying dink with
it in case you ever need to change it. What if you never need to do
that? Then you've wasted time refactoring code and you've got no
actual benefit from it, only potential benefit.

How is that different than me recommending that you take some time
to consider structure before writing code?
...
But, Steve, you'd never create your Person class, because you'd
never be able to justify all that work for no purpose, no? ;)

It would be justified as soon as I had the second or third use
case. I would refactor the code, and move most of it to the
class module.


So, I take it, then, that you already have a working Person
class? ;)


Well, I haven't been coding this way very long, but as a matter of
fact, I do have a clsPerson in the newest project I'm working on.
It was a very big help in terms of keeping code simple.


Damn. I thought I had you! :)

--
David W. Fenton http://www.bway.net/~dfenton
dfenton at bway dot net http://www.bway.net/~dfassoc
Nov 12 '05 #54

P: n/a
On Fri, 19 Sep 2003 11:26:11 GMT, "rkc"
<rk*@yabba.dabba.do.rochester.rr.com> wrote:

"David W. Fenton" <dX********@bway.net> wrote in message
news:93*********************@24.168.128.78...
rk*@yabba.dabba.do.rochester.rr.com (rkc) wrote in
<A_********************@twister.nyroc.rr.com>:

....I'm not posting this because I think it's briiliant. It's just a different
approach. You and Steve are two of the few people in this ng that
are willing to expose the thought process behind what you do. I
learn as much, or more, from that as I do from a post describing how
to format a report.


You were replying to David's post, but I assume you are asking for input
from both of us. I'll be happy to respond, but I'm rushing to get started
on a 4-day relaxation vacation, so a thourough reply will have to wait
until Tuesday.

First impression, like any code, there are things that could be improved,
but the code does not "blow".

The first problem I do notice is that you make the assumption that a name
may not contain an apostrophe character. Either the requirement should be
that a name may not contain an apostrophe, and you sould add an assertion
to generate an error if one does contain an apostrophe (even if there is a
constraint on the control, especially since this code is form-agnostic), or
you should make the code accept names with apostrophes correctly (probably
best since we know there are names like O'Connor, etc.).

Of course, one could write code to correctly escape the apostrophes, but
that would be duplicating code that already exists in DAO. If, instead,
you generate SQL strings containing parameters, use a temporary querydef to
execute the query, and pass the arguments to the querydef parameters, DAO
does all the work for you of making sure strings with special characters
are properly handled.
Nov 12 '05 #55

P: n/a
rkc

"Steve Jorgensen" <no****@nospam.nospam> wrote in message
news:mt********************************@4ax.com...
Of course, one could write code to correctly escape the apostrophes, but
that would be duplicating code that already exists in DAO. If, instead,
you generate SQL strings containing parameters, use a temporary querydef to execute the query, and pass the arguments to the querydef parameters, DAO
does all the work for you of making sure strings with special characters
are properly handled.


I appreciate that you are still interested enough to reply. Your comment
about the code I posted not dealing with apostrophes is valid and I
would hang my head in shame if what I posted was meant to be
production code. It was posted to illustrate an alternate approach to an
admittedly trivial need.

No matter. I was beating a dead horse. Moving on.


Nov 12 '05 #56

55 Replies

This discussion thread is closed

Replies have been disabled for this discussion.