Thinking about optional parameters and optional object elements

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Thinking about optional parameters and optional object elements

4D Tech mailing list
Like everybody, I tend to develop habits/patterns/templates for my methods.
There are lots of benefits to consisincy:

-- If it worked before, it will work again.
-- It's a lot faster to do what you know rather than thinking everything
through from scratch each time.
-- Old methods look totally understandable, even after a long time.

So, I tend to name things pretty consitently, organize my methods in a
couple of basic ways and handle parameters in a particlar way.

But it's good to revisit old choices now and then and see if there's a
better way. Not long ago, I was reading some materials arguing aginst
optional parmeters. Not much after that, Rob Laveaux made a comment
(paraphrasing here) about initializing objects with *all* elements. In ther
words, create a C_OBJECT and populate it with all elements right away (even
if blank or default values) so that the rest of your code never has to
worry if the element exists or not. It does. All of this got me thinking
about these similar subjects: optional method parameters and optional
object elements. I thought I'd toss out a few words and see what other
people think and might offer. I'm in that brief period when I'm being open
minded about something. Soon I'll make some deciscions, and then I'll
probably stick with them for a few years. (Like most people, I'm right all
the time...but what I think is right does change down the years. Earlier
David Adams? What an idiot. Now I'm finally right...)

Anyway, I like explicit parameters, so I'm not down with pushing everything
into an object - I'm definitely not trying to start that discussion. But I
do tend to keep param lists short. Here's an imaginary example of a method
that takes 2-3 parameters:

MyWonderfulMethod(->[Table]Foo;5)
MyWonderfulMethod(->[Table]Foo;5;Current date)

$3 is optional:

$table_pointer:=$1
$day_count:=$2
If (count parameters>=3)
   $date:=$3
Else
   $date:=Current date
End if

I set this kind of code up *automatically*. I find that I'm going it for
methods that are only called from one or two places. Why? It makes no
sense. Somewhere down the line something in me decided that every parameter
made my life worse in some big way that was worth a lot of effort to avoid.
So it's been my custom to make as many parameters optional as possible.
Looking back, I think I made a mistake. Yes, it makes it easier to call a
method if there are fewer parameters, but how much easier? Well, when there
are only a few parameters, it's not really much of a gain. For long
parameter lists, sure...but if I've got 6+ parameters, I might want to take
another look at how I'm setting up the code.

Okay, now what about the *costs* of optional parameters? There are several:

-- The code inside the method is more complex, both for assignments and
testing
-- The code is harder to read and rewrite because it's more complex
-- It's harder to scan for missing parameters.

So I'm being bold and making more explicit parameters and fewer optional
ones.

With that said, sometimes I've ended up with optional parameters because a
routine has various options. In that case, it is pretty nice to have an
options object:

C_OBJECT($options_object)
$options_object:=MakeMyWonderfulOptionsObject
OB SET($options_object;"capitalize_words";True)
MyWonderfulMethod(->[Table]Foo;5;Current date;$options_object)

This can be really helpful when there are several options. Speaking of
several options, back to Rob's point (or what I took from what he said
anyway.) Yeah, I'm 100% down with creating the object with all elements
defined. Leaving out situations where this makes no sense at all (you know
who you are), it's a great way to move forward. You create a method to
define your object (thinking of each C_OBJECT of this sort as a "type") and
then you always know that the elements you need are in place. You can
assign default values at the same time, which is handy. If you need to
add/remove/rename elements, you know right where you go to do it.

Also speaking of objects: Use custom constants for element names! For those
of you with access to current tech notes, there's a newish one that I wrote
up with Cannon Smith with lots of details and handy code from Cannon (so
you know it's good) to manage constants entirely within code. Jim Dorrance
has also kindly posted custom constants code here in the past, so that's in
the archives. Kirk Brooks often mentions using custom constants for his
element names, so he may have a few thoughts too.

Managing Custom Constants with Code
http://kb.4d.com/assetid=77806

Anyway, back to objects...as many of you know from you're work, they're
quite handy for storing data that is used through multiple methods to
complete a task. Done right, this can greatly reduce parameter list lengths
without compromising the ability to test your code and without necessarily
adding undue complexity to your methods.

So, open to thoughts and suggestions...but only briefly ;-)
**********************************************************************
4D Internet Users Group (4D iNUG)
FAQ:  http://lists.4d.com/faqnug.html
Archive:  http://lists.4d.com/archives.html
Options: http://lists.4d.com/mailman/options/4d_tech
Unsub:  mailto:[hidden email]
**********************************************************************
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Thinking about optional parameters and optional object elements

4D Tech mailing list
David,

If I understood your thoughts right, which is no guarantee at all ;), I believe you are proposing replacing a method call like:

   MyMethodWithOptionals(p1, p2, p3, p4)
or
   MyMethodWithOptionals(p1, p2, p3, p4, p5, p6,p7)

where parameters 1-3 are mandatory and 4-7 optional, by something like:

   c_Object($options)
   OB SET($options;”o4”;p4;”o5”;”";”o6”;”";”o7”;”")
   MyMethodWithOptionals(p1, p2, p3, $options)
or
   c_Object($options)
   OB SET($options;”o4”;p4;”o5”;p5;”o6”;p6;”o7”;p7)
   MyMethodWithOptionals(p1, p2, p3, $options)


If that is what you are implying, I do not see the benefit of doing it.
I does not really makes your code clear (my opinion), it is not faster, it does not really make it easier to call the method. And it looks awful to me, again my opinion.

So, please correct me if I’m wrong, but I do not see the point of going that way :-(

cheers,
julio

> On Jul 31, 2017, at 7:49 PM, David Adams via 4D_Tech <[hidden email]> wrote:
>
> Like everybody, I tend to develop habits/patterns/templates for my methods.
> There are lots of benefits to consisincy:
>
> -- If it worked before, it will work again.
> -- It's a lot faster to do what you know rather than thinking everything
> through from scratch each time.
> -- Old methods look totally understandable, even after a long time.
>
> So, I tend to name things pretty consitently, organize my methods in a
> couple of basic ways and handle parameters in a particlar way.
>
> But it's good to revisit old choices now and then and see if there's a
> better way. Not long ago, I was reading some materials arguing aginst
> optional parmeters. Not much after that, Rob Laveaux made a comment
> (paraphrasing here) about initializing objects with *all* elements. In ther
> words, create a C_OBJECT and populate it with all elements right away (even
> if blank or default values) so that the rest of your code never has to
> worry if the element exists or not. It does. All of this got me thinking
> about these similar subjects: optional method parameters and optional
> object elements. I thought I'd toss out a few words and see what other
> people think and might offer. I'm in that brief period when I'm being open
> minded about something. Soon I'll make some deciscions, and then I'll
> probably stick with them for a few years. (Like most people, I'm right all
> the time...but what I think is right does change down the years. Earlier
> David Adams? What an idiot. Now I'm finally right...)
>
> Anyway, I like explicit parameters, so I'm not down with pushing everything
> into an object - I'm definitely not trying to start that discussion. But I
> do tend to keep param lists short. Here's an imaginary example of a method
> that takes 2-3 parameters:
>
> MyWonderfulMethod(->[Table]Foo;5)
> MyWonderfulMethod(->[Table]Foo;5;Current date)
>
> $3 is optional:
>
> $table_pointer:=$1
> $day_count:=$2
> If (count parameters>=3)
>   $date:=$3
> Else
>   $date:=Current date
> End if
>
> I set this kind of code up *automatically*. I find that I'm going it for
> methods that are only called from one or two places. Why? It makes no
> sense. Somewhere down the line something in me decided that every parameter
> made my life worse in some big way that was worth a lot of effort to avoid.
> So it's been my custom to make as many parameters optional as possible.
> Looking back, I think I made a mistake. Yes, it makes it easier to call a
> method if there are fewer parameters, but how much easier? Well, when there
> are only a few parameters, it's not really much of a gain. For long
> parameter lists, sure...but if I've got 6+ parameters, I might want to take
> another look at how I'm setting up the code.
>
> Okay, now what about the *costs* of optional parameters? There are several:
>
> -- The code inside the method is more complex, both for assignments and
> testing
> -- The code is harder to read and rewrite because it's more complex
> -- It's harder to scan for missing parameters.
>
> So I'm being bold and making more explicit parameters and fewer optional
> ones.
>
> With that said, sometimes I've ended up with optional parameters because a
> routine has various options. In that case, it is pretty nice to have an
> options object:
>
> C_OBJECT($options_object)
> $options_object:=MakeMyWonderfulOptionsObject
> OB SET($options_object;"capitalize_words";True)
> MyWonderfulMethod(->[Table]Foo;5;Current date;$options_object)
>
> This can be really helpful when there are several options. Speaking of
> several options, back to Rob's point (or what I took from what he said
> anyway.) Yeah, I'm 100% down with creating the object with all elements
> defined. Leaving out situations where this makes no sense at all (you know
> who you are), it's a great way to move forward. You create a method to
> define your object (thinking of each C_OBJECT of this sort as a "type") and
> then you always know that the elements you need are in place. You can
> assign default values at the same time, which is handy. If you need to
> add/remove/rename elements, you know right where you go to do it.
>
> Also speaking of objects: Use custom constants for element names! For those
> of you with access to current tech notes, there's a newish one that I wrote
> up with Cannon Smith with lots of details and handy code from Cannon (so
> you know it's good) to manage constants entirely within code. Jim Dorrance
> has also kindly posted custom constants code here in the past, so that's in
> the archives. Kirk Brooks often mentions using custom constants for his
> element names, so he may have a few thoughts too.
>
> Managing Custom Constants with Code
> http://kb.4d.com/assetid=77806
>
> Anyway, back to objects...as many of you know from you're work, they're
> quite handy for storing data that is used through multiple methods to
> complete a task. Done right, this can greatly reduce parameter list lengths
> without compromising the ability to test your code and without necessarily
> adding undue complexity to your methods.
>
> So, open to thoughts and suggestions...but only briefly ;-)
> **********************************************************************
> 4D Internet Users Group (4D iNUG)
> FAQ:  http://lists.4d.com/faqnug.html
> Archive:  http://lists.4d.com/archives.html
> Options: http://lists.4d.com/mailman/options/4d_tech
> Unsub:  mailto:[hidden email]
> **********************************************************************

--
Julio Carneiro
[hidden email]



**********************************************************************
4D Internet Users Group (4D iNUG)
FAQ:  http://lists.4d.com/faqnug.html
Archive:  http://lists.4d.com/archives.html
Options: http://lists.4d.com/mailman/options/4d_tech
Unsub:  mailto:[hidden email]
**********************************************************************
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Thinking about optional parameters and optional object elements

4D Tech mailing list
Julio,

I'm sure that you hate what I'm saying in the nicest possible way ;-)

I think that you more-or-less got what I was saying, although a bit less
ugly that. This sort of code is really horrible in every way:

   OB SET($options;”o4”;p4;”o5”;”";”o6”;”";”o7”;”")   or
   MyMedioreMethod(->[Table];5;Current date;"";"";0;5)

So, agreed, that's just nasty.

Mostly thinking things through...I may land right back where I've been for
years with optional parameters, but sometimes it is helpful to revisit old
habits. For object creation in general, I'm definitely all in on
initializing objects with a standard structure all in one go.
(Acknowledging that there are likely to be cases where the structure isn't
standard and it would be counter-productive to insist on a standard format.)

I don't default to using options objects, that's for sure. I'm a pretty big
believer in clearly named and specific parameters as they make your
intentions clear at a glance:

GetSum($table_pointer;$date_from;$date_to)

Can be replaced by

C_OBJECT($parameters_object)
// Insert everything here
GetSum($parameters_object)

Ugh:
GetSum($parameters_object)
GetSum($table_pointer;$date_from;$date_to)

#2 is a whole lot more informative in the code itself. For #1, you need to
look at the rest of the method or, more often, see the object at runtime.
(Often times information is flowing through a call chain and you might not
see the object assignments right next to the object being passed down the
chain.)

I do like option objects for otherwise nasty code like this:

   MyMedioreMethod(->[Table];5;Current date;"";"";0;5)

There are four optional parameters and only the last one is used - it's set
to 5. In this case, an options object is nice for a couple of reasons:

-- You only have to assign the value that you're interested in.
-- Under some conditions, the called routine can distinguish between
options that have been supplied and options that have not. With a fixed
parameter list, that's harder.

Does that all make you hate me less? ;-)

I'll tell you one thing I hate, those absurd and massive "parameter"
objects that are all-too common in JavaScript. I mean, they can get just
insanely large. Completely out of control...and odd in a language with a
very nice (as far as I can tell) closure implementation. Closures are
probably the thing that I like the most in JS (at this point...not far
enough along to say I won't find something I like even more.)
**********************************************************************
4D Internet Users Group (4D iNUG)
FAQ:  http://lists.4d.com/faqnug.html
Archive:  http://lists.4d.com/archives.html
Options: http://lists.4d.com/mailman/options/4d_tech
Unsub:  mailto:[hidden email]
**********************************************************************
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Thinking about optional parameters and optional object elements

4D Tech mailing list
Well, I might hate you less ;-) if instead of:
>
> MyMediocreMethod(->[Table];5;Current date;"";"";0;5)

We coud write something like:
> MyMediocreMethod(->[Table];5;Current date;{numofdays:5})
or
> MyMediocreMethod(->[Table];5;Current date;{startDay:0; numofdays:5})

If the optional parameters are identified in the call, then that makes it clearer to me.
Of course there are those cases you mentioned, where the optional parameters come from a call chain and it gets harder to identify exactly what is being fed to method.

Now, I’ll repeat one more time what I believe is missing from 4D’s object implementation: the ability to declare object structures and have compiler syntax check them.

Suppose you could have a way to declare (ignore the syntax, not proposing any syntax format here, just semantics):

      C_Structure(MyMediocreMethodOptions;c_text(“format”);c_text(“type”);c_longint(“startDay”);c_longint(“numOfDays”))

(please 4D, if you implement the above do not use my syntax, I’m just trying to convey an idea here)


Then, the calls above would become:
> MyMediocreMethod(->[Table];5;Current date;$options)

Where $options would be a “MyMediocreMethodOptions” type object. And the compiler could even validate code to populate MyMediocreMethodOptions variables.
So, using the new dot notation you’d have:
   $options.format = “utc”
be validated and
   $options.formato = “utc” /// error, bad attribute
   $options.format = 5 /// error, bad attribute value type


What I’m trying to say here is that just replacing optional parameters by a C_Object does not bring any benefit, at least to me :-)
The old David Adams code looks much better to me :-)

cheers,
--
Julio Carneiro
[hidden email]



**********************************************************************
4D Internet Users Group (4D iNUG)
FAQ:  http://lists.4d.com/faqnug.html
Archive:  http://lists.4d.com/archives.html
Options: http://lists.4d.com/mailman/options/4d_tech
Unsub:  mailto:[hidden email]
**********************************************************************
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Thinking about optional parameters and optional object elements

4D Tech mailing list
On Mon, Jul 31, 2017 at 1:44 PM, Julio Carneiro via 4D_Tech <
[hidden email]> wrote:


> We coud write something like:
> > MyMediocreMethod(->[Table];5;Current date;{numofdays:5})
> or
> > MyMediocreMethod(->[Table];5;Current date;{startDay:0; numofdays:5})
>

Yes, wouldn't that be nice :(

Now, I’ll repeat one more time what I believe is missing from 4D’s object
> implementation: the ability to declare object structures and have compiler
> syntax check them.
>

+1,000! I was fighting for structs for months over on the Forums before I
banished myself from there. As far as I can tell, all I did was annoy 4D
and waste my own time. But, yes, we absolutely need structs. It's a
50-year+ old feature and not having declarable, verifiable structures makes
it *incredibly* hard to write a lot of sensible things in 4D. I'll stop,
but you'e got my vote.  And, agreed, this is a task for the compiler - not
the runtime interpreter.

To date, I have gotten not one person at 4D to seemingly agree that what
I'm talking about is missing, is a problem, or matters. I just don't get
it. Presumably, they don't use 4D for serious work and spend their time in
languages with all kinds of nice tools.


> Where $options would be a “MyMediocreMethodOptions” type object. And the
> compiler could even validate code to populate MyMediocreMethodOptions
> variables.
>

New(). Exactly. Some months back I tried to write my own meta-syntax in 4D
and ultimately had to give up on that too because of the incomplete JSON
support. (I had written a version in V13 using NTK's JSON.) I could have
done it in XML but, honestly, I have to write my own  declarative syntax, a
parser for it, and then a New()/Create() engine and Validate() engine? And
then to do proper validation, I have to write a complete code parser &
scanner? (I got pretty far down that road too.) That's a lot of heavy
lifting for something every other language has build in (and then some.)

What I’m trying to say here is that just replacing optional parameters by a
> C_Object does not bring any benefit, at least to me :-)
> The old David Adams code looks much better to me :-)
>

Well, I think that _everyone_ can agree that he's an idiot, you can just
pick the version you think is an idiot. There are so many to choose from ;-)
**********************************************************************
4D Internet Users Group (4D iNUG)
FAQ:  http://lists.4d.com/faqnug.html
Archive:  http://lists.4d.com/archives.html
Options: http://lists.4d.com/mailman/options/4d_tech
Unsub:  mailto:[hidden email]
**********************************************************************
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Thinking about optional parameters and optional object elements

4D Tech mailing list
In reply to this post by 4D Tech mailing list
My use of optional paramters was motivated by wanting add new features to, or extract more information from existing methods.  I had to make sure that existing callers could still call those methods without having to pass anything extra.  The optional parameter could just be missing when not needed.

However, if the method were to one day accept a second additional parameter, the first additional parameter would need a value to indicate when it was "optional".  Unfortunately a * cannot be passed in the position of a LONGINT, for instance (like it can in 4D methods).  So, does 0 mean skip using this, or is 0 valid?

Here is where an Object can help.  An optional param can actually be missing.

Keith - CDI

> On Jul 31, 2017, at 1:49 PM, David Adams via 4D_Tech <[hidden email]> wrote:
>
> Like everybody, I tend to develop habits/patterns/templates for my methods.
> There are lots of benefits to consisincy:
>
> -- If it worked before, it will work again.
> -- It's a lot faster to do what you know rather than thinking everything
> through from scratch each time.
> -- Old methods look totally understandable, even after a long time.
>
> So, I tend to name things pretty consitently, organize my methods in a
> couple of basic ways and handle parameters in a particlar way.
>
> But it's good to revisit old choices now and then and see if there's a
> better way. Not long ago, I was reading some materials arguing aginst
> optional parmeters. Not much after that, Rob Laveaux made a comment
> (paraphrasing here) about initializing objects with *all* elements. In ther
> words, create a C_OBJECT and populate it with all elements right away (even
> if blank or default values) so that the rest of your code never has to
> worry if the element exists or not. It does. All of this got me thinking
> about these similar subjects: optional method parameters and optional
> object elements. I thought I'd toss out a few words and see what other
> people think and might offer. I'm in that brief period when I'm being open
> minded about something. Soon I'll make some deciscions, and then I'll
> probably stick with them for a few years. (Like most people, I'm right all
> the time...but what I think is right does change down the years. Earlier
> David Adams? What an idiot. Now I'm finally right...)
>
> Anyway, I like explicit parameters, so I'm not down with pushing everything
> into an object - I'm definitely not trying to start that discussion. But I
> do tend to keep param lists short. Here's an imaginary example of a method
> that takes 2-3 parameters:
>
> MyWonderfulMethod(->[Table]Foo;5)
> MyWonderfulMethod(->[Table]Foo;5;Current date)
>
> $3 is optional:
>
> $table_pointer:=$1
> $day_count:=$2
> If (count parameters>=3)
>   $date:=$3
> Else
>   $date:=Current date
> End if
>
> I set this kind of code up *automatically*. I find that I'm going it for
> methods that are only called from one or two places. Why? It makes no
> sense. Somewhere down the line something in me decided that every parameter
> made my life worse in some big way that was worth a lot of effort to avoid.
> So it's been my custom to make as many parameters optional as possible.
> Looking back, I think I made a mistake. Yes, it makes it easier to call a
> method if there are fewer parameters, but how much easier? Well, when there
> are only a few parameters, it's not really much of a gain. For long
> parameter lists, sure...but if I've got 6+ parameters, I might want to take
> another look at how I'm setting up the code.
>
> Okay, now what about the *costs* of optional parameters? There are several:
>
> -- The code inside the method is more complex, both for assignments and
> testing
> -- The code is harder to read and rewrite because it's more complex
> -- It's harder to scan for missing parameters.
>
> So I'm being bold and making more explicit parameters and fewer optional
> ones.
>
> With that said, sometimes I've ended up with optional parameters because a
> routine has various options. In that case, it is pretty nice to have an
> options object:
>
> C_OBJECT($options_object)
> $options_object:=MakeMyWonderfulOptionsObject
> OB SET($options_object;"capitalize_words";True)
> MyWonderfulMethod(->[Table]Foo;5;Current date;$options_object)
>
> This can be really helpful when there are several options. Speaking of
> several options, back to Rob's point (or what I took from what he said
> anyway.) Yeah, I'm 100% down with creating the object with all elements
> defined. Leaving out situations where this makes no sense at all (you know
> who you are), it's a great way to move forward. You create a method to
> define your object (thinking of each C_OBJECT of this sort as a "type") and
> then you always know that the elements you need are in place. You can
> assign default values at the same time, which is handy. If you need to
> add/remove/rename elements, you know right where you go to do it.
>
> Also speaking of objects: Use custom constants for element names! For those
> of you with access to current tech notes, there's a newish one that I wrote
> up with Cannon Smith with lots of details and handy code from Cannon (so
> you know it's good) to manage constants entirely within code. Jim Dorrance
> has also kindly posted custom constants code here in the past, so that's in
> the archives. Kirk Brooks often mentions using custom constants for his
> element names, so he may have a few thoughts too.
>
> Managing Custom Constants with Code
> http://kb.4d.com/assetid=77806
>
> Anyway, back to objects...as many of you know from you're work, they're
> quite handy for storing data that is used through multiple methods to
> complete a task. Done right, this can greatly reduce parameter list lengths
> without compromising the ability to test your code and without necessarily
> adding undue complexity to your methods.
>
> So, open to thoughts and suggestions...but only briefly ;-)
>

**********************************************************************
4D Internet Users Group (4D iNUG)
FAQ:  http://lists.4d.com/faqnug.html
Archive:  http://lists.4d.com/archives.html
Options: http://lists.4d.com/mailman/options/4d_tech
Unsub:  mailto:[hidden email]
**********************************************************************
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Thinking about optional parameters and optional object elements

4D Tech mailing list
In reply to this post by 4D Tech mailing list
Yes, yes, yes, yes, yes! structs are the single biggest thing I missed when coming to 4D from C; and I still miss them. Objects are not a substitute, nice and useful though they may be.

Jeremy


Jeremy Roussak
[hidden email]



> +1,000! I was fighting for structs for months over on the Forums before I
> banished myself from there. As far as I can tell, all I did was annoy 4D
> and waste my own time. But, yes, we absolutely need structs. It's a
> 50-year+ old feature and not having declarable, verifiable structures makes
> it *incredibly* hard to write a lot of sensible things in 4D. I'll stop,
> but you'e got my vote.  And, agreed, this is a task for the compiler - not
> the runtime interpreter.
**********************************************************************
4D Internet Users Group (4D iNUG)
FAQ:  http://lists.4d.com/faqnug.html
Archive:  http://lists.4d.com/archives.html
Options: http://lists.4d.com/mailman/options/4d_tech
Unsub:  mailto:[hidden email]
**********************************************************************
Loading...