Plateforme Level Extreme
Abonnement
Profil corporatif
Produits & Services
Support
Légal
English
Return DoDefault() surprise
Message
De
18/03/2011 17:33:11
 
 
À
18/03/2011 17:23:20
Information générale
Forum:
Visual FoxPro
Catégorie:
Codage, syntaxe et commandes
Versions des environnements
Visual FoxPro:
VFP 9 SP2
Database:
Visual FoxPro
Divers
Thread ID:
01504135
Message ID:
01504182
Vues:
67
Yes, we all know this.

In this case, I am calling into a method on a wwBusiness class from Rick Strahl's West Wind framework.

Here's the code, for those who are curious. It's loaded with Return statements. It's not my work, so I have no choice but to call into it. And I'm certainly not going to change his source code. Sure, it has multiple Returns, however, they all seem properly coded and guarded to me. I'm not about to knock him. He's a master coder for sure, and today he might agree or do it differently, but this code has been around for years.
*================================================================================
* Class  wwbusiness of D:\WORK\LM_3\WW\CLASSES\WWBUSINESS.VCX

Procedure wwbusiness.Query
LPARAMETERS lcSelect, lcCursor, lnResultmode
LOCAL lnResult

lcSelect=IIF(EMPTY(lcSelect),THIS.cSQL,lcSelect)
lcCursor=IIF(EMPTY(lcCursor),THIS.cSQLCursor,lcCursor)
lnResultmode=IIF(EMPTY(lnResultmode),THIS.nResultmode,lnResultmode)

THIS.seterror()

IF !THIS.OPEN()
   RETURN 0
ENDIF

IF EMPTY( lcSelect ) OR NOT VARTYPE( lcSelect ) = "C"
   lcSelect = THIS.cSQL
ENDIF
IF EMPTY( lcSelect )
   ** We get everything...
   lcSelect = "*"
ENDIF
IF ATC(" FROM",lcSelect) = 0
  IF THIS.nDataMode = 0
   lcSelect = lcSelect + " FROM  '" + ALLTRIM(THIS.cDataPath + THIS.cFileName) + "' "
  ELSE
   lcSelect = lcSelect + " FROM " + ALLTRIM(THIS.cFileName) + " "
  ENDIF   
   *{lcSelect = "SELECT FROM " + Alltrim(THIS.cMasterTable) + " " + Subs(lcSelect,At(" ",lcSelect)+1)
ENDIF
IF NOT UPPER(lcSelect) = "SELECT "
   lcSelect = "SELECT " + lcSelect
ENDIF

THIS.cSQL = lcSelect

*** Run the SQL Statement
DO CASE
   CASE THIS.nDataMode = 0
      IF ATC(" INTO",lcSelect) = 0
         lcSelect = lcSelect + " INTO CURSOR " + lcCursor
      ENDIF

      &lcSelect

      IF !USED(lcCursor)
         RETURN 0
      ELSE
         lnResult = _TALLY
      ENDIF
   CASE THIS.nDataMode = 2
      lcOldCursor = THIS.oSQL.cSQLCursor 
      THIS.osql.cSQLCursor = lcCursor
      lnResult = THIS.osql.Execute(lcSelect)
      IF lnResult < 0
         THIS.seterror(THIS.osql.cErrorMsg)
         RETURN 0
      ENDIF
      
      THIS.oSQL.cSQLCursor = lcOldCursor

      lnResult = RECCOUNT()
   CASE THIS.nDataMode = 4
      lcOldCursor = THIS.oHTTPSQL.cSQLCursor 
      THIS.oHTTPsql.cSQLCursor = lcCursor
      lnResult = THIS.oHTTPsql.Execute(lcSelect) 
      IF lnResult < 0
         THIS.seterror(THIS.oHTTPsql.cErrorMsg)
         RETURN 0
      ENDIF
      
      THIS.oHTTPSQL.cSQLCursor = lcOldCursor
ENDCASE
 
*** Convert data if necessary
IF lnResultmode # 0
   THIS.ConvertData(lnResultmode,,lcCursor)
   USE IN (lcCursor)
ENDIF

RETURN lnResult

EndProc
>IMO multiple return/exit points are bad practice. I never, ever use them - so many Heisenbugs. If I have to work on someone else's code that has them, I refactor - no exceptions.
>
>It's off-topic, but if you get nothing else out of this thread, consider never having multiple exit points in your code.
>
>This topic has been heatedly debated here before and there's no need for me to get involved again - subscribers can search :)
>
>>Others have mentioned the possibility of various return point. There are multiple return points in the code, but I reviewed the code all Return points are properly coded to return an integer. Regardless, my new pattern would still be affected if a bool return type came back because of bad coding in the called method. I changed nothing in the baseclass code, but yet I began to get an int value back, like I was expecting.
>>
>>I agree, it should have worked tghe way it was... And today it does. I'm not sure what was wrong.
>>
>>I just know that I was testing for (lnReturn > 0) and lnReturn was actually a coming back as a bool, so my test code failed. The I stepped through the bebugger to see whay I was getting a bool, and I realized that I could not step into the Dodefault() code which was being called inline with a Return stament, therefore, I could not tell which part of the called code was returning the bool value. So, I assumed it was some oddity with callind DoDefault() inline with a Return statement.
>>
>>I changed to the new format, then I could step into the DoDefault() code, and it passed back an int, like it should have all along.
>>
>>Regardless, the mere fact that step-through debugging is affected by this inline pattern is enough to make me abandon it.
>>
>>
>>
>>
>>
>>
>>
>>>RETURN DODEFAULT() always works. I believe it's a good practice if you want your subclass code to run, then the default. Don't abondon -- fix what's wrong. One could argue that all sorts of combined statements make a harder to debug, and they do; but once you trust the pattern, it's not an issue. Perhaps you have mulitple RETURNS in a procedure?
>>>
>>>>Well, your code indeed works fine.
>>>>
>>>>And, I've gone back to my own code, and now I cannot get it to repeat the results I was getting last night.
>>>>
>>>>I *KNOW* for sure that is was not working correctly, but today I cannot replicate it.
>>>>
>>>>However, I still am resolved that I like my modified coding sequece anyway, so I'm still going to abandon the Return DoDefault() structure going forard.
>>>>
>>>>
>>>>
>>>>>>Some of you probably already knew this, but it caught me off guard...
>>>>>>
>>>>>
>>>>>Are you sure that's what's happening? Are you sure your base class always returns a number (and doesn't have some cases where it just does a RETURN out of the code)?
>>>>>
>>>>>I tried it and it works fine:
>>>>>
>>>>>
>>>>>o = CREATEOBJECT("TestB")
>>>>>?o.DoSomething("")
>>>>>
>>>>>DEFINE CLASS TestA AS Custom
>>>>>   FUNCTION DoSomething(tcString)
>>>>>      RETURN 1
>>>>>   ENDFUNC
>>>>>ENDDEFINE
>>>>>
>>>>>DEFINE CLASS TestB AS TestA
>>>>>   FUNCTION DoSomething(tcString)
>>>>>      RETURN DODEFAULT(tcString)
>>>>>   ENDFUNC
>>>>>ENDDEFINE
>>>>>
Précédent
Suivant
Répondre
Fil
Voir

Click here to load this message in the networking platform