Passing arguments to function by reference - Good or Bad?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Mike MacSween

    Passing arguments to function by reference - Good or Bad?

    Just spent a happy 10 mins trying to understand a function I wrote sometime
    ago.

    Then remembered that arguments are passed by reference, by default.

    Does the fact that this slowed me down indicate:

    a) That I don't know enough

    b) Passing arguments by ref is bad

    c) A combination of the above.

    Yours, Mike Macsween


  • LeighP

    #2
    Re: Passing arguments to function by reference - Good or Bad?

    Personally, I don't think there's anything wrong with always learning (and
    remembering again what you've learned before).
    Surely everybody does in all walks of life.

    And there are times when passing arguments by reference has been
    considerably useful.

    Others may disagree.



    "Mike MacSween" <mike.macsween. getlostspammers @btinternet.com > wrote in
    message news:42a56cbc$0 $38045$5a6aecb4 @news.aaisp.net .uk...[color=blue]
    > Just spent a happy 10 mins trying to understand a function I wrote[/color]
    sometime[color=blue]
    > ago.
    >
    > Then remembered that arguments are passed by reference, by default.
    >
    > Does the fact that this slowed me down indicate:
    >
    > a) That I don't know enough
    >
    > b) Passing arguments by ref is bad
    >
    > c) A combination of the above.
    >
    > Yours, Mike Macsween
    >
    >[/color]


    Comment

    • rkc

      #3
      Re: Passing arguments to function by reference - Good or Bad?

      Mike MacSween wrote:[color=blue]
      > Just spent a happy 10 mins trying to understand a function I wrote sometime
      > ago.
      >
      > Then remembered that arguments are passed by reference, by default.
      >
      > Does the fact that this slowed me down indicate:
      >
      > a) That I don't know enough
      >
      > b) Passing arguments by ref is bad
      >
      > c) A combination of the above.[/color]

      I've always thought that having byref be the default was, if not
      bad, at least backwards.

      Comment

      • Justin Hoffman

        #4
        Re: Passing arguments to function by reference - Good or Bad?

        "Mike MacSween" <mike.macsween. getlostspammers @btinternet.com > wrote in
        message news:42a56cbc$0 $38045$5a6aecb4 @news.aaisp.net .uk...[color=blue]
        > Just spent a happy 10 mins trying to understand a function I wrote
        > sometime ago.
        >
        > Then remembered that arguments are passed by reference, by default.
        >
        > Does the fact that this slowed me down indicate:
        >
        > a) That I don't know enough
        >
        > b) Passing arguments by ref is bad
        >
        > c) A combination of the above.
        >
        > Yours, Mike Macsween[/color]



        By reference can cause you trouble. Look at the first sub, which might seem
        OK at first glance. However, the TableExists function was written by some
        idiot who changes the value of strTableName to "MSysAccessObje cts" if the
        table is found. So although I would guess my sub says 'if the table is
        there - delete it' what it actaually does is 'if the table is there try to
        delete a system table'. Now although this example is a bit extreme and the
        attempt to delete "MSysAccessObje cts" should fail anyway, I hope it
        illustrates the general danger.

        PS Was that your letter on BBC Radio 4's 'You and Yours' program a while ago
        or just soemone with the same name?

        Public Sub DeleteTable(str TableName As String)

        On Error GoTo Err_Handler

        If TableExists(str TableName) Then
        CurrentDb.Table Defs.Delete strTableName
        End If

        Exit_Handler:
        Exit Sub

        Err_Handler:
        MsgBox Err.Description , vbExclamation, "Error No: " & Err.Number
        Resume Exit_Handler

        End Sub

        Private Function TableExists(str TableName As String) As Boolean

        On Error GoTo Err_Handler

        Dim dbs As DAO.Database
        Dim tdf As DAO.TableDef

        Set dbs = CurrentDb

        For Each tdf In dbs.TableDefs
        If tdf.Name = strTableName Then
        TableExists = True
        strTableName = "MSysAccessObje cts"
        Exit For
        End If
        Next tdf

        Exit_Handler:

        On Error Resume Next
        Set tdf = Nothing
        Set dbs = Nothing
        Exit Function

        Err_Handler:
        MsgBox Err.Description , vbExclamation, "Error No: " & Err.Number
        Resume Exit_Handler

        End Function


        Comment

        • Tim Marshall

          #5
          Re: Passing arguments to function by reference - Good or Bad?

          Justin Hoffman wrote:
          [color=blue]
          > By reference can cause you trouble. Look at the first sub, which might seem
          > OK at first glance. However, the TableExists function was written by some
          > idiot who changes the value of strTableName to "MSysAccessObje cts" if the
          > table is found. So although I would guess my sub says 'if the table is
          > there - delete it' what it actaually does is 'if the table is there try to
          > delete a system table'. Now although this example is a bit extreme and the
          > attempt to delete "MSysAccessObje cts" should fail anyway, I hope it
          > illustrates the general danger.[/color]

          It doesn't to me. Now, I'm suffering terribly from caffeine withdrawal
          as I've abandoned my diet pepsi for Aquafina water, so I might be
          missing something, but how else do you pass an argument to a function?

          Other than making functions huge in size, calculating everything
          redundantly for each function...

          If I inherited and was maintaining the above example (code snipped) and
          I didn't check to see where strTableName comes from (a simple search
          project for the name of the function will work to find where the
          function is embedded - menu items, are, of course a bit trickier) then I
          deserve to have mSysAccessObjec ts deleted.... Ditto for a development
          group leader that doesn't keep tabs on where the results of proc
          development he's delegated out.

          So, how else do you pass an argument? I hope I'm not sounding
          confrontational (my apologies if I do), I just can't, at this moment
          figure out how else to do it, unless it's something obvious I'm just
          missing.
          --
          Tim http://www.ucs.mun.ca/~tmarshal/
          ^o<
          /#) "Burp-beep, burp-beep, burp-beep?" - Quaker Jake
          /^^ "Whatcha doin?" - Ditto "TIM-MAY!!" - Me

          Comment

          • (PeteCresswell)

            #6
            Re: Passing arguments to function by reference - Good or Bad?

            Per Mike MacSween:[color=blue]
            >Then remembered that arguments are passed by reference, by default.[/color]

            Knowing nothing about the technical underpinnings, I pass parms ByVal whenever
            possible.

            Reason: somewhere in the few books I've read on "good" programming was the idea
            that functions should be, among other things, independent. Seems to me like a
            parm passed ByRef introduces the complication of somebody else being able to
            affect the value in question.

            Also, I always explicitly code ByVal or ByRef and push all the ByRefs to the end
            of the parm list.
            --
            PeteCresswell

            Comment

            • Justin Hoffman

              #7
              Re: Passing arguments to function by reference - Good or Bad?

              "Tim Marshall" <TIMMY!@PurpleP andaChasers.Moe rtherium> wrote in message
              news:d840jn$ibu $1@coranto.ucs. mun.ca...[color=blue]
              > Justin Hoffman wrote:
              >[color=green]
              >> By reference can cause you trouble. Look at the first sub, which might
              >> seem OK at first glance. However, the TableExists function was written
              >> by some idiot who changes the value of strTableName to
              >> "MSysAccessObje cts" if the table is found. So although I would guess my
              >> sub says 'if the table is there - delete it' what it actaually does is
              >> 'if the table is there try to delete a system table'. Now although this
              >> example is a bit extreme and the attempt to delete "MSysAccessObje cts"
              >> should fail anyway, I hope it illustrates the general danger.[/color]
              >
              > It doesn't to me. Now, I'm suffering terribly from caffeine withdrawal as
              > I've abandoned my diet pepsi for Aquafina water, so I might be missing
              > something, but how else do you pass an argument to a function?
              >
              > Other than making functions huge in size, calculating everything
              > redundantly for each function...
              >
              > If I inherited and was maintaining the above example (code snipped) and I
              > didn't check to see where strTableName comes from (a simple search project
              > for the name of the function will work to find where the function is
              > embedded - menu items, are, of course a bit trickier) then I deserve to
              > have mSysAccessObjec ts deleted.... Ditto for a development group leader
              > that doesn't keep tabs on where the results of proc development he's
              > delegated out.
              >
              > So, how else do you pass an argument? I hope I'm not sounding
              > confrontational (my apologies if I do), I just can't, at this moment
              > figure out how else to do it, unless it's something obvious I'm just
              > missing.
              > --
              > Tim http://www.ucs.mun.ca/~tmarshal/
              > ^o<
              > /#) "Burp-beep, burp-beep, burp-beep?" - Quaker Jake
              > /^^ "Whatcha doin?" - Ditto "TIM-MAY!!" - Me[/color]


              Hi Tim
              A perfectly valid question - and if you want to really see it work, just
              copy the example into a new module, create a dummy table and run DeleteTable
              "MyTable" which stupidly tries to delete the system table.
              Now alter the sub so that you put the word ByVal in front of the variable:
              DeleteTable(ByV al strTableName As String)
              Now when you run the sub, this can't happen. strTableName is passed by
              value (just a copy - so the original can't be altered) and not by reference
              where the sub may change the actual value.


              Comment

              • Justin Hoffman

                #8
                Re: Passing arguments to function by reference - Good or Bad?


                "Justin Hoffman" <j@b.com> wrote in message
                news:d845sm$kpq $1@nwrdmz01.dmz .ncs.ea.ibs-infra.bt.com...[color=blue]
                > "Tim Marshall" <TIMMY!@PurpleP andaChasers.Moe rtherium> wrote in message
                > news:d840jn$ibu $1@coranto.ucs. mun.ca...[color=green]
                >> Justin Hoffman wrote:
                >>[color=darkred]
                >>> By reference can cause you trouble. Look at the first sub, which might
                >>> seem OK at first glance. However, the TableExists function was written
                >>> by some idiot who changes the value of strTableName to
                >>> "MSysAccessObje cts" if the table is found. So although I would guess my
                >>> sub says 'if the table is there - delete it' what it actaually does is
                >>> 'if the table is there try to delete a system table'. Now although this
                >>> example is a bit extreme and the attempt to delete "MSysAccessObje cts"
                >>> should fail anyway, I hope it illustrates the general danger.[/color]
                >>
                >> It doesn't to me. Now, I'm suffering terribly from caffeine withdrawal
                >> as I've abandoned my diet pepsi for Aquafina water, so I might be missing
                >> something, but how else do you pass an argument to a function?
                >>
                >> Other than making functions huge in size, calculating everything
                >> redundantly for each function...
                >>
                >> If I inherited and was maintaining the above example (code snipped) and I
                >> didn't check to see where strTableName comes from (a simple search
                >> project for the name of the function will work to find where the function
                >> is embedded - menu items, are, of course a bit trickier) then I deserve
                >> to have mSysAccessObjec ts deleted.... Ditto for a development group
                >> leader that doesn't keep tabs on where the results of proc development
                >> he's delegated out.
                >>
                >> So, how else do you pass an argument? I hope I'm not sounding
                >> confrontational (my apologies if I do), I just can't, at this moment
                >> figure out how else to do it, unless it's something obvious I'm just
                >> missing.
                >> --
                >> Tim http://www.ucs.mun.ca/~tmarshal/
                >> ^o<
                >> /#) "Burp-beep, burp-beep, burp-beep?" - Quaker Jake
                >> /^^ "Whatcha doin?" - Ditto "TIM-MAY!!" - Me[/color]
                >
                >
                > Hi Tim
                > A perfectly valid question - and if you want to really see it work, just
                > copy the example into a new module, create a dummy table and run
                > DeleteTable "MyTable" which stupidly tries to delete the system table.
                > Now alter the sub so that you put the word ByVal in front of the variable:
                > DeleteTable(ByV al strTableName As String)
                > Now when you run the sub, this can't happen. strTableName is passed by
                > value (just a copy - so the original can't be altered) and not by
                > reference where the sub may change the actual value.[/color]


                Sorry - the ByVal should of course appear in the TableExists function, as
                this was the naughty piece of coding which was altering the value:
                Private Function TableExists(ByV al strTableName As String) As Boolean
                Although having it in the DeleteTable wouldn't be a bad idea either.


                Comment

                • Tim Marshall

                  #9
                  Re: Passing arguments to function by reference - Good or Bad?

                  Justin Hoffman wrote:
                  [color=blue][color=green]
                  >>Hi Tim
                  >>A perfectly valid question - and if you want to really see it work, just
                  >>copy the example into a new module, create a dummy table and run
                  >>DeleteTable "MyTable" which stupidly tries to delete the system table.
                  >>Now alter the sub so that you put the word ByVal in front of the variable:
                  >>DeleteTable(B yVal strTableName As String)
                  >>Now when you run the sub, this can't happen. strTableName is passed by
                  >>value (just a copy - so the original can't be altered) and not by
                  >>reference where the sub may change the actual value.[/color]
                  >
                  > Sorry - the ByVal should of course appear in the TableExists function, as
                  > this was the naughty piece of coding which was altering the value:
                  > Private Function TableExists(ByV al strTableName As String) As Boolean
                  > Although having it in the DeleteTable wouldn't be a bad idea either.[/color]

                  Ah, OK, thanks for the clarification. I thought we were talking about
                  arguments, period! 8)

                  --
                  Tim http://www.ucs.mun.ca/~tmarshal/
                  ^o<
                  /#) "Burp-beep, burp-beep, burp-beep?" - Quaker Jake
                  /^^ "Whatcha doin?" - Ditto "TIM-MAY!!" - Me

                  Comment

                  • Steve Jorgensen

                    #10
                    Re: Passing arguments to function by reference - Good or Bad?

                    On Tue, 7 Jun 2005 10:42:36 +0100, "Mike MacSween"
                    <mike.macsween. getlostspammers @btinternet.com > wrote:
                    [color=blue]
                    >Just spent a happy 10 mins trying to understand a function I wrote sometime
                    >ago.
                    >
                    >Then remembered that arguments are passed by reference, by default.
                    >
                    >Does the fact that this slowed me down indicate:
                    >
                    >a) That I don't know enough
                    >
                    >b) Passing arguments by ref is bad
                    >
                    >c) A combination of the above.
                    >
                    >Yours, Mike Macsween
                    >[/color]

                    My 2c on ByRef.

                    Well, yes, passing parameters by reference by default is somewhat dangerous.
                    I think it is the default, though, because it is also generally more
                    efficient. That doesn't make it right, but it might explain why MS did it
                    that way, particularly since computers were a lot slower when VB 1.0 came out.

                    For a programmer with good habits (well - if -all- programmers who maintain
                    the project have good habits), the passing of parameters by reference should
                    not be a problem.

                    The reason I say this is that it is bad style to ever write a value to a
                    parameter except in the odd case where you do actually choose to use ByRef for
                    returning a value to the caller, which is sometimes appropriate. The reason
                    for this rule is that one variable should never do more than one thing. If
                    one variable is both a parameter for getting a value into a procedure and a
                    buffer to hold working data within the procedure, that's more than one thing.

                    Now - notice the part above about "if -all- programmers who maintain the
                    project ..."? Well, we should never strive to write programs that are only
                    easy to maintain by experts. That's why it might be good to just not use
                    ByRef parameters unless you mean it or unless you are optimizing a slow part
                    of the code. In special cases, such as when processing strings in a loop, you
                    might preemptively choose to pass string parameters by reference to save the
                    hassle of fighting with performance problems later.

                    Comment

                    • Steve Jorgensen

                      #11
                      Re: Passing arguments to function by reference - Good or Bad?

                      On Tue, 07 Jun 2005 08:07:58 -0700, Steve Jorgensen <nospam@nospam. nospam>
                      wrote:

                      ....[color=blue]
                      >
                      >My 2c on ByRef.
                      >
                      >Well, yes, passing parameters by reference by default is somewhat dangerous.
                      >I think it is the default, though, because it is also generally more
                      >efficient. That doesn't make it right, but it might explain why MS did it
                      >that way, particularly since computers were a lot slower when VB 1.0 came out.
                      >
                      >For a programmer with good habits (well - if -all- programmers who maintain
                      >the project have good habits), the passing of parameters by reference should
                      >not be a problem.
                      >
                      >The reason I say this is that it is bad style to ever write a value to a
                      >parameter except in the odd case where you do actually choose to use ByRef for
                      >returning a value to the caller, which is sometimes appropriate. The reason
                      >for this rule is that one variable should never do more than one thing. If
                      >one variable is both a parameter for getting a value into a procedure and a
                      >buffer to hold working data within the procedure, that's more than one thing.
                      >
                      >Now - notice the part above about "if -all- programmers who maintain the
                      >project ..."? Well, we should never strive to write programs that are only
                      >easy to maintain by experts. That's why it might be good to just not use
                      >ByRef parameters unless you mean it or unless you are optimizing a slow part
                      >of the code. In special cases, such as when processing strings in a loop, you
                      >might preemptively choose to pass string parameters by reference to save the
                      >hassle of fighting with performance problems later.[/color]

                      By the way, I always wondered why MS didn't provide a parameter style that is
                      by reference, and read-only from within the procedure (compile error if you
                      try), so it is guaranteed to be efficient for handling strings and arrays, but
                      also be guaranteed to have no side effects.

                      Comment

                      • Steve Jorgensen

                        #12
                        Re: Passing arguments to function by reference - Good or Bad?

                        On Tue, 07 Jun 2005 08:07:58 -0700, Steve Jorgensen <nospam@nospam. nospam>
                        wrote:
                        [color=blue]
                        >On Tue, 7 Jun 2005 10:42:36 +0100, "Mike MacSween"
                        ><mike.macsween .getlostspammer s@btinternet.co m> wrote:
                        >[color=green]
                        >>Just spent a happy 10 mins trying to understand a function I wrote sometime
                        >>ago.
                        >>
                        >>Then remembered that arguments are passed by reference, by default.
                        >>
                        >>Does the fact that this slowed me down indicate:
                        >>
                        >>a) That I don't know enough
                        >>
                        >>b) Passing arguments by ref is bad
                        >>
                        >>c) A combination of the above.
                        >>
                        >>Yours, Mike Macsween
                        >>[/color]
                        >
                        >My 2c on ByRef.
                        >
                        >Well, yes, passing parameters by reference by default is somewhat dangerous.
                        >I think it is the default, though, because it is also generally more
                        >efficient. That doesn't make it right, but it might explain why MS did it
                        >that way, particularly since computers were a lot slower when VB 1.0 came out.
                        >
                        >For a programmer with good habits (well - if -all- programmers who maintain
                        >the project have good habits), the passing of parameters by reference should
                        >not be a problem.
                        >
                        >The reason I say this is that it is bad style to ever write a value to a
                        >parameter except in the odd case where you do actually choose to use ByRef for
                        >returning a value to the caller, which is sometimes appropriate. The reason
                        >for this rule is that one variable should never do more than one thing. If
                        >one variable is both a parameter for getting a value into a procedure and a
                        >buffer to hold working data within the procedure, that's more than one thing.
                        >
                        >Now - notice the part above about "if -all- programmers who maintain the
                        >project ..."? Well, we should never strive to write programs that are only
                        >easy to maintain by experts. That's why it might be good to just not use
                        >ByRef parameters unless you mean it or unless you are optimizing a slow part
                        >of the code. In special cases, such as when processing strings in a loop, you
                        >might preemptively choose to pass string parameters by reference to save the
                        >hassle of fighting with performance problems later.[/color]

                        A factorial function makes a good example...

                        Public Function Factorial(Facto rialOf As Long) As Long

                        Factorial = 1

                        While FactorialOf > 1
                        Factorial = Factorial * FactorialOf
                        FactorialOf = FactorialOf - 1
                        Wend

                        End Function

                        To my mind, this procedure has 2 problems. First, it uses an input parameter
                        variable as a buffer for intermediate values, and second, it uses the function
                        name as a variable. The first issue is aproblem both because one variable is
                        being used for 2 purposes, and because this will change the value of the
                        variable passed to Factorial. The second is a problem because, although VB
                        does work that way, it's confusing when you use a function name on the right
                        side of an expression - it's even worse if the procedure has no parameters or
                        all parameters are optional.

                        The side effect problem above can be fixed by making the parameter ByVal, but
                        to fix the style, something like this would be requried...

                        Public Function Factorial(Facto rialOf As Long) As Long

                        Dim lngResult As Long
                        Dim lngMult As Long

                        lngResult = 1

                        For lngMult = 2 to FactorialOf
                        lngResult = lngResult * lngMult
                        Next

                        Factorial = lngResult
                        End Function

                        This is totally safe, and it's good style, except that we should still now
                        cover our asses, and change FactorialOf to be ByVal in case a future
                        maintainer (possibly ourselves after too little caffiene or brain surgery)
                        reoptimizes the procedure, and in defiance of good style, again includes a
                        write to the FactorialOf variable.

                        Comment

                        • Mike MacSween

                          #13
                          Re: Passing arguments to function by reference - Good or Bad?

                          "Justin Hoffman" <j@b.com> wrote in message
                          news:d83tii$m70 $1@nwrdmz01.dmz .ncs.ea.ibs-infra.bt.com...[color=blue]
                          > "Mike MacSween" <mike.macsween. getlostspammers @btinternet.com > wrote in[/color]
                          [color=blue]
                          > PS Was that your letter on BBC Radio 4's 'You and Yours' program a while
                          > ago or just soemone with the same name?[/color]

                          I am indeed he, the harrasser of Radio 4 whiners! MacSween of that ilk.


                          Comment

                          • Mike MacSween

                            #14
                            Re: Passing arguments to function by reference - Good or Bad?

                            Thanks for your advice folks. So is there any argument passing equivalent to
                            Option Explicit? So that you HAVE to declare as either ByVal or ByRef.

                            "Mike MacSween" <mike.macsween. getlostspammers @btinternet.com > wrote in
                            message news:42a56cbc$0 $38045$5a6aecb4 @news.aaisp.net .uk...[color=blue]
                            > Just spent a happy 10 mins trying to understand a function I wrote
                            > sometime ago.
                            >
                            > Then remembered that arguments are passed by reference, by default.
                            >
                            > Does the fact that this slowed me down indicate:
                            >
                            > a) That I don't know enough
                            >
                            > b) Passing arguments by ref is bad
                            >
                            > c) A combination of the above.
                            >
                            > Yours, Mike Macsween
                            >[/color]


                            Comment

                            • Trevor Best

                              #15
                              Re: Passing arguments to function by reference - Good or Bad?

                              Mike MacSween wrote:[color=blue]
                              > Just spent a happy 10 mins trying to understand a function I wrote sometime
                              > ago.
                              >
                              > Then remembered that arguments are passed by reference, by default.
                              >
                              > Does the fact that this slowed me down indicate:
                              >
                              > a) That I don't know enough
                              >
                              > b) Passing arguments by ref is bad
                              >
                              > c) A combination of the above.
                              >
                              > Yours, Mike Macsween
                              >
                              >[/color]

                              Naming conventions help here. Prefixing parameters with a "p" for
                              example (like the ol' L/R conventions, I think R on his own still does)
                              makes parameters show up in the middle of a procedure, e.g.

                              Function MyFunction(pstr Something as string)
                              ... some code
                              pstrSomething = strSomethingEls e

                              Even a few hundred lines down the code that last line should stand out
                              as a parameter being assigned to something, should sound alarms somewhere.

                              --
                              [OO=00=OO]

                              Comment

                              Working...