






                   -----------------------------------------

                                B U I L D I N G
                             S O U R C E  C O D E
                               L I B R A R I E S

                   -----------------------------------------


       The following is an excerpt from a chapter of a seminar topic
       entitled "Building Source Code Libraries."  The chapter is called
       CONSISTENT and it is presented amid chapters called PLANNED,
       IMPLEMENTED, CENTRALIZED, GENERALIZED, DOCUMENTED, RELIABLE and
       WORTHWHILE.

       The full document, along with stacks and stacks of standard
       library code, form the essential Yellick Computing application
       development environment.  I demand that everyone doing
       programming for me must adhere to the conventions and use the
       library functions whenever possible.  Of course, not everyone
       DOES but at least an attempt is made.  When things get kinky in
       someone's module I can stab my finger at it an say "What's going
       on in here?  Why did you rewrite the blah-blah function?"  It's
       one thing to say "please program nice" and quite another to hand
       someone a big stack of detailed information about what I consider
       to be "nice code".


       A quick note about the copyright status of this document...

       Ok, so it doesn't make a whole lot of sense to copyright
       something and then upload it on the largest BBS in the world.
       The reason I'm marking it up this way is to retain the rights to
       the larger work that this is a part of.  Obviously you can copy
       it back and forth on your hard disk and even print a copy on a
       printer.  Sure-- give a copy to a colleague.  But definitely DO
       NOT upload this anywhere but in NanForum and do not incorporate
       it verbatim in your own conventions manuals.  I really do need to
       maintain control of this thing.

       It has been uploaded to start a hopefully on-going discussion
       thread on programming conventions, with side-threads on the
       problems people have with subcontractors and multiple programmer
       projects.


                     Copyright (c) 1989, Yellick Computing
       



                                      BUILDING SOURCE CODE LIBRARIES   2



                              C O N S I S T E N T

       Complete consistency is one of the hardest parts of source code
       management.  Programming techniques evolve over time, and the
       demands of each individual application often force you to alter
       your conventions.  Despite the inherent difficulty you must give
       it your best shot and stay with it.  If you end up with bad, bug-
       ridden code it will be easier to fix if it's at least
       consistently bad and bug-ridden.

       If you are working with multiple programmers or programs written
       over a long period of time, every minute spent on maintaining
       consistency will pay off ten times over in debugging, maintenance
       and modifications.

       Here is a list of conventions I follow very strictly.  I attempt
       to enforce these conventions on all who write code for me.  The
       more consistent the code the easier it is to read and maintain.
       Many of my conventions are designed to help a program editor's
       search and replace functions get more "hits".  If you write
       sloppy and inconsistent code you'll have a hard time tracking
       down every occurrence of a problem.



                                    **  *  **

       True Story...  Once after presenting this seminar a fellow asked
       me if so-and-so ever did programming for me.  I had never met
       this fellow, and the other programmer in question had never told
       him that he worked for me.  But just from reading the following
       conventions he was able to identify him as one of my
       subcontractors.

















                                              --------------------------
                                                      Copyright (c) 1989
                                                       Yellick Computing
      



                                      BUILDING SOURCE CODE LIBRARIES   3



                                   Keywords
                                   --------

       Keywords are in all lower case with no abbreviations.
       Abbreviating keywords is counterproductive and misguided.  Use a
       code compression utility to squeeze a program if size is
       important, but leave the original, debugged version alone.  I use
       lower case for keywords because it feels more natural to type
       that way.  Making them all caps is time consuming and makes them
       STAND OUT TOO MUCH IN THE SURROUNDING CODE, IF YOU KNOW WHAT I
       MEAN.  The language keywords are obvious enough, and there aren't
       that many.  Keywords are not as significant as the application
       specific parts of your code, so why make them stand out so much?
       Finally, the human eye can distinguish between lower case letters
       much more easily and rapidly than the uniform and sometimes
       nearly identical upper case letters.


                           Memory Variables & Names
                           ------------------------

       Memory variable names are in all lower case.
       e.g.  foobar= 1234

       Extremely short variable names imply that the scope of the
       variable is very brief.  One letter variables are never used to
       control large loops or pass global information.
       e.g.  i= 5  && Must be local

       Array names always end with an underscore so you can distinguish
       them from regular memory variables.  It also makes the subscript
       easier to see in dense code lines.
       e.g.  item_[7]= "ALEX"

       Variable assignments have the equals sign ( = ) right up against
       the variable; equality comparisons have a space on either side of
       the equals sign.  This allows you to search for variable
       assignments without getting "hits" on IF and DO WHILE lines.
       e.g.  x= 321  v.s.  if x = 123











                                              --------------------------
                                                      Copyright (c) 1989
                                                       Yellick Computing
       



                                      BUILDING SOURCE CODE LIBRARIES   4


       Important, global memory variable names follow a naming
       convention that places them into functional groups.  The
       following prefixes have significant meanings in my source code:

            lib_  Library constants or flags
            cnf_  Configuration parameters (end-user can change)
            sys_  System install parameters (only for the programmer)
            prn_  Printer controls
            pag_  Page margins
            clr_  Screen color and attribute controls
            key_  Keyboard inkey() codes
            scr_  Screen saves

       Local memory variables follow a less rigid naming convention that
       helps identify their data type or origin.

            u_    End-user responses to prompts, non-scalar
            dte_  Date data types if lots of conversion is nearby
            txt_  Character strings if lots of conversion is nearby

       A bit of elaboration is in order.  By "non-scalar responses" I
       mean answers that are difficult to validate or verify, but still
       need to be used for program flow control.  The u_ warns anyone
       looking at the code that the variable assignment came from an
       end-user at run-time.  When debugging at run-time I know to check
       the contents of a u_ prefixed variable, it is more likely to be
       the cause of problems.

       The DTE_ and TXT_ prefixes indicate that the variable was
       assigned as a date or character type on purpose, or was converted
       to that type.  This cuts down on the confusion that almost always
       occurs when several variables are converted from one type to
       another.  For example, the end-user may be prompted for a date,
       which is validated and also converted to a character string for
       display purposes.  The code fragment might look like the
       following.

            u_begin= GetDate(5, 10, "Beginning when?")
            if empty(u_begin)
              return
            endif
            dte_begin= MakeValid(u_begin)
            txt_begin= "Beginning " +dtoc(dte_begin)
            DispStats(txt_begin)

       Contrast the above code to the usual D1, D2, D3-style variable
       naming cop-outs.  Sometimes I spend more time thinking up good




                                              --------------------------
                                                      Copyright (c) 1989
                                                       Yellick Computing
       



                                      BUILDING SOURCE CODE LIBRARIES   5


       variable names (or changing all references to bad ones) than it
       takes to actually write the code.


                            Procedures and Functions
                            ------------------------

       Procedures and function names that I create are made "proper", to
       distinguish them from keywords.
       e.g.  MyFunction(date())

       I prefer to write FUNCTIONS over PROCEDURES whenever possible.
       There is no advantage to this other than being easier to type and
       nicer looking in the source code.  Compare these lines.

            do FooBar with "ABC", "DEF"

            FooBar("ABC", "DEF")

       To Clipper there is no significant difference, especially since
       there is no return value.  If the FOOBAR routine ever needs to
       return something no changes are necessary if the call is already
       set up like a function.

       Many Clipper programmers use the following guidelines for
       determining when to use FUNCTION over PROCEDURE.

       Procedures perform tasks and are called when the side effect of
       calling the routine is desired.  Procedures do things like
       printing reports and processing data.

       Functions are called when a return value is desired.  Functions
       never alter the environment outside of their own source code.
       Functions do things like date conversions and validating data
       entries.

       These guidelines have merit, that's why I mention them here.
       Programs which follow these guidelines are somewhat easier to
       read because you can tell things about the program flow from the
       way the calls are made.  I know my flow well enough that I don't
       need the formal definition in the code.  Well-chosen function and
       variable names go a long way toward source code readability.

       All procedures and functions declare their scratch variables
       PRIVATE to avoid conflicts.  Use of PUBLIC and especially
       inherited variables is avoided whenever possible.  Parameters are
       passed by value.  Exceptions:  See the above discussion about the
       naming conventions for global variable prefixes-- lib_, cnf_,



                                              --------------------------
                                                      Copyright (c) 1989
                                                       Yellick Computing
       



                                      BUILDING SOURCE CODE LIBRARIES   6


       etc.  The prefix tells you what the variable is and hopefully its
       parentage.

       Inherited variables (those passed down to sub-procedures in the
       hierarchy) are too much trouble and are to be avoided, period.
       If you have too many parameters to pass efficiently then develop
       a special naming convention and DOCUMENT them in the procedure
       which creates them, and MENTION THEM IN COMMENTS in EVERY sub-
       procedure which references them.  And for gawd's sake don't be
       altering the values!

       All procedures and functions have a header describing their
       purpose and calling requirements and have some kind of marker
       where they officially end.  Don't rely on looking for the first
       RETURN statement to mark the end of a procedure or function.
       Although multiple RETURN statements violate structured
       programming rules, sometimes it's just too convenient to issue a
       RETURN instead of additional flags and loops.

       Many of my library procedures and functions make heavy use of the
       pcount() and type() functions to allow extremely flexible
       parameter lists.  Do not be alarmed to see the same function
       called with zero, one, two or three parameters and different
       variable types.

       Flexible functions should be designed to react logically and
       consistently to the parameters passed to them.  Once again I
       throw structured programming rules to the wind and gain coding
       speed and flexibility.  Writing flexible functions that are
       elegant and reliable is somewhat of a black art.  If you do it
       right you can speed and efficiency.  If you do it wrong you
       create a debugging nightmare.


                                   Databases
                                   ---------

       References to database names are in all capitals and always use
       the alias prefix.  References to field names are made proper.
       e.g.  CUSTOMER->LastName

       Never, ever use the work area numbers or letters with the SELECT
       command.  Database flow is hard enough to track without obscuring
       the intent with  "select 1"  or  "select C"  or other nonsense.
       When you see a line like  "select VENDOR"  you know exactly what
       is going on.  Always use the alias when selecting work areas.





                                              --------------------------
                                                      Copyright (c) 1989
                                                       Yellick Computing
       



                                      BUILDING SOURCE CODE LIBRARIES   7


       I don't use the M-> alias on memory variables because I'm so
       fanatically consistent about using aliases on field names.
       Additionally, using M-> gets to be a real bother and makes the
       code hard to read.


                                  In General
                                  ----------

       Avoid writing lines that extend beyond the visible right margin.
       (An exception is when defining report headings, I know they
       usually extend way over).  The purpose is obvious--  it's easy to
       miss what you can't see.  Use the semi-colon line continuation
       symbol and indent multiple lines to be readable.

            do while (VENDOR->Category = u_cat) ;
                     .and. (VENDOR->State = u_state) ;
                     .and. .not. eof()

       Those using dBASE on slow machines may be complaining that such
       constructs slow the interpreter down.  Yes, it does.  Tough.
       What's a few tenths of a second compared to the debugging time
       you will waste panning back and forth in the editor looking for
       problems?

       On a related note, I also avoid writing long lines of text to the
       screen.  I do this partly so the lines fit entirely on the screen
       in the editor.  Just as importantly, it's much easier on the end-
       user if they don't have to read 70+ columns of text.  It's hard
       to follow, especially when written in typical programmer grammar.

                 The XMP function which you are executing via
                 the previous NAMSQUAT menu.  Is not
                 available. Please refer to the PLUMPA config
                 screen or re-run the INITSYS installation
                 routine from DOS (but not from the DOS
                 shell).  Press any key to continue. <beep!>

       Logical levels are indented two spaces.  I don't use tabs because
       in some text editors they expand and shoot everything over to the
       right edge of the screen and make printed source code harder to
       read.  Two spaces seems to be sufficient to keep the logical
       nesting straight when reading the code.  The default eight
       characters per tab is way too much space.

       Very Important Note to Lazy Programmers:  Don't skip adjusting
       the indentation when you add or remove a large logic level!  I've
       had to clean up messes resulting from such sloth too many times.



                                              --------------------------
                                                      Copyright (c) 1989
                                                       Yellick Computing
       



                                      BUILDING SOURCE CODE LIBRARIES   8


       Compilers won't let you get away with really serious errors, but
       most interpreters will.

            do while .t.
            if DBF->Amount = 0
              *
              * about 600 lines of code
              *
            endif
            skip
            enddo
            return

       The above code is a time bomb waiting for some innocent (or even
       the original) programmer to make an edit somewhere in the middle.
       Buy a dedicated source code editor that can shift blocks of text
       by columns.  Some editors can indent and adjust your source code
       automatically.  Also, buy a code analyzer and sick it on every
       piece of code you can find.  Good analyzers will tell you where
       your  IF..END  DO..ENNDO  CASE..ENDCASE  errors are.  dBASE puts
       up with a variety of errors due to its interpreted nature.

       Don't expect files starting with TEMP to stick around very long.
       Assume that an ERASE TEMP*.* is issued when an application is
       exited.

       All procedures and functions within a source code file should
       have an obvious beginning and an obvious end.  The very last line
       of the source code file should have a marker as well.  Here is a
       mini-example with all the code removed.

            ***  File:  BunchaProcs.Prg

            procedure FirstProc
            return
            * end proc FirstProc

            function FuncOne
            return []
            * end func FuncOne

            procedure SecondProc
            return
            * end proc SecondProc

            * eof BunchaProcs.Prg





                                              --------------------------
                                                      Copyright (c) 1989
                                                       Yellick Computing
       



                                      BUILDING SOURCE CODE LIBRARIES   9


       Between each procedure or function I place a full screen width
       line of dashes so when I'm scrolling through a long file I can
       see where the logical breaks occur.

            function SomeThingOrOther

            return answer

            * end func SomeThingOrOther
            *--------------------------------------------------*

            procedure ThisOne

            return

            * end proc ThisOne
            *--------------------------------------------------*

       All source code files should have a comment on the last line
       which contains a chr(12) form-feed character.  You should also
       stick these between logical divisions in large procedures.  This
       may look unusual in your word processor, but it allows you to
       batch print the files with page ejects in the right spots.




























                                              --------------------------
                                                      Copyright (c) 1989
                                                       Yellick Computing
       



                                     BUILDING SOURCE CODE LIBRARIES   10



                              Now It's Your Turn
                              ------------------

       This was a bit long winded, but I wanted to get all the
       conventions listed.  I've spent many years refining them, and
       only since the Summer '87 release of Clipper can I say that I'm
       completely happy with them.



       Please contribute to the discussion thread.  If something I
       mentioned in here strikes you as odd or outrageous by all means
       take me to task!  The only way to improve such conventions is to
       attack them constantly.  I know this because every new programmer
       I work with bitches for a week or so.  And not surprisingly, they
       are often CORRECT, so I make a change in the conventions.


                          What are your experiences?
                         ADD A COMMENT TO THE THREAD!


                 Do you have a prepared conventions document?
                                  UPLOAD IT!


                      Will you write one this afternoon?
                          UPLOAD IT WHEN YOU'RE DONE!






















                                              --------------------------
                                                      Copyright (c) 1989
                                                       Yellick Computing
       


                            An Advertising Trailer

       -----------------------------------------------------------------
       Ladies and gentlemen, the bills they must be paid.  Please take a
       quick look at the following product information.  You have to be
       curious about the commercial products of an outfit that has a
       conventions maniac like Craig Yellick at the helm.
       -----------------------------------------------------------------

       *  Introduction to Clipper for dBASE Programmers

       *  Printer Control Function Library

       *  User Interface and Screen Control Library


       General Comments about all of our products:
         o  Unconditional, unlimited money-back guarantee.
         o  Products are in heavy use all over the WORLD...

               Japan           Australia      Canada       Sweden
               United Kingdom  Netherlands    Mexico       Italy
               Hong Kong       Kuala Lumpur   Suadi Arabia

         o  Outstanding documentation:  Printed, spiral bound,
            indexed, reference tables, source code.
         o  Well structured source code, a joy to read.
         o  These are NOT code-generators.
         o  100% Clipper, no C and no assembler.

       $95 each, includes everything.  (Outside USA/Canada/Mexico please
       add $15 for airmail shipment).

       Free literature on request.  Send name and address or give us a
       call.  Phones answered full business day, both coasts. (7am-7pm
       Central Standard Time)    612 473-1805

       Sample/Demos available for all products, send $5 (USA, $8
       abroad).  The price can be applied to any future purchase.

       -----------------------------------------------------------------
       Coming Soon (as in, by mid-April '89 we are absolutely SHIPPING)

                                    bugArry
                              The Array Debugger

       This is the first of a series of programmer tools, all priced to
       be an unbelievable bargain.  Exact pricing has not yet been
       determined, but it will make you very happy.  The tools will be
       sold a la carte-- buy only the components that you need.

       -----------------------------------------------------------------
       Yellick Computing  *  509 Maple Square  *  Wayzata, MN 55391-1036
       (612) 473-1805                                     (612) 473-1805
       -----------------------------------------------------------------
      



                            Introduction to Clipper
                   (for dBASE Programmers and Clipper Users)



       Do you dread adding the "new guy" to the development team, the
       guy who thinks he's hot with dBASE but has never touched Clipper?

       Are YOU the "new guy" (or gal) who feels you'll never absorb all
       the Clipper intricacies?  Do you want ammunition for the next
       time some equally novice person tries to "explain" something to
       you?

       -----------------------------------------------------------------

       This is the  ONLY reference guide written especially for people
       with dBASE backgrounds making the move to Clipper.  Also targeted
       at Clipper programmers who know they are missing something but
       can't find the right resource.

       We have documented every command and function DIFFERENCE between
       dBASE and Clipper.  We have developed numerous EXAMPLES of
       Clipper's new and unique features.

       We EXPLAIN IN DETAIL why Clipper does what it does, why it is
       different from dBASE.

       And best of all:  We include a step-by-step guide for CONVERTING
       large dBASE applications for use with Clipper.

       Includes a huge manual and a diskette with a sample Clipper
       application and a FREE FUNCTION LIBRARY so you don't have to
       "reprogram the wheel" on you first application.

       Function library contains numerous handy functions that every
       Clipper application can use.

       On top of the regular guarantee we offer something even more
       outrageous:  You will save the cost of this guide on your first
       Clipper application.  You will save MORE than the cost if you are
       converting a large dBASE application to Clipper.  You can't loose
       on this one.

       -----------------------------------------------------------------

       Established Clipper Programmers:  Don't skip this.  Even someone
       already programming in Clipper will gain VALUABLE INSIGHTS, and
       not just some new tricks.
       



                     Printer Control Function Library



       What?  You don't have a library dedicated to coding reports,
       controlling the printer, handling errors, dealing with the end-
       user, and managing printer control codes?

       You are wasting too much time.

       -----------------------------------------------------------------

       Imagine being able to send reports to the printer, a text file,
       or to the screen... under end-user control, at RUN-TIME, without
       changing a SINGLE BYTE of source code.  If you use our highly
       efficient library functions it will happen automatically.

       Imagine never having to type @ PROW(), PCOL() SAY ever again.  We
       have replacements for these and other commands.  Once you see our
       method you will never go back to the "old" way.

       Imagine run-time printer errors that are handled transparently by
       the library.  Cancel reports, retry and so on.  You can regain
       control of your application, even if the end-user turns off the
       printer in the middle of the report.

       If that were all we provided, the Printer Control Function
       Library would be a pretty good deal.  But that's not all we
       provide.  Also included are manual sections on how to layout
       better looking reports, how to implement various features of the
       library in your existing applications, and much, much more.

       The manual IS NOT just an alphabetic listing of the functions and
       a few pathetic comments about how they are used.  We have
       developed a comprehensive product that addresses the ENTIRE
       PRINTING PROCESS, from laying out the report, coding it,
       presenting user options, sending control codes, handling run-time
       errors.

       -----------------------------------------------------------------
       



                   User Interface and Screen Control Library


       Ok, so you might admit that you aren't handling the printer as
       well as you could be, but you definitely have a nice set of user
       interface routines...

       Ours are better.

       What arrogance.  Audacity.  How cheeky.  (Just love that on-line
       thesaurus).

       -----------------------------------------------------------------

       This is the only library you can buy that has been designed from
       the ground up to be an integrated user interface system.  After
       years of doing it mostly right and sometimes totally wrong, we
       started from scratch and have developed a system that drives
       Clipper like it was meant to be.

       Pop-up, pull-down, light-bar, multiple-choice-- it's all in here.
       We provide bullet proof routines for all the common prompting
       situations:  String, date, numeric, logical, multiple choice and
       so on.  Then we add a top-notch screen color/attribute handler,
       several highly efficient replacements for "@ ROW(), COL() SAY", a
       unique context-sensitive "repeat the previous response" function,
       an on-screen ruler that will make complex layouts much easier,
       (get a free copy of the ruler by downloading RULER.ARC in
       NanForum), and several other innovations.

       Most of the functions calculate row/column coordinateds
       FROM CONTEXT.  You don't have to pass them as parameters.

       As with the Printer Control Function Library, the manual is the
       very best you will ever see associated with a Clipper add-on
       product, especially at our low price.  It's much more than just a
       quick run-down of the library functions.  You get details on the
       theory and practice of a good user interface.  Real-life horror
       stories of the wrong way to do things.

       -----------------------------------------------------------------

       Don't forget the guarantee.  We just told you our library does
       things BETTER than whatever you are currently doing.  Take up
       the challenge.  Buy it.  You can't loose.  Either you get the
       best interface lib on the market, or you send it back for a
       refund, happier than ever with "your way".
       
