4

I learned to code in OO languages. I've always been interested in design patterns, clean code, etc., etc. - you know the type.

Now at work I'm using a BASIC dialect. Given modern programming values, should we try to carry over these same principles to new procedural code?

I'm pondering the following issues, and I wondering if I'm on the right lines.


Variable Names

Variables are not strongly typed (nightmare!), they're given short names and written in ALL CAPS (why?!) - basically I find them hard to read and they could be anything. Once upon a time, I'm sure XCNT = 1 would have offered performance gains over int_EXISTINGCUSTOMERCOUNT = 1, but we're past that now - surely? I choose the verbose name here.

GOSUB

I want to break down long blocks of code down into multiple smaller blocks. Internally, GOSUB is used (over a FUNCTION) if the helper is not re-usable by other programs / functions. Given its ability to add / modify variables without the safety of scoping (as we know it in the OO world) GOSUB scares me.

This is typical:

GOSUB GET_BEST_CUSTOMER
IF RC = 0 THEN CRT CNAME

But I would write:

rc_GETBESTCUSTOMER = 1 ; !Default exception
str_CUSTOMERNAME = ""
GOSUB GET_BEST_CUSTOMER ; !set rc_GETBESTCUSTOMER, populate str_CUSTOMERNAME
IF(rc_GETBESTCUSTOMER = 0) THEN
    CRT str_CUSTOMERNAME
END

With the caveat that GET_BEST_CUSTOMER would only modify rc_GETBESTCUSTOMER and str_CUSTOMERNAME in 'global' scope.


There's more, but it's all along the same lines. Given the editor of choice (Notepad++), I'd say my coding style makes the code easier to read and understand - therefore easier to maintain. But I'm sure some BASIC die-hard would readily tell me I'm doing it all wrong.

7
  • 3
    I'm not a BASIC coder, but IMO we moved away from this horrible short hand (XCNT) into more verbose phrases for a reason - scalability, maintainability etc. I know your question is about how to do it the right way for Basic but if I was in charge of this project, I'd only do what is right for the team, company and myself so next update is efficient as it can be for me!
    – Dave
    Commented Feb 19, 2013 at 10:06
  • 2
    Can't you switch to a more modern basic dialect like Visual Basic? What kind of environment is this?
    – Doc Brown
    Commented Feb 19, 2013 at 10:12
  • @DaveRook I totally agree. Having spent days trying to understand some existing code (and subsequently wanting to re-write the code my new code will interact with!) I'd argue that there is much time to be saved.
    – Tom Tom
    Commented Feb 19, 2013 at 11:37
  • @DocBrown There's a long term plan to move away from it, but ultimately no - there's a lot of legacy code. The BASIC is limited to lower-levels, including data access and some business logic.
    – Tom Tom
    Commented Feb 19, 2013 at 11:37
  • 3
    What dialect of BASIC are you using? The performance and memory cost of things like variable names and Gosub vs. GoTo vs. Procedure will vary based on this.
    – jfrankcarr
    Commented Feb 19, 2013 at 15:35

3 Answers 3

1

GOSUB

GOSUB was a more disciplined version of GOTO. This is a particularly horrible example of the sort of misuse of GOTO that was once popular. GOSUB is an enormous step up from that, and it looks like your codebase is using labels instead of line numbers for the GOSUB targets, so it really could be a lot worse.

I don't know what dialect of BASIC you're using, and I hadn't ever used FUNCTION in the little bit of BASIC programming I did a long time ago, but if FUNCTION in your dialect of BASIC is anything like a modern language function call, I'd prefer it over GOSUB for new code. In your example code, the proposed replacement was 3 times longer than the 2 line original, so I can't really agree that it's more readable, but I'm guessing that a rewrite of the original using FUNCTION would end up having about the same length and clarity as the original.

Naming

I don't see the point in attaching the type to the front of the variable name. Your long names are an improvement over XCNT, but EXISTING_CUSTOMER_COUNT is more readable (IMO) than running them together and sticking a type prefix on it. You may be running them together due to being used to camelCase, but you can't do camel case in all caps.

1
  • Agreed. FUNCTIONS do exist (and IMO they're certainly preferable - I don't understand the requirement for GOSUBs) and our ALLCAPS naming convention isn't great.
    – Tom Tom
    Commented Mar 14, 2013 at 17:27
2

Variable Names

It wasn't about performance, it was about the system only being able to interpret values with a character length less than some value (8 in most cases). Yes, verbose variable names are now allowed throughout, and use them to your heart's content, but if you get legacy code don't go changing variable names just because you don't like it (as per good coding practice should say anyway). As well, all caps was used since some systems may not necessarily been on ascii standard, nor would some systems output the same print style to the screen, caps is an easy way to solve this since they should all be nearly similar.

GoSub

If you can't protect with scoping, protect with naming. Each subroutine name should be short, that way if you do have to worry about "scoping" variables, you can append the subroutine name to the front or back of the variable, handle being descriptive about the subroutine in the comments, not the name.

Honestly, there's not a major paradigm shift from OOP to Procedural, yes there are some semantic issues, but subroutines are key in keeping your code maintainable and semi-modular, just like classes and methods are there for that same purpose in OOP.

And as always, stay away from GOTO (Dijkstra).

2
  • The naming stuff is very informative - thank you. I do struggle with the notion of short subroutine names (in some instances, at least). By way of a (trivial, fictitious) example, what would you rename the subroutine in the example to? Alas the point remains - introducing a mechanism in place of actual scoping is the way to deal with the issue here. I agree on the final point, too. The tasks I'm dealing with are all very... Procedural. It actually seems quite natural to express them as such.
    – Tom Tom
    Commented Feb 19, 2013 at 15:17
  • Mechanisms to mimic scoping is what the assembly really does anyway, you don't have functions in assembly, you have indirect addressing modes that will go to ram or rom locations and some stack pointer arithmatic. As for subroutine naming, I would aim for setting a coding standard, like 4-5 letter acronym using the letters from the words that would be there, GET_BEST_CUSTOMER becomes GBC or GBCUST, if you have a set subroutine you'll be able to see relation SBCUST, etc... Commented Feb 19, 2013 at 17:28
0

The UniBASIC 9.3 reference manual states a 32 character limit for variable names. Iff the LONGVARS option is active, otherwise it's max two characters per variable name.

Names are case insensitive. Foo, FOO, foo, fOo, … are all the same name. Using all upper case is a tradition from times where machines/systems existed that only had one case for characters and that was usually upper case.

What do you mean by variables not being strongly typed? They are either a number, or a string when the name ends with $.

I didn't find a FUNCTION keyword in the documentation so GOSUB is the way to write subroutines. Then there is CALL and ENTER for subprograms. The only way to define functions is DEF FN which limits function names to one letter and the implementation to one expression.

Naming the return value after the subroutine name is wasting variables. Yes, the number of variables per program also has a limit. Default is 348 names, but this can be increased via the MAXVARS environment variable. The documentation suggests the default was as low as 93 in the past.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.