Forking off a comment from another recent thread, I wanted to toss
something out about validating method names passed as arguments. For
background, 4D has an small but expanding set of methods that take a method
name as an argument, including ON ERR CALL, New process, Execute on server,
and so on. Unfortunately, these arguments are treated as strings by the
compiler and as method names by the interpreter. While there's no way for
the compiler to test expressions that resolve to a method name at runtime,
there's every way that it could test string literals at compile time. But
it doesn't.

Anyway, this leads to a nasty situation where your error is happening at
the worst time, runtime. It's 100%  a developer error, so the user should
never get it or see it. How to prevent it? Wrap the command test the method
name argument. Not a perfect solution, but it's something.

So (with fake code) ON_ERR_CALL("MyMethodName")

...and then ON_ERR_CALL checks

$good:=Method_Exists($1)

if($good)
  ON ERR CALL($1)
end if

Here's the real code of Method_Exists:

// Method_Exists

C_BOOLEAN($0;$exists_b)
C_TEXT($1;$method_name)

$method_name:=$1  // May be Method_Name or Method_Name(Argument or
something, clean it.

$exists_b:=False

If ($method_name#"")
  ARRAY TEXT($names_at;0)
  METHOD GET NAMES($names_at;$method_name)
  $exists_b:=Size of array($names_at)=1
End if

$0:=$exists_b

There are a couple of obvious drawbacks here:

* Kind of super inefficient to build the whole array every time.

* Do you really want to run this over and over and over and over?

What I do breaks down like this:

* Think about caching the method names and then testing against that
instead of calling METHOD GET NAMES. But then not do it...but you might
want to.

* Only call in debug, development, or testing mode.

As an example, here's what my actual error handler wrapper looks like:

// ErrorHandler_Install
// Install and track a new error handler. The previous handler can be
restored by calling

C_TEXT($1;$handler_name)
$handler_name:=Substring($1;1;31)

ErrorHandler_InitializeTracking   // Make sure that the tracking array is
defined.

INSERT IN ARRAY(ErrorHandler_MethodNames_at;1;1)  // Put it at the bottom.
ErrorHandler_MethodNames_at{1}:=$handler_name

C_TEXT($handler_name)
$handler_name:=ErrorHandler_MethodNames_at{1}
ON ERR CALL($handler_name)

If ($handler_name#"")  // Don't validate an empty handler name, it is valid
by definition in this context.

   If (System_IsRunningInDeveloperMode )

      If (Method_Exists ($handler_name)=False)
         ErrorLog_Record ("ErrorHandler_HandlerDoesNotExist";Current method
name;"Handler name = "+$handler_name)
      End if

   End if

End if

  // End of method.
**********************************************************************
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:4d_tech-unsubscr...@lists.4d.com
**********************************************************************

Reply via email to