Saturday, April 30, 2016

Inventory Reordering Example: What BBL is Good For and What It's Not Good For

"Blockly for Business Logic" (BBL) is not for everything. The case for using this approach can be summarized as:
  • Logic that needs to be customized for the particular organization. If every organization could use the same logic, then there would only be need for one off-the-shelf software solution for every organization, but even small organizations often find they need a high degree of customization to be effective. 
  • Logic that changes relatively often. Every organization that hopes to survive must adapt to changing laws, changing markets and evolving risks and opportunities, but the cost, time and dangers of changing the logic embedded in traditionally-structured software holds back this vital adaptation.
BBL is not intended to be a general-purpose programming language, though. The power of the concept is in its simplifications, but these simplifications mean that there are some use cases it can't handle well or can't handle at all. The following inventory reordering example shows what can be done with BBL and what needs to be handled outside of it.

The example involves determining whether a particular product needs to be re-ordered because inventory is low. On the face of it, it seems that it should be a relatively simple calculation. Many businesses simply create a "reorder point", which is the inventory level where the product is re-ordered. This simple approach has the following problems, however:
  • Shipping costs can be reduced and better volume discounts obtained if re-ordering is done less frequently and in larger shipments.
  • Limited storage space and spoilage restrict the size of re-orders.
  • Demand for particular products can sometimes be quite variable and difficult to predict, for example if Oprah features a product on her television show, making it impossible to be 100% sure that you will always be able to remain stocked in all items.
  • Some products are more important to the business than others and must be re-ordered more frequently if necessary. For example, if a grocery chain runs out of a popular brand of beer even occasionally customers will stop going to that chain, but they won't stop using the store just because once in a while the store doesn't have saffron.
In the example, these problems are handled with the following specification:
  • Products are assigned an "importance" value between 0 and 1, with a low importance, 0.1 for example, being assigned to a product like saffron, and a high importance, 0.9 for example, being assigned to a product like Bud Light.
  • Re-ordering regimens are identified as daily, weekly, monthly or quarterly re-orders. Daily re-orders are only performed for high importance products, and weekly, monthly and quarterly used for progressively less important products.
  • Each product has a "lead time", which is the time from placing the order until it is available for sale. The projected sales during this lead time for each product are calculated and compared to current inventory. For high importance products, the product is re-ordered when the amount on hand is below 115% of projected sales, and for low importance products, it's re-ordered when the amount on hand is below 95% of projected sales.
At the top level, we have two conditions that need to be met, as follows:
The "(is) product reorderable" determines if the product is important enough to be re-ordered more frequently, that is, daily or weekly. The "(is) product needed" determines if the inventory has fallen low enough in relation to the projected sales to be reordered. Both of these are "calculated inputs", meaning that they are defined in BBL. Here is the definition for "reorderable":
The "product importance" is compared to a cut-off value for each reorder type, daily, weekly or monthly, to determine if the product is eligible for re-order for that type of order. All products can be re-ordered if it's a quarterly re-order.

Finally, here is the definition for the "product needed" input:

The product is needed if the quantity in stock is less than the projected sales during the time it takes to receive the product and make it ready for sale, adjusted up 15% if it's a high importance product to reduce the chances of running out in the meantime, or adjusted down by 5% to reduce costs of frequent reordering when it's a product that doesn't matter so much of you run out.

The example shows the part of the process where BBL works well, but it's also necessary to point out what part of the process is being handled external to BBL. The input "projected sales" is a particular example of this. It's an input to the BBL and is calculated elsewhere as follows:
  • Determine the "lead time" for each product--the time it takes from ordering until the product is ready for sale. It includes the time it takes to process the order, the time it takes for it to be filled, shipped and received, and the time it takes to place it "on the shelf" ready for sale.
  • Estimate the cumulative sales of the product during this lead time, taking into account such factors as seasonality and promotions. This requires estimating daily sales and summing them for the lead time period.
The "projected sales" calculation is not suited to BBL calculation. BBL calculates only from "flat" inputs, and the "projected sales" calculation is not flat, because it requires summing over daily projections for a "lead time" number of days that is different for each product. That requires a "loop" and BBL does not support looping in order to achieve simplification.

The projection for a single day could possibly be done in BBL, though, as well as the lead time. These would be inputs to a conventional process, probably SQL, that produces the "projected sales" input to the inventory re-ordering. Whether it's a good idea to use BBL for daily projection and lead time calculations depends on how complex they are and how often they change.

In the example, the BBL can be expected to change relatively frequently in order to "fine tune" the algorithm to maximize cost savings and customer satisfaction. These two factors can be visualized as the two axes of a chart, as follows:
The chart shows a linear relationship between cost and customer satisfaction. It assumes a dollar of cost increase produces a dollar of increased customer satisfaction. A competitive, adaptive business strives to always make this curve more shallow, to get more than a dollar of satisfaction from a dollar of expense. In fact, that is practically the definition of "profit". "Fine tuning" business algorithms such as the inventory re-order calculation is an important way to achieve these gains. The changes which may be considered in the BBL to fine tune the algorithm may include:
  • Changing the "reorder type" options, for example by adding a bi-weekly or bi-monthly reorder type.
  • Changing the "importance" thresholds for allowing re-ordering of products with greater or lesser frequency.
  • Adding additional "importance" thresholds for determining the percentage of projected sales to be applied when comparing to current inventory, and changing those percentages for different importance categories.
Imagine how much more nimble a business can be if it can change these features of the algorithm without software development.

It's true that a conventional software application could be written to allow an analyst to modify these kinds of parameters. I myself have written a number of programs like that. BBL, however, allows greater flexibility as to how the algorithms can be modified without reprogramming. Also, the interfaces to such "configuration" tools, written by different teams over some period of years, tend to be inconsistent, leading to potential confusion and longer learning curves for users. BBL offers the possibility of a single, consistent, and highly flexible platform for development of logic that can be expressed as a flat, functional calculation, plus it facilitates use of the same logic on different software platforms and for different purposes, and migration to new platforms.

Not everything can be expressed in the BBL language, but a lot can be. By using BBL to express and maintain business logic that needs to adapt to changing conditions, an organization can achieve more rapid and more effective response to pressures and opportunities.

Saturday, April 23, 2016

Expenditure Approval Example

The Problem

Businesses and organizations live or die on the efficiency and effectiveness of their processes, and none is more important than procedures to control of expenditures. Improperly authorized spending can bankrupt an organization, but controls that are too burdensome can result in lost opportunities. It's one of the more difficult balancing acts faced by modern organizations in the face of sophisticated fraud schemes and a fast changing world. As a result, expenditure controls are often complex and often need to be updated on a regular basis to meet new threats while also responding to changing needs. For these reasons, expenditure approval procedures present a good case for the use of techniques I'm promoting via Blockly for Business Logic (BBL).

USAF/CAP Example

For my example, I found an online description of expenditure controls used the the United States Air Force Auxiliary Civil Air Patrol in this PDF and implemented the procedure in BBL. The main output is a boolean calculation I've called "expenditure approved" which is true if the expenditure is approved and false if it's not, which looks like this:

Blockly has a built-in feature for adding comments, which look like this:

In Blockly, you add comments by right clicking on a block, which creates a question mark in a blue button on the block. Clicking on the button opens a box for entering the comment. You can hide or show the comment by clicking on the button.

As this example, shows, there are two ways to approve an expenditure. Non-recurring expenditures have a complex approval process, while recurring expenditures are more or less automatic.

The following screen shot looks more closely at the non-recurring approval process:

The green blocks are inputs to this calculation. The first three are boolean inputs that indicate whether the request is documented, whether it's within guidelines, and whether documents have been reviewed. These inputs are generated outside of this logic and may be as simple as having the requester click on check boxes indicating they have been done, or they may involve more complex validations. 

The word "is" in parenthesis is the "type" of the input, and "is" indicates boolean. This is intended to be read by non-programmers, so the use of technical terms like "boolean" is avoided.

There are two forms of approval allowed: written, or online signature using Sertifi. 

Calculated Inputs

Next we look at some inputs that are calculated using sub-modules.


These three inputs are actually outputs from sub-modules. Within this module, though, they appear simply as inputs. BBL is able to figure out which module definitions depend on which other module definitions and perform the source calculations before running the higher-level dependent calculations. Recursion is not allowed. You can't call a module from itself or from any of its sub-modules. It could be implemented, of course, but the whole point is to create a simple way of expressing logic that works for perhaps 80% of business logic and is usable by non-programmers. More complex logic would be implemented outside of this context, either during generation of inputs to this process (preferable, I think) or by implementing custom-designed operations as blocks.

Unlike most programming languages, sub-modules are called without the use of parameters. Again, the point is to reduce complexity for use by non-programmers. All inputs to all modules are global. Because the process is "functional", there are never any local variables, so name conflicts between global inputs and local variables are never a problem. 

Here is the definition of the "approver approved" sub-module:


It checks for individual approver limits. In this simplified example, there is only one approver. If there were a small number of approvers, they might be handled as shown here, though for a large number of approvers it would be handled in a database outside the BBL mechanism and the approver limit would be passed as an input instead of the identity of the approver.

This is the definition of the "level approved" sub-module:

And this is the definition of the "sertifi approved" sub-module:


Unit Tests

When a module is defined, a template for creating unit test cases is automatically generated. In the case of the main module, it looks like this:

Test cases are set up by filling out the controls for a test and saving them. When the tests are run, the output is shown, and if it matches the "expect" value, a green check mark shows, otherwise a red circled X.

These are unit tests, not integration tests, so the inputs that come from sub-modules are not calculated, just entered. Likewise, the inputs used by sub-modules but not used by the main module are not included in these tests. Integration testing will also be required, but that is a separate process.

Generated Code

The immediate result of creating a valid definition is an XML representation of the calculation, for example:

  <output name="expenditure_approved" type="is">
    <conjunction operator="any">
      <conjunction operator="all">
        <input type="is">documented</input>
        <input type="is">within_guidelines</input>
      </conjunction>
      <conjunction operator="all">
        <selection name="form_of_approval">recurring_approval</selection>
        <input type="is">recurring_approved</input>
        <input type="is">documents_reviewed</input>
        <conjunction operator="any">
          <selection name="form_of_approval">written_approval</selection>
          <selection name="form_of_approval">sertifi_approval</selection>
        </conjunction>
        <input type="is">approver_approved</input>
        <input type="is">level_approved</input>
        <input type="is">sertifi_approved</input>
      </conjunction>
      <conjunction operator="all">
        <selection name="form_of_approval">recurring_approval</selection>
        <input type="is">recurring_approved</input>
      </conjunction>
    </conjunction>
  </output>

This XML can automatically be translated into any programming language. For purposes of running the unit tests, it's translated into JavaScript, which looks like the following. This code is somewhat difficult to understand because it's generated in a "functional" style, as one long expression. As I said in a previous post, the functional style has great advantages in terms of being able to validate correctness and for other reasons, but is difficult to work with if you're not using something like Blockly.

expenditure_approved:function(inputs)
   {
      return 
         (
            (
               (
                  (
                     validate(
                        "is", 
                        inputs.documented
                     )
                  ) && 
                  (
                     validate(
                        "is", 
                        inputs.within_guidelines
                     )
                  )
               )
            ) || 
            (
               (
                  (
                     (
                        validate(
                           "form_of_approval",
                           inputs.form_of_approval
                        ) === "recurring_approval"
                     )
                  ) && 
                  (
                     validate(
                        "is", 
                        inputs.recurring_approved
                     )
                  ) && 
                  (
                     validate(
                        "is", 
                        inputs.documents_reviewed
                     )
                  ) && 
                  (
                     (
                        (
                           (
                              validate(
                                 "form_of_approval",
                                 inputs.form_of_approval
                              ) ===  "written_approval"
                           )
                        ) || 
                        (
                           (
                              validate(
                                 "form_of_approval",
                                 inputs.form_of_approval
                              ) ===  "sertifi_approval"
                           )
                        )
                     )
                  ) && 
                  (
                     validate(
                        "is", 
                        inputs.approver_approved
                     )
                  ) && 
                  (
                     validate(
                        "is", 
                        inputs.level_approved
                     )
                  ) && 
                  (
                     validate(
                        "is", 
                        inputs.sertifi_approved
                     )
                  )
               )
            ) || 
            (
               (
                  (
                     (
                        validate(
                           "form_of_approval",
                           inputs.form_of_approval
                        ) ===  "recurring_approval"
                     )
                  ) && 
                  (
                     validate(
                        "is", 
                        inputs.recurring_approved
                     )
                  )
               )
            )
         )
   }

How It's Used

The ultimate question is, how is this used? It may be used in a variety of different ways. It can be used to generate the validations for a web form input, for example, or it can be used to validate a batch file containing expenditure records. It can be used to create a server application that validates via a server protocol. It can be used in multiple ways at the same time. If it's used to generate code for one platform, you can more easily switch to using a different platform, without having to pick the business logic out of the old code and rewrite it in new code.

The biggest advantage, though, is that the logic can be written by someone who is not a programmer, or at least by someone who has only "light" programming skills. Even more important, the logic can be READ by someone who is not a programmer. This allows the code to be "self documenting" and is important for software auditing. 

The Bottom Line

All organizations do battle with the two-headed monster of control versus responsiveness. Yes, an organization needs to maintain tight controls and yes, the organization needs to be flexible and responsive. Doing both things at once requires getting more control over the expression of business logic within the organization, and something like the BBL approach seems to offer a way forward.

Tuesday, April 19, 2016

Wash. Rinse. Repeat.

For many years, bottles of shampoo contained these instructions:
  1. Wash.
  2. Rinse.
  3. Repeat.
This is an example of what is called, in computer science, a "loop". You do something over and over again. Hopefully, at some point, you stop doing it. For example, these might be the instructions for adding up a list of numbers:
  1. If there are no more numbers, quit.
  2. Get the next number.
  3. Add it to the total.
  4. Go to step 1.
This and the shampoo instructions are examples of "procedural" programs. They tell you how to do something. There's another kind of programming, though, called "declarative" programming. With declarative programming, you say what you want done, but not how to do it.

For example, the shampoo instructions might say:
  1. Wash your hair.
This implies that the shampoo user knows that you need to rinse the soap out and possibly repeat the process a certain number of times.

In the case of a computer program, the "declarative" version might be:
  1. Sum these numbers.
It's not difficult to write a programming language that knows what to do when you give it a declarative instruction like this. I worked for 35 years programming in APL, a computer language invented in the 1960s that is largely declarative. The APL instruction for "sum these numbers" is:

      +/NUMBERS
If you've used computer spreadsheets like Excel, you're probably familiar with its declarative command for summing a list of numbers:

      SUM(A1:A5)

Most computers, deep down inside, still need to go through the list of numbers one at a time to add them up, but it's easy to write computer programs that accept declarative instructions like these and are smart enough to fill in all the steps necessary to produce the result.  In short, with declarative programming, you don't need to write "loops". The computer system knows how to do the loops for you. The loops are "implied" rather than "explicit".

Some years ago I had an assignment to convert an actuarial accounting system from RPG to a more modern programming language. RPG is an IBM programming language invented in 1959 and still used today, though in a much evolved form. In its original form, RPG was highly declarative and the looping was implied. At its simplest, you wrote a program that operated on one input record and produced one output record. RPG knew how to run this program over and over again on a lot of different input records to produce a lot of different output records. You didn't have to write this loop yourself.

I realized as I worked on this project that the RPG model of programming involved a powerful simplification. Of necessity, each step of a complex process was broken down into small bits. Each bit took in a record from an input file, did a bit of work, and produced record in an output file that was passed on as input to the next step in the process. RPG worked this way because it was designed to work efficiently on the very limited computers available at the time, but it also had the benefit of making it much easier to create correct programs. A very complex process, broken down in this way, became very manageable. It was something like "mass production" applied to programming. Unfortunately, as computers became more powerful, we started creating programs that weren't so simple. They ended up more artisanal than industrial, and correctness and maintainability suffered. I think we need to revisit the industrial model for maintaining business logic.

One of the most successful declarative languages is SQL, used to retrieve and manipulate data in relational databases. Declarative languages have the same difficulty as functional programming, though, in that they often end up having long "one-line" expressions that can be difficult to work with. The following is a typical expression from SQL:

SELECT DISTINCT Pnumber FROM PROJECT WHERE Pnumber IN   ( SELECT Pnumber FROM PROJECT, DEPARTMENT, EMPLOYEE WHERE Dnum=Dnumber AND Mgr_ssn=Ssn AND Lname=‘Smith’ ) OR Pnumber IN ( SELECT Pno FROM WORKS_ON, EMPLOYEE WHERE Essn=Ssn AND Lname=‘Smith’ );
These "one-liners" can be broken down and indented to make them more readable, but they're still difficult to work with:

SELECT DISTINCT Pnumber
FROM PROJECT
WHERE Pnumber IN   (
      SELECT Pnumber
      FROM PROJECT, DEPARTMENT, EMPLOYEE
      WHERE Dnum=Dnumber AND Mgr_ssn=Ssn AND Lname=‘Smith’ )
OR Pnumber IN (
      SELECT Pno
      FROM WORKS_ON, EMPLOYEE
      WHERE Essn=Ssn AND Lname=‘Smith’ );

Writing and testing SQL statements like this is a huge pain. Blockly visual programming, though, is just the thing for these kinds of expressions. Sure enough, some folks at a German firm have created a Blockly SQL editor. You can see a demo at this YouTube video.

The Blockly for Business Logic (BBL) idea I'm developing uses functional programming to process a single record. It relies on an external process to feed it records and handle results. The inputs would most likely be generated using SQL, and Blockly should be used to define the SQL-derived data inputs.

I've been working on developing examples of what BBL would look like when applied to various business requirements, which I'll share in future posts.

Wednesday, April 6, 2016

Flat World

I love people who believe the world is flat, I really do. They are simple people who live much simpler and happier lives than those of us who "watch the sun going down and see the world spinning round". Flat worlders believe that the flat world rides on the back of a turtle, and if you ask them what the turtle is on, they'll tell you it's another turtle. Turtles all the way down. 

Flat is good, turtles or not. I look at a map, I want to know how to get to Toledo--it's I-75 the whole way. Sweet.

If it's Toledo, Ohio. If it's Toledo, Spain, I need to use a "great circle" mapper that shows a curving arc that my jet will fly from Sarasota, Florida to Madrid airport, because the earth, so I'm told, "she's a-round".

But if I don't need to go to Spain, I-75 will do just fine for me. Why use round when flat will do? You're just making life difficult for yourself. You'll end up wasting a lot of time and you'll miss Monday Night Football.

Software development is like that. Sometimes you need to make round software, no getting around it (!?), but most of the time, flat will do nicely and it's SO much simpler.

What, you may ask, is flat software?

If you ask computer scientists, you'll get different answers, but to me, flat software is software that takes flat inputs and turns them into flat outputs.

OK, so what are flat inputs and what are flat outputs?

Here's a flat input:

Cash Client  Security Type  Transaction Date 
Yes          Stocks         June 7, 1995


Here's an input that's not flat:

Cash Client  Security Type  Transaction Date 
Yes          Stocks, Bonds  June 6-7, 1995

The not-flat input has more than one of each kind of thing.

To work with not-flat inputs or outputs, you need to repeat some part of the program more than once. In programmer-speak, you need to use a "loop" (or at least "recursion"). With flat inputs and outputs, though, whatever you do, you only need to do it once. Computer scientists have a special word for programs like this. It's called "functional programming". 

This is not really new. I'm old enough to remember when almost all programs were flat programs. The inputs were on punch cards. They weren't just conceptually flat, they were ACTUALLY flat. If there were 20 steps in your program, you wrote 20 different programs. Each step took in a punch card, processed it, and punched a new card as an output to that intermediate step. Then you took that card and fed it into the card read with the program for the second step, and it processed that and punched another intermediate result. And so on. This was "functional programming" though we didn't know it at the time.

As computer hardware and software got more powerful, we got away from this model of programming and things got more complicated. I have often wished that we could get back to this simpler "flat world" model where it was possible to be much more certain about what the programs did.

Writing programs that only do each thing once is a HUGE simplification. The Wikipedia article on "functional programming" says that it "makes it much easier to understand and predict the behavior of a program".

But wait, what if you need to go to Spain, uh, I mean, work with a LOT of the same kinds of things? Well, that's somebody else's problem. You only make doors. You don't make the whole car all by yourself.

It's not practical to write everything this way, but wow, if you can use functional programming for the things that change most often, you're WAY better off. I can't prove it, but I strongly suspect that 80% of the parts of software systems that change frequently can be written using functional programming.

There's a problem with functional programming though. When done using text-based languages, functional programs often end up being one long line of code. Some people love it, but you need to be smarter than the average bear. 

Doing it with text-based languages is harder than it needs to be. Here's the program I showed in my last post using a Blockly visual programming editor:

It has flat inputs and outputs! It's a "functional program"! But it's EASY to create using Blockly by dragging and combining colored blocks. It's easy to understand. It's easy to test. It's just EASY.

Easy is good. Just ask a Ford Motor Company door maker. He or she will tell you, "yeah, it's not rocket science". (Actually, they will tell you 这不是火箭科学.)

Bottom line: Don't do hard if you don't have to. Do easy when you can.

Mass Producing Software

Before about 1900, if you wanted to make something, you needed to know how to make the whole thing yourself. If you wanted to make a car, you had to be a car maker. Then along came mass production, and you only needed to be a door maker, so long as there were other people who knew how to make the rest of the car and you could figure out how to work together.

People who work in car factories today don't know how to make cars. They know how to make parts of cars. It's a lot easier to learn to make a door than it is to learn to make a whole car. Besides that, door makers use tools that are designed to be really good at making doors but which can't be used to make steering wheels. 

In software development, scripting is like mass production. A scripting language is a tool that can be designed to be really good at making one part of a computer program, even though it can't be used to make other parts of the program. It's also much easier to learn and much easier to use, so you don't need to be much of a genius to make really good programs.

I've created or helped develop scripting languages at various times in my career. Designing good scripting languages was difficult though. And users still needed to learn the specialized language and type in commands correctly. Then along came Blockly.

BOOM! Blockly simplifies the creating of scriping languages and makes using them 100 times easier.

Here's a calculation I created that does a simplified version of a calculation that was needed in a securities trading system I worked on at my last job, using a scripting language I created using Blockly. It calculates the number of days after a securities transaction before the securities are delivered and paid for. Even if you're not a computer programmer, you can probably look at this and understand what it does. Let's call this Way A. Give it a try.


Here's a program written in a general purpose, text based language, that does the same thing. Let's call it Way B.

settlement_days:function(inputs){
   return 
      (
      validate("boolean", inputs.cash_client) 
      || validate("security_type",inputs.security_type) 
         === "money_market" 
      || validate("security_type",inputs.security_type) 
         === "treasury_bills"
      )
      ? 0 
      : 
         lt(validate("date", inputs.transaction_date),802497600000
         ? 5 
         : 3
}

Some people love doing Way B. Let's call them WayBers. For them, there is no greater happiness than staying up all night typing computer code. WayBers make up about 1/10 of 1% of the population. Mostly they don't get invited to parties. A lot of them are still single by the time they are 35.

A lot more of us are WayAers. We want to finish working on our company's software by 5:00 so we can get home, have dinner with our families and watch the game.

There's a great effort being made just now to get WayAers to learn to write programs using Way B.

It ain't going to happen.

If you want WayAers to write software, you need to do it using Way A, which is the way we make cars and everything else. Once we figure that out, the lion will lie down with the lamb, all the people of the world will come together in harmony, and we will be mentally and spiritually at peace. Or not. But at least we will be able to get our work done so we can go home and watch the game.

Tuesday, April 5, 2016

What Is This All About?

Blockly is a computer software library that lets computer programmers build visual programming editors.

That may sound a bit geeky, and it is. I'm a geek, though, and it's been a long time since I've been this excited about anything. The only way for me to exorcise myself of this unhealthy enthusiasm is to start yet another blog.

It seems like I've been coming to this point in fits and starts for the last 35 years. 

Within just two years of first learning to program, I accidentally invented something that became an overnight phenomenon. I was a developer working on a database product that had a "teletype" user interface. You type a command and press enter, and the computer does something and asks what you want to do next. Microsoft Windows hadn't been invented yet. The personal computer hardly existed. Telephones had wires attached to them and you couldn't carry them around so easily, not very far, anyway, except in Star Trek.

One day I was home sick, lying in bed, testing a change I had made to the program. I'm basically lazy, and as Benjamin Franklin never said, "laziness is the mother of invention". I had to keep typing the same things over and over into the computer, and it got old fast. So I added a feature to the program that captured a series of commands that could be "played back" without retyping them. One day my boss saw me doing that and asked, "What's that?" She was thunderstruck. I was thunderstruck that she was thunderstruck. I never imagined that this was something that no one had thought to do before. It seemed so simple and obvious.

Philips, which is sort of the General Electric of Europe, bought our software and quickly wrote thousands of "programs" using this feature. Because that's what it was, "programming" by using the application commands as a kind of programming language. Ultimately they used it to prepare and win a bid to install a new telephone system for the entire country of Indonesia. The bid had to be printed on paper in those days and filled five pallets. I was spending about 1/4 of my time in Netherlands for several years, which was lovely.

This was obviously a powerful idea. Very soon everyone was doing it. In Microsoft Office it's called "macros". I later learned that there's a term for it in computer science, "scripting". The idea is to create some special purpose language designed to do one particular kind of thing. If you do it well, the language can be much more powerful and much easier to learn than "general purpose" programming languages that can do anything.

Over the years I developed or worked on other scripting languages for various purposes that let non-programmers write "programs". Designing good scripting languages is a challenge, but if you get it right, it's beautiful.

About 10 years ago I became fascinated with something called "Scratch" developed at MIT to help elementary school children learn programming. It's a "visual programming" environment that lets kids create their own computer games by dragging and connecting colored blocks on the screen. It's amazingly easy and fun to use. I wondered, why can't professional software development be this easy? It should be.

At my next job, one of my responsibilities was teaching newly hired developers the APL programming language. I wrote a visual editor modeled on Scratch to help with that. It's really difficult to write a visual editor and I spent way too much time on it and never got a really satisfactory result, which was frustrating.

Two years ago I "retired" when my company laid me off and I couldn't get another job. I went back to Scratch and decided to use it to develop some learning programs for my grandsons. I found myself wishing I had a somewhat better version of "Scratch", that it was a bit clumsy in some ways for what I was trying to do, so I googled "visual programming editor" and, lo and behold:

BLOCKLY!

A guy at Google had developed JUST the thing I needed to do the things I had been struggling to do for 35 YEARS!

AND IT'S FREE!

Free is good, especially if you're "retired".

I've been going crazy with it for two weeks and I can hardly drag myself away from it. In the posts that follow, I will "share my journey". So let the fun begin.