If you're new to the Clier environment, you may nee! to ta"e an e#i$tin% #&a$e 'mo$t any !iale(t a$t or re$ent) or Clipper *ummer '+, relea$e ali(ation an! %ive it a fa(elift by ma"in% it (omatible with the late$t ver$ion of C-.Clipper. In thi$ arti(le, I'll refer to the (urrent ver$ion a$ $imly /Clipper./
I, er$onally, en0oy 'an! $en! a $i%nifi(ant art of my (on$ultin% ra(ti(e) imrovin% e#i$tin% ali(ation$ by (han%in% !ate! #&a$e metho!olo%ie$ to more (ontemorary /Clier (ool/ te(hni1ue$. I no lon%er a%ree to mo!ify *ummer '+, $y$tem$ without !oin% a full Clier (onver$ion. 2he 0u$tifi(ation for thi$ attitu!e (enter$ aroun! my belief that future !eveloment an! maintenan(e will be more $treamline! an! (o$t effe(tive on(e a more robu$t lan%ua%e (ome$ into lay..whi(h, in my oinion, 0u$tifie$ the (onver$ion (o$t u front.
In thi$ arti(le, I e#lore the in$ an! out$ of $u(h a (onver$ion. 3ou'll nee! to !raw on your ba$i( "nowle!%e of (urrent ver$ion Clipper lan%ua%e feature$, ro%rammin% (on$tru(t$, an! te(hni1ue$, mo$t of whi(h we've (overe! in a$t (olumn$.
Levels of conversion
2he fir$t thin% to (on$i!er when you !e(i!e to move an e#i$tin% (o!e ba$e to Clipper, i$ how !etaile! a (onver$ion i$ re1uire!. 2here are $everal way$ to ro(ee!4
Enough for an OBJ
2hi$ metho! yiel!$ the 1ui("e$t re$ult$, but in the lon% run, i$ the lea$t benefi(ial. 5ere, you u$e Clipper'$ (omatibility with *ummer '+, an! !&a$e III 678*, alon% with a few a!0u$tment$ !ue to a minority of un$uorte! (omman!$, an! (ome u with a $u((e$$ful (omile an! re$ultin% 9&: file. 2rue, you're now u$in% the mo$t (urrent ver$ion of Clipper, but you aren't u$in% any of the feature$ that ma"e it a better !eveloment latform.
Unobtrusive conversion
Goin% !own thi$ ath, you $et the $ta%e for a full (onver$ion by u$in% (ontemorary Clier te(hni1ue$ only where imme!iately obviou$, leavin% ol!er metho!$ for another !ay.
Full conversion
2hi$ i$ the mo$t !iffi(ult, but %enerally yiel!$ the mo$t favorable re$ult$. 5ere, you %o all the way, $o to $ea", by intro!u(in% ra%%e! array$, built.in (la$$e$, (o!e blo("$, et(. into the new ali(ation. 2he balan(e of thi$ arti(le fo(u$e$ on thi$ aroa(h.
Steps toard conversion
2o ro(ee! with a $eamle$$, trouble.free evolution to the Clipper lan%ua%e, follow thi$ (he(" li$t. If you ay attention to all the$e item$, you'll a(hieve a full (onver$ion. I've al$o thrown in a few item$ that romote an imrove! (o!in% $tyle, whi(h, when (arrie! forwar! with the full (onver$ion, yiel!$ very rewar!in% re$ult$.
!ungarian "otation
- arti(ularly %oo! time to intro!u(e 5un%arian notation in an e#i$tin% ali(ation i$ !urin% the (onver$ion. 2hi$ way you (an better mana%e the e#an!e! number of !ata tye$ available in Clipper, e$e(ially when !ealin% with array$, (o!e blo("$, an! ob0e(t$.
8$in% 5un%arian notation al$o la(e$ ne(e$$ary limitation$ on #&a$e'$ inherent /!ynami( tyin%/ fa(ility whereby a variable'$ !ata tye (an be (han%e! by $imly a$$i%nin% it a value of a !ifferent tye. Con$i!er the (o!e $e%ment below4
; In #&a$e you (an !efine a (hara(ter variable an! ; then rea$$i%n to a numeri(.
mZipCode = '90278' mZipCode = 90024 && Type re-assignment!
; <ith 5un%arian notation, thi$ (an t haen if you follow the rule$.
cZipCode = '90278' // 'c' prefix allows only char. nZipCode = 90024 // Another memvar is required, this time with a 'n' prefix.
3ou'll fin! that a lot of le%a(y #&a$e an! *ummer '+, ali(ation$ u$e e#(e$$ive !ynami( tyin%. 2he (onver$ion ro(e$$ i$ a %oo! time to ferret out the e#(e$$ive !ynami( tyin% to %et a more $table (o!e ba$e.
<hen !ealin% with Clipper, you $houl! al$o (ontemlate e#li(itly !e(larin% all memvar$ in LOCAL or STATIC $tatement$. 2hi$ way, there will be one (entral la(e to (he(" for a variable'$ e#i$ten(e an! it$ $ole !ata tye.
Clipper Operators
7e%a(y #&a$e (o!e may nee! an imortant fa(elift with Clipper'$ $erie$ of $treamline! oerator$. 5ere'$ a li$t of the$e oerator$4
Intro!u(in% the$e oerator$ !urin% a (onver$ion i$ imortant for many rea$on$. 6robably the mo$t imortant of the$e rea$on$ (enter$ aroun! the ability to embe! them a$ /in.line/ e#re$$ion$ in lo%i(al e#re$$ion$, arameter li$t$, an! (o!e blo("$.
2he !ate! STORE (omman! fin!$ a rela(ement by the (omoun! a$$i%nment oerator, yiel!in% a more rea!able form4
; >ir$t an ?ba$e ver$ion
STORE O TO nCount1, nCount2, nCount3
; Now in Clipper
nCount1 := nCount2 := nCount3 := 0
Co,piling ith (-
<henever (omilin% a 6@G with Clipper, e$e(ially !urin% the initial $ta%e$ of a (onver$ion, I re(ommen! u$in% the (- (omiler $wit(h. &eware thou%h, a$ a !elu%e of warnin% me$$a%e$ will en$ue. 2hi$ tell$ you how the (omiler really feel$ about your ro%ram. 3our %oal $houl! be to %et a (lean (omile 'i.e., no error$ or warnin%$). 9ne otentially annoyin% $i!e affe(t of Clipper i$ the ubli( array GetList whi(h i$ referen(e! by many (omman!$. 2hi$ referen(e %enerate$ warnin% me$$a%e$. 3ou (an eliminate the warnin%$ by la(in% a MEMVAR GetList $tatement in ea(h ro%ram that the (omiler !ia%no$e$ with a warnin%.
Shortcutting
2he !efault ro(e$$ of /lo%i(al oerator $hort(uttin%/ in Clipper may leave le%a(y #&a$e $y$tem$ runnin% !ifferently than before. *hort(uttin% involve$ $ituation$ where a lo%i(al e#re$$ion i$n't evaluate! (omletely 'a$ an otimization te(hni1ue), (au$in% in(orre(t re$ult$. Con$i!er the followin% e#amle4
IF lDelinq .AND. Fees() < ... Statements > ... ENDIF
5ere, if the lo%i(al value of lDelin% i$ .>., Clipper !oe$n't evaluate the re$t of the e#re$$ion, namely (all the >ee$') 8D> $in(e the value of the e#re$$ion ha$ been !etermine! be(au$e lDelin1 i$ fal$e. 8nfortunately, >ee$') may erform an imortant (al(ulation. >ee$') woul! have been (alle! in other lan%ua%e$, in(lu!in% *ummer '+,. 3ou (an turn off $hort(uttin% for (omatibility uro$e$ by $e(ifyin% the (. (omiler $wit(h, but it'$ re(ommen!e! !urin% the (onver$ion ro(e$$ to re.write the offen!in% lo%i(al e#re$$ion$ to ta"e a!vanta%e of $hort(uttin%. In our e#amle, we $ee the e1uivalent (o!e4
LReturn := Fees() // Call Fees() no matter what IF lDelinq .AND. lReturn // Now shortcutting OK.
TBrose and TBColu,n
9ne $ellin% oint for Clipper i$ it$ TBrowse an! TBColumn re!efine! (la$$e$ that to%ether rovi!e for an a!van(e!, ob0e(t.ba$e!, !ata brow$in% te(hnolo%y. >or *ummer '+, ali(ation$, all o((urren(e$ of DBEDIT() $houl! be (onverte! 'Clipper li$t$ DBEDIT() a$ a (omatibility fun(tion) to a TBrowse e1uivalent. 2hi$ may be a !iffi(ult ro(e$$, e$e(ially if DBEDIT()'$ u$er fun(tion arameter wa$ u$e!. Convertin% from other #&a$e lan%ua%e$ involve$ ta"in% the BROWSE (omman!'$ fun(tionality an! (omin% u with $omethin% $imilar in Clipper.
The /reprocessor
<herever aroriate, you $houl! (on$i!er u$in% the feature$ of the rero(e$$or. 2hi$ in(lu!e$ u$in% manife$t (on$tant$ in$tea! of memory variable (on$tant$, u$in% the re!efine! manife$t (on$tant$ foun! in the $tan!ar! Clipper hea!er file$ 'e$e(ially "ey !efinition$ li"e ABC*C, AB86, et(.), an! intro!u(in% $eu!o fun(tion$ to rela(e $imle 8D>$.
In the (a$e of lo%i(al (on$tant$, COMMON.CH (ontain$ two very u$eful (on$tant !efinition$4
#define TRUE .T. #define FALSE .F.
I've foun! that TRUE an! FALSE ma"e for mu(h more rea!able lo%i(al e#re$$ion$.
0evised scoping(lifeti,e
2hi$ i$ one of the mo$t imortant area$ !urin% the (onver$ion ro(e$$ an! often the mo$t !iffi(ult. Dany #&a$e an! *ummer '+, ali(ation$ have be(ome e#tremely tan%le! !ue to the mi$u$e of the #&a$e lan%ua%e'$ ability to /wil!ly inherit/ variable$ o$$e$$in% a PRIVATE $(oe. >or e#amle, I've $een $y$tem$ that !e(lare a rivate memvar, a$$i%n it a value, an! not refer to it until it rea(he$ a mo!ule five level$ !ee in the (allin% (hain. 2hi$ i$ an abu$e of the inheritan(e of rivate$, e$e(ially if that lower level mo!ule i$ (alle! by other mo!ule$.
In Clipper, you $houl! !e(lare re%ular memvar$ a$ LOCAL an! a$$ them to $ubro%ram$ a$ arameter$ in$tea! of !een!in% on their inheritan(e.
2here are $ome in$tan(e$ where limite! $(ale inheritan(e i$ a((etable, namely for !ata.entry ro%ram$ that i$$ue GET$ for memvar$ an! (all $ub$i!iary mo!ule$ to $(atter an!=or %ather !ataba$e fiel! (ontent$ 'althou%h u$in% array$ i$ more effi(ient).
Durin% a (onver$ion, you $houl! try to eliminate all PRIVATE$ an! PUBLIC$ in favor of the le#i(ally $(oe! LOCAL an! STATIC 'in(lu!in% file.wi!e $tati($).
@emember that a file.wi!e $tati( %ive you the $ame lifetime a$ a PUBLIC 'i.e., forever), but it$ $(oe i$ limite! to $ubro%ram$ in the (urrent 6@G file. If you truly nee! /%lobally $(oe!/ variable$, tho$e that are "nown everywhere an! live forever, u$e PUBLIC$. Da"e $ure you !e(lare PUBLIC$ in the Dain') mo!ule
Functioni1e
Contemorary u$e of the Clipper lan%ua%e $ay$ you $houl! (on$i!er /fun(tionizin%/ all ro%ram mo!ule$. 3ou (an %rou relate! $ubro%ram$ in a $in%le 6@G file an! en(lo$e ea(h mo!ule in either a FUNCTION or PROCEDURE !e(laration. 3ou (an treat the PROCEDURE form of $ubro%ram a$ a fun(tion, (allin% it a$ a fun(tion. 2hi$ way the arameter a$$in% te(hni1ue$ are the $ame for both form$ of $ubro%ram$. 2he only !ifferen(e i$ that a 8D> return$ a value an! a ro(e!ure !oe$n't. 2he mo$t imortant thin% i$ to %et ri! of the DO/WITH $tyle of ro(e!ure (all$. @emember, when u$in% thi$ $ubro%ram $tyle, you nee! the =N (omiler $wit(h.
Eli,inate ,acros
2here are u$ually many oortunitie$ to eliminate ma(ro$ in favor of (o!e blo("$. 3ou'll fin! that many ol!er #&a$e an! *ummer '+, ali(ation$ %o overboar! with the 2 ma(ro oerator. In Clipper, you (an avoi! u$in% ma(ro$ by otin% for e#ten!e! e#re$$ion$ a$ in4
LOCAL cDatabase := 'Orders'
; In$tea! of4
USE &cDatabase
; we (an !o the followin%4
USE (cDatabase) // Extended expression
? (cDatabase)->CustNo //Also with alias notation.
Co!e blo("$ al$o offer an oortunity to avoi! ma(ro$ in (ertain $ituation$, a$ in4
LOCAL cSelection := 'Grade > 80 LOCAL nTotGrade
; In$tea! of4
SUM Class->Grade TO nTotGrade FOR &cSelection
; we (an !o the followin%4
bSelection := { || Grade > 80 }
SUM Class->Grade TO nTotGrade FOR EVAL (bSelection)
2he (hallen%e i$ to re(o%nize when to $ub$titute a (o!e blo(" for a ma(ro.
Use the enhanced arra3 facilities
Dany of the (o!in% !e(i$ion$ an! ra(ti(e$ that were art of ol!er ali(ation$ may have been ba$e! on the limitation$ or ab$en(e of array $tru(ture$. <hen (onvertin%, the$e !e(i$ion$ $houl! be re(on$i!ere! an! the ra%%e! array aroa(h alie!. In a!!ition, the array ro(e$$in% (aabilitie$ in the variou$ built.in array fun(tion$ $houl! be u$e! whenever o$$ible. &e aware, however, that intro!u(in% array$ to a ro%ram that !i!n't reviou$ly u$e them, normally re1uire$ a re.write.
2he har!e$t art in alyin% Clipper'$ array te(hnolo%y i$ in re(o%nizin% when the ro%ram nee!$ array$. 9ften the nee! 0um$ out at you a$ in4
5ere, an array (an $horten an! (larify the (o!e (on$i!erably a$ in4
LOCAL aTaxRate[26] // Array of tax rates nTaxAmt := nPrice * aTaxRate[nCounty]
Database functions
- "nowle!%e of Clipper'$ ability to have the rero(e$$or tran$late many !ataba$e.oriente! (omman!$ to their built.in fun(tion e1uivalent$ '$ee *2D.C5), $he!$ li%ht on an alternate way of writin% Clipper (o!e..(allin% the !ataba$e fun(tion$ !ire(tly. 2hu$, the followin% *ummer '+, (o!e mi%ht evolve in thi$ manner4
; *ummer '+, ver$ion
SET SOFTSEEK ON mName = 'Gorham' SEEK mName DO WHILE Customer->Name = mName .AND. .NOT. EOF() ? Customer -> Name, Customer -> Zip SKIP ENDDO
=; Clier ver$ion ;=
LOCAL cName DBSEEK(cName, TRUE) // 2nd parm indicates a softseek WHILE Customer->Name == cName .AND. !EOF() QOUT(Customer->Name) QQOUT (Customer->Zip) DBSKIP() END
2he only %ain in (allin% !ataba$e fun(tion$ !ire(tly i$ that they may be alia$e! a$ in
Employee->(DBSKIP()).
Using the order ,anage,ent s3ste,
Clipper ha$ a va$tly imrove! $y$tem for or!erin% !ata in a !ataba$e file whi(h i$ ba$e! aroun! it$ @DD 'rela(eable !ataba$e !river) te(hnolo%y. New (on(et$ $u(h a$ or!er$, or!er ba%$, an! or!er li$t$, rovi!e (omatibility with in!e#in% $(heme$ for !&-*C IE, >o#6ro, an! 6ara!o#. *o if the *ummer '+, $y$tem you've been !ealin% with wa$ ben!in% over ba("war! to %et thi$ (omatibility, the roa! i$ now mu(h $moother.
Other orth3 ,entions
5ere are a few mi$(ellaneou$ item$ you may (on$i!er when !oin% a Clipper (onver$ion4 Get ri! of ob$olete (omman!$ $u(h a$4
CALL CANCEL CLEAR ALL DIR FIND NOTE RESTORE SCREEN SAVE SCREEN SET COLOR SET EXACT SET EXCLUSIVE SET FORMAT SET PROCEDURE SET UNIQUE STORE TEXT/ENDTEXT WAIT
8$e the SET() fun(tion to $ave an! re$tore Clipper $ettin%$. >or e#amle4
LOCAL LCursorSave := SET(_SET_CURSOR, 0) . .<statements>. SET(_SET_CURSOR, LCursorSave) // Restore before leaving.
Convert all >D2 $(reen form$ an! >@D reort form$ to native Clipper (o!e. 2hi$ ma"e$ them mu(h more fle#ible for han!lin% future re1uirement$, it al$o remove$ the !een!en(e on e#ternal file$ 'e.%., >D2$ an! >@D$).
4n su,,ar3
<ith the ti$ outline! in thi$ arti(le, you $houl! have a retty $oli! i!ea of what you're u a%ain$t when ma"in% the ro%re$$ion to the Clipper G.H lan%ua%e. 2he ro(e$$ may $eem ar!uou$ at time$, but the benefit$ outwei%h the !iffi(ultie$. 9ne la$t wor! to (onvin(e you a (onver$ion will a$$i$t future !eveloment en!eavor$ i$ that the (omin% C-.Ei$ual 9b0e(t$ <in!ow$ environment (ontain$ all the feature$ !efine! here. Da"in% a tran$ition from Clier to C-.E9 will be all the le$$ ainful if you $tart mi%ratin% your (o!e to a better way now.