Ask Reuben

Minimal Reproducible Example

Why when I send a small example to support does it not work for them?

What is a reprex?

What is a mvce?

With support issues, you may be asked to provide a “small example” that allow us to reproduce the issue.  It is amazing the number of examples we get that do not allow us to immediately start working on the issue and we have to go back and ask for additional files or we have to modify the program.

There are a number of articles out there that illustrate what is required with these small examples.  These articles include this one at Stack Overflow titled How to Create a Minimal Reproducible Example.  which also includes links to articles such as How to Debug Small Programs .  Another good article is this one on SSCCE,  Short, Self Contained, Correct (Compilable), Example.

Common issues I see with small examples include …

Missing Database Schema File

The example code includes a reference to a database schema file but the database schema file is not supplied!.   For a small example you should be able to replace any LIKE table.column with the actual database types thus negating the need to supply a .sch file

Missing Report Schema Files

A .4rp report files is supplied without  a report data schema (.rdd/.xsd).   Note in the architecture the Data Schema.   .4rp report files go hand in hand with the .rdd / .xsd report data schema.  If you are supplying a .4rp, there should also be  a .rdd (or .xsd file).  It is not needed to run the report but helps if we need to edit the .4rp.

One trap here is you might have your .rdd in a seperate directory (/rdd) but you supply the files separately rather than bundling up in a .zip.   Hence the .4rp does not point to a .rdd  To get around this we normally edit the .4rp in a text editor to remove the location reference to the .rdd / .xsd file and have them both in the same directory.

Incomplete Database Information

The example code has database statements but does not provide anything to create the database and populate it with data.

A good tip here is to use the in-memory database of the SQLite database drivers.  I wrote about this here and it means your example program can contain the CREATE TABLE statements and INSERT or LOAD FROM to populate this database in memory rather than dealing with creating tables and populating data in  a physical database and worrying about configuration to a database.

FGLPROFILE Missing

Your runtime environment uses FGLPROFILE for some configuration and so your example behaves differently with your FGLPROFILE settings than it does when we run it with our default FGLPROFILE.

Also in this area, watch out if you edit directory FGLDIR/etc/fglprofile.  Ideally you leave that untouched and set the environment variable FGLPROFILE to point at your own file(s) and supply that file(s) with your example.

default.4st Missing

Your runtime environment uses presentation styles and has a default.4st somewhere in FGLRESOURCEPATH / DBPATH or you have modified FGLDIR/lib/default.4st that gets loaded as per the load rules.  If you do this you do not need an explicit ui.Interface.loadStyles and so it is easy to forget to provide us this file.

Ideally your small example supplies its own .4st file if necessary that is explicitly referenced with ui.Interface.loadStyles .

default.4ad Missing

Your runtime environment uses action defaults and has a default.4ad somewhere in FGLRESOURCEPATH / DBPATH or you have modified FGLDIR/lib/default.4ad that gets loaded as per the load rules, Like the presentation styles entry if you do this you do not need an explicit loadActionDefaults call and so it is easy to forget to provide us this file.

Ideally your small example supplies its own .4ad file if necessary that is referenced with ui.Interface.loadActionDefaults .

Environment Variables Incomplete Information

Your small example reads certain environment variables via FGL_GETENV but you do not provide us with details of these.  Hence when we run the application it may go down a different path if there is any IF statements etc based on these variables.

Ideally your small example does not make use of any environment variables, expect perhaps to allow the program to run two or more different ways.

Command Line Arguments Incomplete Information

Similar to the above entry, when you run your application you do so with certain command line arguments.

Ideally your small example does not make use of any command line arguments, expect perhaps to allow the program to run two or more different ways.

Images missing

Reports and screens may use images, and these are not supplied.

These often get overlooked and it maybe necessary for us to have the images in order to see the issue, particularly if it involves the way elements in a report or screen are sized.  Also a report will stop if the image file is missing, and this gets noticed if your report file includes a logo that is not supplied.

Also pay attention if you stores images in certain directories.  Particularly with reports, this location may be embedded in the image file name.

Library missing 

Your “small example” makes use of functions in 4gl (IMPORT FGL), c (IMPORT) , Java libraries (IMPORT JAVA) and these libraries are not supplied.

Ideally a small example consists of a single 4gl and has no need for code in such libraries unless the issue relates to the libraries themselves.  If you do utilise libraries as part of your example then remember to include thm

Another issue I see occasionally is development environments where a lot of the underlying Genero commands are hidden and abstracted from the junior developer.  In these environments a developer does not know how to execute …

fglcomp helloworld.4gl
fglrun helloworld

… instead they may do something like …

make
make run

and not know how the Makefile has been constructed.  Always be inquisitive as to what  commands are actually being executed.  This applies also to Genero Studio and Genero Application Server, try and understand what the raw commands being executed on the server are.  This will help in creating standalone small examples.

To create small example what I find useful is having a small starting program that I can then modify to try and reproduce certain issues.  I will start with a program similar to the below and then add to it to try and reproduce the issue I am looking at.   That may involve using certain datatypes, widgets, widget attributes, and Presentation Styles.   This example uses a GRID and an INPUT, I have a similar program that uses arrays, TABLES, DISPLAY ARRAY .  If I need to look at other dialogs such as CONSTRUCT, INPUT ARRAY, or more complex forms I can modify these programs to try and reproduce the issue.

#! example.4gl
MAIN
DEFINE rec RECORD
    field1 INTEGER,
    field2 STRING,
    field3 DATE
END RECORD

    WHENEVER ANY ERROR STOP
    DEFER INTERRUPT
    DEFER QUIT
    OPTIONS FIELD ORDER FORM
    OPTIONS INPUT WRAP
    
    CALL ui.Interface.loadStyles("example.4st")
    CONNECT TO ":memory:+driver='dbmsqt'"
    CLOSE WINDOW SCREEN

    LET rec.field1 = 1
    LET rec.field2 = "Lorem Ipsum"
    LET rec.field3 = TODAY
    
    OPEN WINDOW w WITH FORM "example" ATTRIBUTES(TEXT="Example")
    INPUT BY NAME rec.* ATTRIBUTES(WITHOUT DEFAULTS=TRUE)
END MAIN
#! example.per 
LAYOUT
GRID
{
[l01     ][f01         ]
[l02     ][f02         ]
[l03     ][f03         ]
}
END
END
ATTRIBUTES
LABEL l01 : label1, TEXT="Field 1";
LABEL l02 : label2, TEXT="Field 2";
LABEL l03 : label3, TEXT="Field 3";

EDIT f01 = formonly.field1;
EDIT f02 = formonly.field2;
DATEEDIT f03 = formonly.field3;
#! example.4st 
<StyleList>
  <Style name="Window">
    <StyleAttribute name="actionPanelPosition" value="bottom" />
    <StyleAttribute name="ringMenuPosition" value="top" />
  </Style>
    <Style name="Window.dialog">
    <StyleAttribute name="windowType" value="modal" />
  </Style>
    <Style name="Table">
    <StyleAttribute name="headerAlignment" value="auto" />
    <StyleAttribute name="alternateRows" value="yes" />
  </Style>
</StyleList>

Final point, one of my favourite quotes is …

Nothing spins a geeks propellor like an isolated reproducible example

… If you can provide a small example program that behaves one way with version A of our product and behaves differently with version B of our product, you have immediately piqued the interest and grabbed the attention of our team members.  They know it is a legitimate issue and not a time waster.  They then have something useful that they can use to analyse the issue and test their solution.