Download - 4GL Coding Worst Practices

Transcript
Page 1: 4GL Coding Worst Practices

1

4GLCodingWorstPracticesaka:TheKeywordForgetListAccordingtoTomTomBascom,WhiteStarSoftwareAbstract:JustbecauseyouCAN-DO()itdoesn'tmeanthatyoushoulddoit.Programmersaredrawntobadexampleslikesmothstoflame.Nomatterhowmanycarefullycraftedcommentsyouputaroundthatoneusageofaspecialcasesomeprogrammerwillfinditandsuddenlypropagateitthroughoutyourapplication.CometothissessiontolearnwhyCAN-DO(),FINDFIRST,RELEASEandmany,manyothercodingworstpracticesshouldbebanned!Oratleastlearnwhyyoushouldnotcontinuetousetheseworstpracticesjustbecause"everyoneelsealwaysdoesitthatway".

Page 2: 4GL Coding Worst Practices

4GLCodingWorstPracticesaka:TheKeywordForgetListAccordingtoTom

TomBascom,[email protected]

Page 3: 4GL Coding Worst Practices

AFewWordsabouttheSpeaker

•  TomBascom:Progressuser&roamingDBAsince1987•  Partner:WhiteStarSoftware&DBAppraise,LLC– ExpertconsultingservicesrelatedtoallaspectsofProgressandOpenEdge.– RemotedatabasemanagementserviceforOpenEdge.– Authorof:– Simplifyingthejobofmanagingandmonitoringtheworld’sbestbusinessapplications.

–  [email protected]

3

Page 4: 4GL Coding Worst Practices

4

Page 5: 4GL Coding Worst Practices

{disclaimer.i}

•  IdonotworkforProgress…•  …andafterthiswecanbeprettysurethatIneverwill;)

•  Thecontentofthissessionisheavilylacedwithopinion!

5

Page 6: 4GL Coding Worst Practices

“Deprecated”=notquite“banned”L

knowledgebase.progress.com/articles/Article/P67734

•  Codewillstill“work”butitisstronglyrecommendedtostartmodifyingyourcode.

•  TechnicalSupportwilldotheirbesttohelp.•  Noescalationswillbeissuedondeprecatedstatementsandclauses.

•  Notguaranteedthatoldcodewithdeprecatedstatementswillstillworkinfuturereleases.

6

Page 7: 4GL Coding Worst Practices

Progress’OfficiallyDeprecatedFeatures

•  UPDATEEDITING•  GO-PENDING•  CHOOSE•  SCROLL•  PUTSCREEN•  IS-ATTR-SPACE•  GATEWAYS•  SQL(withinthe4gl)

7

Page 8: 4GL Coding Worst Practices

Tom’sList!

8

Page 9: 4GL Coding Worst Practices

DOS

•  EvenworsethanWindows!

9

Page 10: 4GL Coding Worst Practices

DOS

•  EvenworsethanWindows!•  AndUNIXandVMSandBTOSforthatmatter•  ThesestatementsbindyourcodetoaparticularOS.•  Yourcodeislessflexibleandmorebrittle…•  InsteaduseOS-COMMANDVALUE(cmd)– CMDcanbeastoredinaconfigtable.– PerhapsasatemplatethatyouusewithSUBSTITUTE

10

Page 11: 4GL Coding Worst Practices

OS-COMMAND&SUBSTITUTE

11

ifopsys="unix"thendbaCmd="$DLC/bin/proutil&1-Cdbanalys-Bp10>”+“$PROTOP/dbanalys/&2.dba2>&&1&&”.elsedbaCmd="%DLC%~\bin~\proutil&1-Cdbanalys-Bp10>”“%PROTOP%~\dbanalys~\&2.dba2>&&1&&”.os-commandsilentvalue(substitute(dbaCmd,pdbname(1),ldbname(1))).

Page 12: 4GL Coding Worst Practices

UnquotedFileNames

•  Unfortunately,thiscodeworks:

12

outputtotest.put"hellokitty".

•  IMHOthatshouldbeacompilererror.•  Allowingunquotedfilenamesisabugwaitingtohappen:

definevariabletestascharacterno-undo.test="xyzzy".outputtotest.put"hellokitty".

Page 13: 4GL Coding Worst Practices

CALL

•  Thisistheold“HLC”interface.•  Youhavetorelinkyour_progresexecutabletouseit.•  Thecapabilitiesthatitsupportshavebeenreplacedbytheabilitytocallsharedlibraries,evenonUNIX:

http://dbappraise.com/ppt/shlib.pptx

13

Page 14: 4GL Coding Worst Practices

DEFINEWORK-TABLE(WORKFILE)

•  Pre-datestemp-tablesandprodatasets.•  Noindexes-sosearchesareslow•  Nofancy,modernfeatureslikeREAD-JSONetc.•  LimitedbyavailableRAM•  UngracefulfailureswhenyourunoutofRAM– Sessionscrashes– MaybeeventhewholemachineL

14

Page 15: 4GL Coding Worst Practices

ACCUMULATEetc.

•  Aggregatephrases,ingeneral,aretoocomplexandfinicky.•  AVERAGE,TOTAL,etc.•  IMHOitiseasier,andalotclearer,toexplicitlycreatetheintermediatevariablesanddothecalculations.

•  Muchlesslikelytobemessedupbyamaintenanceprogrammer.

15

Page 16: 4GL Coding Worst Practices

ACCUMULATE

Therearetwowaysofconstructingasoftwaredesign:Onewayistomakeitsosimplethatthereareobviouslynodeficienciesandtheotherwayistomakeitsocomplicatedthattherearenoobviousdeficiencies.

—C.A.R.Hoare,The1980ACMTuringAwardLecture

Debuggingistwiceashardaswritingthecodeinthefirstplace.Therefore,ifyouwritethecodeascleverlyaspossible,youare,bydefinition,notsmartenoughtodebugit.

BrianW.KernighanandP.J.PlaugerinTheElementsofProgrammingStyle.

16

Page 17: 4GL Coding Worst Practices

VALIDATE

•  Validationexpressionshavenousefulnessinmoderncode.Theyapplytoolateinthedataentrycycletobeuseful(validationsareperformedjustbeforedataiswrittentothedb).Don'tusethem.You'reonthewrongpath.

•  Ifyouchangeavalidationexpressionthatchangeisn'tnoticedbycodeuntilyourecompile.

•  Validationexpressionsmadegooddemosbackinthedaybuthaveneverreallybeenusefulforrealcode.

•  Theroleofvalidationexpressionsisbetterfilledbya“rulesengine”(suchasCorticon).

17

Page 18: 4GL Coding Worst Practices

RELEASE

•  Almostalwaysasignthattheprogrammerisconfusedaboutrecordlockingortransactionscopeanddoesnotreaddocumentationverycarefully.

18

Page 19: 4GL Coding Worst Practices

RELEASEStatement

Fromthedocumentation:

Verifies that a record complies with mandatory field and unique index definitions. It clears the record from the buffer and unites it to the database if it has been changed.

19

Page 20: 4GL Coding Worst Practices

RELEASEandRecordLocksmessage"beforefind".pause.findcustomerexclusive-lockwherecust-num=2.displaycust-numnamediscount.message"beforeupdate".pause.updatediscount.message"beforereleasecustomer".pause.releasecustomer.message"afterreleasecustomer".pause.

RECIDTableFlagsUsr----------------------------------3862X63862X63862SL6

Page 21: 4GL Coding Worst Practices

RELEASE…

UseproperrecordandtransactionscopingandyouwillneverneedtouseRELEASE:

21

definebufferupd_custforcustomer.foreachcustomerno-lock:ifcustomer.discount>10thendoFORupd_custtransaction:/*strongscopethe“upd_cust"buffer*/findupd_custexclusive-lockwhereupd_cust.custNum=customer.custNum.upd_cust.discount=10.end.end.

Page 22: 4GL Coding Worst Practices

CAN-DO()

•  Along,longtimeago…•  Therewerenolistmanipulationfunctions.•  LOOKUP,ENTRYetc.wasnotinthe4gl…•  SomeonenoticedthatCAN-DOcouldbesubvertedtoperformthiscommontask:

22

displaycan-do("a,b,c","z").

Page 23: 4GL Coding Worst Practices

CAN-DO…morehistory

•  A*lot*ofcodewascreatedbyaveryearly,verysuccessfulVARusingthistechnique.

•  UnfortunatelyagreatmanyProgressprogrammershavebeenexposedtothatcode.

•  Thatdoesnot,however,makeita“bestpractice”orevena“goodidea”.

•  Atbestitisa“badhabit”.

23

Page 24: 4GL Coding Worst Practices

JustBecauseyouCAN-DO…

…doesn’tmeanthatyouSHOULD-DOUsingasecurityfunctiontoperformstringoperationsismisleading.RatherthanhavingplainEnglishself-documentingcodeyouareabusingafunctiontoachieveapurposethatitwasneverintendedfor.

24

Page 25: 4GL Coding Worst Practices

FromtheKbase…

25

http://knowledgebase.progress.com/articles/Article/P100218

UsingtheCAN-DOfunctionasasubstitutefortheLOOKUPfunctionconstitutesamisuseoftheCAN-DOfunctionandisstronglydiscouraged.

http://knowledgebase.progress.com/articles/Article/000041404

TheCAN-DOfunctionisexplicitlydesignedtomatchuser-idpatterns.Usingitforarbitrarystringcomparisonsisnotintendedandwillprovideundefinedresults.

Page 26: 4GL Coding Worst Practices

CAN-DO()alternative

•  Bad:

•  Good:

26

ifcan-do(‘ME,NH,VT,MA,CT,RI’,‘NH’)=truethen…

iflookup(‘NH’,‘ME,NH,VT,MA,CT,RI’)>0then…

Page 27: 4GL Coding Worst Practices

ButCAN-DO()supportswild-cards!

•  99%ofthoseusesarecoveredwithBEGINS,MATCHESorCOMPARE

•  Butifyoureallyneedit:

27

/*credittoKurtGunderson,PEGJuly232015*/functionmyCANDOreturnslogical(inputtaschar,inputsaschar):return((lookup("*",s)<>0orlookup(t,s)<>0)and(notlookup("!"+t,s)<>0)).endfunction.

Page 28: 4GL Coding Worst Practices

…aboutthose“wild-cards”

•  CAN-DO("a,b,#","#”)returnsfalse!•  CAN-DOusessomemagiccharacters:

.:Matchasinglecharacter*:Matchmultiplecharacters!:Negateamatch#:DistinguishGRANTablevs.non-GRANTablepermissionsinSQL89@:Usedtorepresenttheblankuserid(asofoe11)““:Spacesarenotallowed

•  Otherquirkscouldbeaddedatanytime!

28

Page 29: 4GL Coding Worst Practices

Andifthatallthatwasn’tBadEnough

•  CAN-DO()inaWHEREclause*forces*client-sideselectionandsorting.

29

Page 30: 4GL Coding Worst Practices

CAN-DO()Summary

•  CAN-DOisasecurityfunction!•  Specialcharactersinthedatawillcauseittoproduceunexpectedresults!(akabugs)

•  Becauseitisallaboutuseridsitmustbeevaluatedbytheclient.– SoifitisinaWHEREclauseyouwillhaveatablescan!– CAN-DOcannotandwillnotbeevaluatedserver-side.

30

Page 31: 4GL Coding Worst Practices

OF

•  ImpliedWHEREclause•  Usesa”commonnamesthatareindexedimplyJOIN”convention.•  Obscurestablerelationships.•  LikeVALIDATE,OF“makesagooddemo”.•  Butshouldneverbeusedinreallife.

31

Page 32: 4GL Coding Worst Practices

USE-INDEX

•  OverridesProgress’optimizer:– Youareprobablynotsmarterthanthecompiler*–  Icertainlyamnot.

•  Forcesasingleindextobeused.•  WHEREclausemismatcheswillresultinverypoorperformance.•  OnthebrightsideUSE-INDEXprovidesanordering:– Maynotbeclearorobvious–indexnamingconventionscanbemissing,misleadingorwrong.

– MayconflictwithBYphraseandcauseclientsidesorting.

32*Tryingtooutsmartacompilerdefeatsmuchofthepurposeofusingone.—KernighanandPlauger,TheElementsofProgrammingStyle.

Page 33: 4GL Coding Worst Practices

USE-INDEX…

•  Stillthinkyoushoulduseit?– Proveit!– Usingrealisticandmeaningfultestdata.– Providedetailedandreproducibletestcasesinyourcommentssothatfutureprogrammerswillrecognizeandcelebrateyourbrilliance.

33

Page 34: 4GL Coding Worst Practices

FINDFIRST(andLAST)

•  ReflexiveandautomaticuseoneachandeveryFINDdoesNOTimproveyourcode.

•  ItisNOTa“standard”.•  Norisita“bestpractice”.•  Nordoesit“alwayswork”.

•  Yes,Iknowitisallovertheplaceincertaincodebases.

34

Page 35: 4GL Coding Worst Practices

UniqueFINDs

•  FINDisdesignedtoreturnexactlyoneorzerorecords.•  99.44%ofFINDstatementsshouldbeforUNIQUErecords.•  ThisisoneofProgress’bigadvantagesoverSQL.•  IftheWHEREclausespecifiesauniquerecordthenFIRSTaddsnovalue.

•  Worse–itconfusesthemaintenanceprogrammerbyimplyingthatthere/should/beanorderedresult-set.

35

Page 36: 4GL Coding Worst Practices

UniqueFINDFIRSTperformance•  ItisNOTfaster.•  ItdoesNOT“eliminateacheckforambiguousrecords”.

•  Allofthestatementsabovetakethesametimetorunandhavethesame“logical”impactonthedbengine.

•  Allstatementsexecutethesamenumberof“logicalIOops”(ProTop,PROMONorVST“blockaccess”).

•  Feelfreetotestityourself!

36

FINDFIRSTcustomerNO-LOCK.FINDcustomerNO-LOCKWHEREcustNum=1.FINDFIRSTcustomerNO-LOCKWHEREcustNum=1.

Page 37: 4GL Coding Worst Practices

FasterFINDwithFIRST?

•  ButwhatifFIRSTdoesactuallymakeaqueryfaster?– YouhavenotspecifiedUNIQUEcriteria!– YouaremissinganappropriateindextomatchyourWHEREclause.

– MaybeyourWHEREclauseisn’tdoingwhatyouthinkitshouldbedoing?

37

Page 38: 4GL Coding Worst Practices

FINDFIRSTSlogan

ReturningtheWrongRecordFaster!

Aprogramthatproducesincorrectresultstwiceasfastisinfinitelyslower.

—JohnOsterhout

38

Page 39: 4GL Coding Worst Practices

FINDSECOND?

•  YouusedFINDFIRSTanyway…whatareyoudoingaboutthesecondrecord?

•  Ifthereactuallyisasecondrecordandyouareactuallydoingsomethingwithit:– Howdidyouspecifytheordering?–  Ifyoudon’tcareaboutorder–whatdoesFIRSTmean?– AreyoutreatingitexactlythesameastheFIRSTrecordfroma3NFperspective?– Areyouprocessingtheentireresultset?Whydidn’tyouuseFOREACH?

39

Page 40: 4GL Coding Worst Practices

“ItAlwaysWorks”

•  Thisusuallymeansthattheprogrammerdoesnotwanttodealwith:

MorethanoneCustomerrecordsfoundbyauniqueFIND.(3166)

•  AddingFIRSTwill“makeitgoaway”.•  Italsomakesyourresultispotentiallywrong:– Whatifyouforgotacomponentoftheindex?– Ordidn’tknowthatapreviouslyunusedfeaturehasbeenenabledbytheusers?– Ortheuserssuddenlycreateasecondmagicalrecord?

40

Page 41: 4GL Coding Worst Practices

MagicFIRSTRecords

•  Recordsthatarespecialbyconvention.•  Nospecificattributeidentifiestheusage.•  AclearviolationofThirdNormalForm.

41

findfirstcustomerno-lockwherecustNum>0.displaycustNumnamediscount.defaultDiscount=discount.findfirstcustomerno-lockwherename>"".displaycustNumnamediscount.defaultDiscount=discount.

Page 42: 4GL Coding Worst Practices

FINDFIRSTSummary

•  FINDFIRSTisalmostalwaysasignoflazyprogramming•  Itdoesnotimproveperformance•  Itcancreatebugsandmaskexistingbugs•  Somecodebasesareinfestedwithit–butthereisnoreasontomaketheproblemworsebycontinuingthehabit

Page 43: 4GL Coding Worst Practices

FORFIRST(andLAST)

43

forfirstcustomerno-lockwherediscount>10:leave.end.displaycustNumnamediscount.foreachcustomerno-lockwherediscount>10bydiscount:leave.end.displaycustNumnamediscount.forfirstcustomerno-lockbydiscount:leave.end.displaycustNumnamediscount./*continue…*/

Page 44: 4GL Coding Worst Practices

FORFIRST(continued)

44

definevariableminDiscountasdecimalno-undoinitial99999.definevariableminDiscountCustNumasintegerno-undo.foreachcustomerno-lock:ifdiscount<minDiscountthenassignminDiscount=discountminDiscountCustNum=custNum.end.findcustomerno-lockwherecustNum=minDiscountCustNum.displaycustNumnamediscount./*continue…*/

Page 45: 4GL Coding Worst Practices

FORFIRST(results)

•  Sowhatdoes“FIRST”mean?

45

CustNumNameDiscount──────────────────────────────────────────────1LiftTours35%1067ArmadaleFitness15%1LiftTours35%6FanaticalAthletes0%

Page 46: 4GL Coding Worst Practices

FORFIRST(andLAST)

•  GiventhesameWHEREclause:– FINDonlyeverusesoneindex– FORcouldusemultipleindexes

•  Sortingoccursafterselection.– FIRSTandLASTproduceasinglerecord(thusthereisnothingtosort).– Basedonwhateverindexwaschosen.– BYisanindexselectiontie-breaker–itisnottheprimaryoptimization.– Selectionmightnotmatchyourhopedfororder.

46

Page 47: 4GL Coding Worst Practices

Summary

•  DOSetal•  UnquotedFileNames•  CALL•  DEFINEWORKFILE•  ACCUMULATE&AggregatePhrases•  VALIDATE

•  RELEASE•  CAN-DO•  OF•  USE-INDEX•  FINDFIRST•  FORFIRST

47

Page 48: 4GL Coding Worst Practices

Questions?

48

Page 49: 4GL Coding Worst Practices

SuggestedAdditions?

49

Page 50: 4GL Coding Worst Practices

ThankYou!

50