Programming languages and what’s next

  • Post category:Programming
  • Reading time:7 mins read

My review of programming languages I learned in during my years in IT.

BASIC

On the Texas Instruments TI99-4a. 

Could do everything with it. Especially in combination with PEEK and POKE. Nice for building small games.

Impossible to maintain.

GOTO is unavoidable.

Assembler

In various variants.

Z80, 6802, PDP 11, System 390.

Fast, furious, unreadable, unmaintainable.

Algol 68

Loved this language. REF!

Have only seen it run on DEC 10. Mainly used in academic environments (in the Netherlands?)?

Pascal

Well. Structured. Pretty popular in the early 90s. 

Again is this widely adopted?

COBOL

Old. Never programmed extensively in it – just for year 2000.

Totally Readable.

Funny (rediculous) numbering scheme.

Seems to be necessary to use GOTO in some cases which I do not believe.

Smalltalk

Beautiful language.

Should have become the de facto OO programming language but failed for unclear reasons.

Probably because it was way ahead of it’s time with it’s OO base.

Java

Totally nitty gritty programming language.

Productivity based on frameworks, which no one knows which to use.

Never understood why this language was so widely adopted – besides it’s openness and platform independency.

Should never have become the de facto OO programming language but did so because Sun made it open (good move).

Far too many framework needed. J(2)EE add more complexity than it resolves.

Always upgrade issues. (Proud programmer: We run the application in Java! Fed up IT manager: Which Java?)

Rexx

Can do everything quickly.

But nothing structurally.

Ugly code. Readable but ugly.

Some very very strong concepts.

Php

Hodge podgy language of programming concepts and html.

Likely high programmer productivity if you maintain a stark discipline of programming standards. Stark danger of creating unmaintainable crap code mix of html and php.

Python

Nice structured language.

Difficult to set up and reuse.

Can be productive if nitty gritty setup issues can be overcome.

Ruby (on Rails or off-track)

Nice, probably the most elegant OO language. Too nitty gritty to my taste still. Like it though.

I would start with this language if I had to start today.

What is next

Visual programming? Clicking building blocks together?

In programming we should maybe separate the construction of applications from the coding of functions (or objects, or whatever you call the lower level blocks of code.

Programming complex algorithms (efficiently) will probably always remain a craft for specialists.

Constructing applications from the pieces should be brought to a higher level.

The industry (well – the software selling industry) is looking at microservices but that gives operational issues and becomes too distrubuted.

We need a way to build a house from software bricks and doors and windows and roof elements.

Probably we need more standards for that. 

Another bold statement.

AI systems “programming” themselves is nonsense (I have not seen a shred of evidence). 

AI systems are stochastical systems. 

Programming is imperical.

In summary, up to today you can not build software without getting into the nitty gritty very quickly. 

It’s like building a house but having find your own tree and rocks first to cut wood and blicks from. 

And then contruct nails and screws.

A better approach to that would help.

What do you think is the programming language of the future? What need should it address?

A brief GraphQL vs REST investigation

  • Post category:Programming
  • Reading time:2 mins read

People around me are talking about using GraphQL, where they position this next to or opposed to REST API’s. I was not sure how these compare so I needed to find out.

In short, from 10000 feet, GraphQL is an alternatief for REST API’s for application programming interfaces. GraphQL provides more flexibility from several perspectives. Read more about that in the link below.

However, it requires a specific GraphQL server side infrastructure. This is probably also going to be a problem for large scale adoption. You can build a GraphQL client in a number of programming languages, but to serve as a GraphQL provider you need one of the few server side implementations.

So, a big benefit of REST API’s is that is is an implementation-independent interface specification that is easy to implement on your server side middleware. GraphQL would require your middleware to integrate one of the GraphQL implementations, or build one natively. This could be a matter of time and adoption, but currently I do not see a broad adoption.

 Apollographql-rubyJunipergqlgen, and Lacinia are GraphQL implementations. 

I found the article that best describes what GraphQL is on the AWS blog Comparing API Design Architectures – AWS (amazon.com). (I am not an AWS afficionado, it is just that the article best addressed what I wanted to know.)

Testing the IBM Workload Scheduler API

  • Post category:Programming
  • Reading time:3 mins read

We see REST API’s appearing on many middleware tools. In a previous post I have talked about the REST API on MQ. I have also been playing around with the IBM Workload Scheduler (IWS) REST API.

The API is very promising. You can use it for automation of IWS administration, but also in your daily business operation.

A major thing that the API lacks is support for certificate-based authentication. This is incomprehensible since the application that provides the API is a normal Liberty application, just like we MQ Web application providing the MQ API’s that I mentioned before. Apparently the people in Hursley do a more thorough programming job then their IWS brothers (not sure where they are located after IBM made the silly move to outsource IWS development to HCL).

Here my Python program to do the most rudimentary test through the API: get engine info.

(I have left in some code commented out that I used to test certificate authentication.)

import requests

print("tested")


print("hello") 

host = "https://yourserver.com:1603"
# your server
baseapiurl = "/twsz" 
# your request url - engine name is your instead of YRTW
getrequest = "/v1/YRTW/engine/info"
api_url = host + baseapiurl + getrequest
print(api_url)

request_headers = {
    'Content-Type': 'application/json'
}

#cert_file_path = "/your/pythonprograms/dwc-client-ssl-xat.crt"
#key_file_path = "/your/pythonprograms/dwc-client-ssl-xat.privkey"
#cert = (cert_file_path, key_file_path)
# data = {'api_dev_key':API_KEY,
#        'api_option':'paste',
#        'api_paste_code':source_code,
#        'api_paste_format':'python'}

data = """{
  "hasDatabasePlan": true,
  "locale": "string",
  "timezone": "string",
  "timezoneEnable": true,
  "roleBasedSecurityEnabled": true,
  "type": "string",
  "version": "string",
  "apiLevel": 0,
  "featureLevel": 0,
  "hasModel": true,
  "hasPlan": true,
  "enableRerunOpt": true,
  "engineType": "string",
  "ltpStartDate": "2022-02-16T13:48:01.978Z",
  "ltpEndDate": "2022-02-16T13:48:01.978Z",
  "dbTimezone": "string",
  "planTimezone": "string",
  "workstationName": "string",
  "domainName": "string",
  "synphonyRunNumber": 0,
  "synphonyScheduledDate": "2022-02-16T13:48:01.978Z",
  "synphonyBatchManStatus": "string",
  "synphonyStartOfDay": 0,
  "masterDomain": "string",
  "masterWorkstation": "string",
  "synphonyFileName": "string",
  "synphonyPlanStart": "2022-02-16T13:48:01.978Z",
  "synphonyPlanEnd": "2022-02-16T13:48:01.978Z",
  "synphonySize": 0,
  "synphonyStartTime": "2022-02-16T13:48:01.978Z",
  "synphonyFound": true,
  "enableLegacyStartOdDayEvaluation": true,
  "dbStartOfDay": "string",
  "rdbmsSchema": "string",
  "rdbmsUser": "string",
  "rdbmsType": "string",
  "rdbmsUrl": "string",
  "fipsEnabled": true,
  "regardlessOfStatusFilterEnabled": true,
  "executorList": [
    {
      "application": "string",
      "namespace": "string",
      "version": "string",
      "factory": "string",
      "supportedOS": "string",
      "stoppable": true,
      "restartable": true,
      "labels": {
        "additionalProp1": "string",
        "additionalProp2": "string",
        "additionalProp3": "string"
      },
      "id": "string",
      "xsdResourceName": "string",
      "cancelSupported": true,
      "supportedWorkstation": "string"
    }
  ],
  "auditStore": "string",
  "auditModel": "string",
  "auditPlan": "string",
  "licenseType": "string",
  "licenseJobNumber": 0,
  "licenseSendDate": 0,
  "wasFirstStartDate": 0,
  "licenseError": "string"
}"""



try:
    response = requests.get(api_url, auth=('ZOSUSER', 'PASSWORD'), verify=False, headers=request_headers)
    # use this whenever they get certificates working
    #response = requests.get(api_url, cert=cert, verify=False, headers=request_headers)

except requests.exceptions.RequestException as e:
    print(e)

#response.json()
print('---------')

print(response)
print('---------')
print(response.json())
print('---------')

Testing the MQ REST API

  • Post category:MQProgramming
  • Reading time:3 mins read

I have been playing around with the MQ REST API. It works very well. Also certificate-based authentication work out of the box.

Of course, you are doing something that MQ-fanatics might find horrific: reliable messaging over an unreliable protocol. They are somewhat right. By no means can MQ provide assured message delivery over an unreliable HTTP protocol. When using this in application, make sure you handle all error situations. For example, when you do not get an http response, you don’t know whether the message was successfully delivered or not. You application has to cater for such situations. Some call this idempotence.

Here is my small Python program that illustrates how you can use the MQ REST API.

import requests
import json
import sys

class MQWebManager:
    baseapiurl = "/ibmmq/rest/v1/messaging"
    
    def __init__(self, ep, ak, cert_file_path, key_file_path):
        self.endpoint = ep
        self.apikey = ak
        self.cert = (cert_file_path, key_file_path) 

    def apideleterequest(self, qmgr, queue, msgid):
        # operation = POST or DELETE
        resourceurl = self.endpoint + "/ibmmq/rest/v1/messaging/qmgr/" + qmgr + "/queue/" + queue + "/message"
        request_headers = {
            'messageId': "'" + msgid + "'",
            'Content-Type' : 'text/plain;charset=utf-8' ,
            'ibm-mq-rest-csrf-token' : 'somevalue',
            'correlationId' : ''
            }
        data = {}
        response = requests.delete(resourceurl, data=data, cert=self.cert, verify=False, headers=request_headers)
        return response

    def apipostrequest(self, qmgr, queue):
        # operation = POST or DELETE
        resourceurl = self.endpoint + "/ibmmq/rest/v1/messaging/qmgr/" + qmgr + "/queue/" + queue + "/message"
        request_headers = {
            'Content-Type' : 'text/plain;charset=utf-8' ,
            'ibm-mq-rest-csrf-token' : 'somevalue'
            }
        data = 'hello from apipostrequest'
        print('resource url: ', resourceurl)
        response = requests.post(resourceurl, data=data, cert=self.cert, verify=False, headers=request_headers)
        return response



print('---------')

#cert_file_path = "/yourpath/yourcert.crt"   
#key_file_path = "/yourpath/yourcert.privkey"

cert_file_path = sys.argv[1]
key_file_path = sys.argv[2]

m1 = MQWebManager("https://mqweb.yourzos.com:12345","", cert_file_path, key_file_path)

#put a message on the queue
response = m1.apipostrequest("QMGR","YOUR.Q.NAME") 
print(">>>", response.status_code, response.json)

print(response.headers) 

print(response)
#retrieve msgid from the message we just put there
msgid = response.headers['ibm-mq-md-messageId']
print(response.headers['ibm-mq-md-messageId'])

#delete that message we just put there
response = m1.apideleterequest("QMGR","YOUR.Q.NAME", msgid) 
print(">>>", response.status_code, response.json)



print('---------')

Try out you IBM Z Open Automation Utilities

  • Post category:Programming
  • Reading time:1 mins read

Please find a mini Python program to check out your IBM Z Open Automation Utilities installation and get started with it’s possibilities.

Find more information in the IBM documentation.

#import logging_config
import sys
from zoautil_py import datasets 


# total arguments
n = len(sys.argv)
print("Total arguments passed: ", n)

def printname(dsn):
    print("Testing python and IZOAU")
    print("Dataset " + dsn + " exists: " + str(datasets.exists(dsn)))

if (n > 2):
    print("Pass 1 parameter (dataset name) or less (use default dataset name)") 
elif (n==1):
    printname("MYDATA.DATASET")
else:
    printname(sys.argv[1])

Invoke with:

python testibmzoau.py DATASET.NAME

Programming languages for z/OS

  • Post category:DBAOTMProgramming
  • Reading time:9 mins read

In this post I will discuss the programming languages you find on z/OS, and what they are generally used for.

COBOL

The COBOL programming language was invented 60 years ago to make programs portable across different computers. The language is best usable for business programs (as opposed to scientific programs).

COBOL is a language that must be compiled into executables, load modules.

       IDENTIFICATION DIVISION.
       PROGRAM-ID.
           COBPROG.
       ENVIRONMENT DIVISION.
       DATA DIVISION.
       PROCEDURE DIVISION.
           DISPLAY "HELLO WORLD".
           STOP RUN.                   

PL/I

PL/I was developed in the mid-1960s with the aim to create a programming language that could be used for business as well as scientific applications.

Like COBOL, PL/I programs must be compiled into load modules.

   World: Procedure options(main);
          Put List( 'Hello world' );
          End World;

Assembler

Assembler is still around. In the past business applications were developed using Assembler. Nowadays you should not do that anymore. But there are still a lot of legacy assembler programs around on the mainframe.

In the old days, assembler was often used to implement tricks to achieve things that were not possible with the standard operating system, or other programming languages. This practice has created a problematic legacy of very technical programs in many mainframe application portfolios.

The modern stance is that Assembler program should be regarded as severe legacy, because it is no longer maintainable and Assembler program are a risk for operating system and middleware updates.

Furthermore, we find Assembler programs in modifications to the z/OS operating system and middleware.

z/OS offers a number of points where you can customize the behavior of the operating system. These so-called exit-points oftentimes only have interfaces in Assembler. Like application programs in Assembler, z/OS exits in Assembler are a continuity risk. Not only because nobody knows how to program Assembler anymore, but even more so because these exit points make use of interfaces that IBM may (and wishes to) change at any point in the future.

IBM is actively removing Assembler-based exit points and replacing these where needed with configuration parameters.

The bottom line is that you should remove all home-grown Assembler programs from your z/OS installation.

TEST0001 CSECT               
         STM   14,12,12(13) 
         BALR  12,0         
         USING *,12         
         ST    13,SAVE+4     
         LA    13,SAVE       
         WTO   'HELLO WORLD!'
         L     13,SAVE+4     
         LM    14,12,12(13) 
         BR    14           
SAVE     DS    18F           
         END   

Java

The language invented by a team from Sun in the 1990s with the goal to develop a language that could run on any device. Support for Java on the mainframe was introduced somewhere in the beginning of the 21st century.

Java programs do not need to be compiled. They are interpreted by a special layer that must be installed in the runtime environment, called the Java Virtual Machine.

The execution is (therefore) far more inefficient than COBOL and PL/I. So inefficient that running it on the mainframe would be very expensive (see section Understanding the cost of software on z/OS, MLC and OTC). To address this IBM invented the concept of zIIP specialty engines (see section Specialty engines), which makes running Java on the mainframe actually extremely cheap.

public class HelloWorld {
   public static void main(String[] args) {
      // Prints "Hello, World" in the terminal window.
      System.out.println("Hello, World");
   }
}

C/C++

The C/C++ programming language was added to z/OS in the 1990s as a more mainstream programming language for mainframe applications and tools.

The process of compiling a C source program into a load module is basically the same as it is for COBOL.

#include <iostream>
using namespace std;

int main() 
{
    cout << "Hello, World!";
    return 0;
}

JCL

JCL is the original “scripting” tool for the mainframe. It is hardly a programming language, although it has been enhanced with several features over time.

JCL looks very quirky because it was design for interpretation by punch card reader, which you can still see very clearly. The main purpose of JCL is to start a program or a sequence of programs.

Many of the quirky features of JCL have very little use in today’s z/OS programming but are maintained for compatibility reasons.

I mentioned before that there can be tens of thousands of batch jobs running on the mainframe. You should realize that mean you will easily have thousands of JCL “programs” as well to run these jobs.

Nevertheless, we could do with a more accessible, more modern alternative.

//JOBNME5  JOB AB123,PRGRMR,NOTIFY=MYUSER1,MSGLEVEL=(1,1),
//       CLASS=1                   
//RUN       EXEC PGM=COBPROG <- PROGRAM TO RUN  
//* PROGRAM WAS PUT IN HERE --v           
//STEPLIB  DD DISP=SHR,DSN=MYUSER1.LOADLIB 
//SYSPRINT DD SYSOUT=*                    

Rexx

The story goes that the Rexx programming language was created by an IBM developer, Mike Cowlishaw, who was totally fed up with the only available language for scripting at that time, the CLIST language. In one night he is said to have developed Rexx. When he showed it to his colleges next day, they were immediately very enthusiastic.

On z/OS Rexx fulfils the same role a Unix scripts in Unix environments. It is mostly used by system administrators to automated all kinds of administration tasks.

You can run Rexx interactively under TSO/ISPF, but you can also use it in batch jobs.

Rexx is somewhat similar to PHP, I find. It has the same sort of flexibility (and drawbacks).

/* Main program */
say "Hello World"

Unix shell script

z/OS has a Unix part, which is complying to POSIX standards, and hence also support a command shell like any Unix flavor. With the shell scripting language you can automate all kinds of Unix processes.

Shell scripts can also be ran in batch jobs.

#!/bin/bash
echo "Hello World"

SAS

Many z/OS users exploit the SAS language from the company with the same name. SAS is used for ad hoc programs and reporting, besides its analytical capabilities.

On the mainframe SAS is often used to process the measurement data that z/OS generates, and create all kinds of usage and performance reports.

proc ds2 libs=work;
data _null_;

  /* init() - system method */
  method init();
    declare varchar(16) message; /* method (local) scope */
    message = 'Hello World!';
    put message;
  end;
enddata;
run;
quit;

Easytrieve

The programming language Easytrieve from CA/Broadcom you also find regularly in z/OS environments. This language is used by application support staff to create ad-hoc programs, and by advanced end-users to to create business reports from application data. 

Other languages

There are many other languages available on z/OS. But the ones discussed here are the mainstream languages. Languages like Python and R are emerging for analytical applications, JavaScript for use in in Node.js, PHP for web applications. Rocket Software, the company that supports a ported version of Python for z/OS, also have a supported version of PHP and Perl.