Subscribe for automatic updates: RSS icon RSS

Login icon Sign in for full access | Help icon Help
Advanced search

Pages: [1]
  Reply  |  Print  
Author Topic: Language Modernization ideas for discussion - Idea 3 - Record setters/getters  (Read 7488 times)
Eric B.
Posts: 10


« on: January 25, 2021, 11:39:54 pm »

Next idea:  I’ll call this one “record field getters and setters”.  The idea is a ripoff of Java beans and C# property getters and setters as applied to BDL record types.

The following code suggests how it might look, given the following record type:
Code
  1. TYPE t_rec RECORD
  2.   Username STRING,
  3.   Active CHAR(1)
  4. END IF
  5.  
  6. FUNCTION (self t_rec.Active SET) (d CHAR(1)) RETURNS ()
  7.   CASE d
  8.      WHEN d = '0' OR d = 'N' LET self = 'N'
  9.      WHEN '1' LET self = 'Y'
  10.      OTHERWISE LET self = 'N'
  11.   END CASE
  12. END FUNCTION
  13.  
  14. FUNCTION (self t_rec.Active GET) RETURNS CHAR(1)
  15.   CASE self
  16.      WHEN 'Y' RETURN '1'
  17.      OTHERWISE RETURN '0'
  18.   END CASE
  19. END FUNCTION
  20.  
  21. FUNCTION (self t_rec) isActive() RETURNS BOOLEAN
  22.   RETURN (self.Active = 'Y')
  23. END FUNCTION
  24.  
  25. FUNCTION test()
  26.   DEFINE r_rec t_rec
  27.  
  28.   LET r_rec.Username = "xyz1234"
  29.   LET r_rec.Active = TRUE
  30.  
  31.   IF r_rec.isActive() THEN
  32.      DISPLAY "User active!"
  33.   END IF
  34. END FUNCTION

Some basics:
  • I invented the syntax for the GET/SET functions modeled after interface functions.  There is no function name – I’m sure the compiler would construct one internally but a function name isn’t meaningful once you specify its purpose as a GET/SET function.  Don’t read too much into this – I’m just making this up and you can likely come up with something cleaner.
  • The function specification includes both a type (a record type) and a field name, assigned to “self”.  “self” is than assigned to put the desired result in the variable.
  • The SET function must accept one parameter of the same type as the field;  the GET function must return one value with the same type as the field.  The compiler checks for this at compile time.
  • Note the data type transformation in Active.  TRUE is converted to CHAR(1), which emits as either “0”, “1”, or null.  That is, the normal type transformations would be allowed (or disallowed) before the SET or after the GET.

Benefits:
  • To me, this greatly improves readability and consistency.  All data layer field mapping code is put in one spot.  The compiler automatically enforces it.
  • In fact, this could potentially be used to get rid of a whole class of dumb data storage errors that likely are common in old 4GL apps, without have to scrub every line of an old app.  You could get the benefits of this mapping by replacing RECORD LIKE mytable.* in a legacy app with a TYPE declaration on that record and the appropriate setter/getter functions.  I could see that being a big plus in migration.
  • Simple storage transformations (i.e. upper casing, encoding/encryption, changing a boolean to “Y” or “N”, etc.) become much easier to code and manage.  No more code like:
    IF blah = 'N' THEN…
    Only to find out that the test fails when the value is null.  Or:
    IF blah = 'Y' OR blah = ‘y’ THEN…
    … repeated ad nauseum because you can’t be totally sure what’s in there.  Or whatever.
  • It should cut way down on common patterns and opportunities for bugs like not testing consistently for nulls.
  • Helps segregate data layer code into a separate module dedicated to it.
Pages: [1]
  Reply  |  Print  
 
Jump to:  

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines