Modernising Legacy SAS SCL / AF Applications
Before SAS Studio, and even EG (but after display manager), there was a desktop application used exclusively for accessing SAS. It was known as Base SAS, and within it there was an application development facility known as SAS/AF.
This enabled point and click development of user interfaces, in a similar way to User Forms in VBA Excel. The application logic was driven by an object-orientated language known as SCL. SCL code was compiled, stored in catalogs, and the resulting application was often stored on a network drive and launched by end users.
It's fair to say these applications were a massive success, as many of them are still alive today - surviving decades of technological evolution! Still, as organisations have matured, the following challenges transpired:
- Security. Especially of source files, and password management.
- Scalability. Deploying SCL apps to each client machine is non-trivial.
- Support. The original developers are usually long gone, and SCL resources are few and far between.
- User Experience. This was an 80s product and.. it shows.
So, what to do about it? These applications are often complex, business critical, and heavily embedded in the SAS infrastructure. Well, as it happens, there is a tidy solution, quick to implement, and keeps everything within SAS. So what is it?
HTML5 SAS Web Apps
Web apps are a natural migration for legacy AF. Secured by your existing enterprise authorisation mechanism (SASLogon), they are highly scalable, easy to support, quick to build, and very user friendly.
When building web apps on SAS, it's super important to separate the frontend logic (the domain of a web developer) from the backend (idempotent, stateless SAS programs). A typical modernisation project will begin by creating UX diagrams, wireframes, and screenshots to mockup the visuals and diagramming the application logic. This means that the gory details of the AF part, ie all the call display()
and call next()
routines (and associated catalog entries) are effectively disregarded, and completely rebuilt using modern design methods and javascript frameworks.
But what about the data logic? All the SLISTS, SCL programs, subroutines and methods? The good news is that much of this can be re-used. The fact is that SCL is based on, and works very similarly to, good old base SAS. This led to the development of the SCL Transcoding Kit, a framework / approach that lets you migrate SCL entries directly over to SAS (eg to run in a Stored Process or Job Execution Service), without the need for an AF License.
The full list of supported functions includes:
clearlist()
Empty a listcopylist()
Copy a listdelitem()
Deletes an item from an SCL listdellist()
Deletes a listdelnitem()
Deletes a named item from an SCL listformat()
Verifies that the specified format is validgetitemc()
Returns a value identified by its position in an SCL listgetiteml()
Returns a value identified by its position in an SCL listgetitemn()
Returns a value identified by its position in an SCL listgetnitemc()
Return a value identified by name in an SCL listgetniteml()
Return a value identified by name in an SCL listgetnitemn()
Return a value identified by name in an SCL listinsertc()
Insert a value into an SCL listinsertl()
Insert a value into an SCL listinsertn()
Insert a value into an SCL listitemtype()
Returns the type of an item in an SCL listlistlen()
Returns the length of an SCL listlvarlevel()
Fills a list with unique values from a table columnmakelist()
Creates an SCL listnameditem()
Returns the index of a named item in a listnameitem()
Returns the name of an item in an SCL listputlist()
Displays the contents of an SCL list in the LOG windowsavelist()
Stores SCL list items in a datasetsearchc()
Search for a value in an SCL list and return its positionsearchn()
Search for a value in an SCL list and return its positionsetitemc()
Store a value at an indexed position in an SCL listsetitemn()
Store a value at an indexed position in an SCL listsetnitemc()
Assign a value to a named item in an SCL listsetniteml()
Assign a value to a named item in an SCL listsetnitemn()
Assign a value to a named item in an SCL listsortlist()
Sorts the items in an SCL list by value or by name
Other than the fcmp
library (referenced in the video above), this kit also lays out the process for exporting all the lists into a database, handling methods (with overloadable signatures), and migrating SCL entries into SAS code (hence, eradicating the use of catalogs).
Do you have legacy AF / SCL you'd like modernised? I'd love to help. You can contact me here: https://www.linkedin.com/in/allanbowe/
Additional resources:
- AF slides
- LinkedIn Article
- UK Forum presentation
- Info on SLISTS