Blog-Archiv

Samstag, 19. September 2015

JS Poor Developer's IDE

For learning JavaScript I sometimes wanted to have a text field directly in the web-browser where I can write and try out scripts. You can do this any time at JSFiddle, or use the console input of the debugger in your browser (press F12), but let's see whether we can write such a "Poor Developer's JavaScript IDE" as web-page.

JS Evaluation by the Browser

Normally any JavaScript is loaded via a <script type="text/javascript"> HTML element, either in the <head> or in the <body> of the page. There could be either an URL or the script text itself inside. In case URL this must be "relative" to the page, that means it must at least reside on the same server. In any other case the browser will deny and report a cross-site scripting attempt.

Consequently this means that any script the browser loads and executes comes from the server where the page resides. But I want to write a script directly in the browser, and execute it, without having access to the HTTP server where the page resides!

JS has a facility for that, it exposes the JS interpreter of the browser via the global and infamous eval(script) function. Infamous because it is a bad practices to write scripts which generate and execute other scripts. This could easily break out of control and result in endless loops. So do not use eval()! I will use it here exceptionally to achieve my scripting IDE, because it gives me the opportunity to catch interpretation errors.

You could also put the script text into a <script> tag, and add this to the HTML document's head. This would make the browser execute the script. JS source for that is on bottom of this page.

Just Write and Run

Here is a very short HTML page that lets you write and run JS code.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!DOCTYPE html>
<html>
<head>
  <title>Run JavaScripts from Textarea</title>

  <script type="text/javascript">
    var run = function(script)  {
      eval(script);
    };
  </script>

</head>

<body>

  <div style="text-align: center;">
 
    <textarea id='script-text-area' style="width: 100%;">alert("Hello World!")</textarea>
    <br>
    <input type="button" value="Run" onclick="run(document.getElementById('script-text-area').value);"/>
    
  </div>
    
</body>

Select this text and copy it, then create a source file like e.g. /home/me/js-ide.js, open it with some text editor, paste the text and save the file. Then load it into the browser by writing file:///home/me/js-ide.js into the address line on top, press ENTER.

Here is what you should see:


Change the text to "Goodbye World" and press "Run" to get the feeling.

Write, Run Encapsulated, see Errors

There are two major flaws in this very basic IDE.

  1. The scripts you write will "aggregate", that means any variable you define will be globally in the window object, and might affect subsequent scripts. All scripts that are started should run encapsulated, so that the global context (which is implicitly the window object) is not used, or at least not unintended.

  2. We can not see error messages of the JS interpreter when we have mistakes in the script.

Encapsulation

JS has no access modifiers, thus just basic encapsulation mechanisms like scope-visibility can be applied. This is about avoiding global variables, one of the biggest threats against source reliability.

In any script, be it embedded or in its own file, if you write

foobar = "My name is foo-bar";

you will have created a global variable named foobar (which you want to avoid).
If you write

var foobar = "My name is foo-bar";

you also have created a global variable.
But if you declare variables within a function body, it is different.
If you write

var foo = function() {
  var foobar = "My name is foo-bar";
};

you avoided the global variable! But mind that if you write

var foo = function() {
  foobar = "My name is foo-bar";
};

you again created a global variable, because you forgot to prepend var.

So we can not prevent the script writer from "polluting the global namespace", but we can when (s)he uses var to declare variables. So please use var any time you declare a variable in JS, this is a generally good practice!

What we can do is enclose the script from the textarea into an anonymous function and call that function after declaration. This looks like the following.

(function() {
  var foobar = "My name is foo-bar";
})();

And to do even better we also declare the strict mode at head of the script. This will prevent variables without leading var.


"use strict";
(function() {
  // here goes the script text
})();

In such a capsule we will pack any script that we fetch from the text-area.

Read about the revealing module pattern for more information about this kind of encapsulation.

Error Reporting

The JS interpreter does not give good information about errors in scripts (is browser-specific). Nevertheless I want to make them visible. When the eval() function throws an exception, I can catch that and render it in some logging area.

  try {
    eval(script);
  }
  catch (error) {
    log(error);
  }

For that to work we need (1) a log(message) function and (2) a logging area.

The Enhanced IDE

Here is the source code for the enhanced "Poor Developer's JavaScript IDE", including the log() function and a logging area.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<!DOCTYPE html>
<html>
<head>
  <title>Run JavaScripts from Textarea</title>

  <script type="text/javascript">
    var run = function(script)  {
      try {
        eval(
          "'use strict';\n"+
          "(function() {\n"+
            script+
          "\n})();"
        );
      }
      catch (error) {
        log(error);
      }
    };
    
    var log = function(text) {
      var logText = document.createTextNode(text);
      var logLine = document.createElement("p");
      logLine.appendChild(logText);
      
      var logArea = document.getElementById("log-area");
      logArea.appendChild(logLine);
      logLine.scrollIntoView();
    };
  </script>

</head>

<body>

  <div style="text-align: center;">
    <p>Enter some JavaScript text, then press "Run".</p>
    
    <textarea id='script-text-area' rows="25" style="width: 100%;"></textarea>
    <br>
    <input type="button" value="Run" onclick="run(document.getElementById('script-text-area').value);"/>
    
    <p>Use <code>log("my log")</code> to write to the log area below.</p>
    
    <div id='log-area' style="text-align: initial; border: 1px solid gray; height: 20em; overflow: auto;"></div>
    <input type="button" value="Clear Log" onclick="document.getElementById('log-area').innerHTML = '';"/>
    
  </div>
    
</body>
</html>

When your browser denies eval(), you could also use the following JS function to execute the script text. But mind that here you won't receive an exception when the script is erroneous. This creates a script tag and adds it to the HTML document's head, which makes the browser execute it.

    var run = function(script)  {
      var encapsulatedScript =
          "'use strict';\n"+
          "(function() {\n"+
            script+
          "\n})();";
      var scriptElement = document.createElement("script");
      scriptElement.type = "text/javascript";
      scriptElement.appendChild(document.createTextNode(encapsulatedScript));
      document.head.appendChild(scriptElement);
    };

Here is the page for trying out. I added an erroneous script to show whether error messages are displayed.

Enter some JavaScript text, then press "Run".


Use log("my log") to write to the log area below.

Such a mini-IDE is useful when you want to present JavaScript example source and provide the possibility to immediately start it.

Have fun!





Donnerstag, 17. September 2015

Visitor Pattern for Test Data in Java

A visitor is one that comes in and is not interested to know how the exhibition is organized. He wants to see the pictures. So the gallery guide leads him through all floors and rooms.

  • Finally the visitor
    • did not miss any picture because of the guidance, and
    • did not have to care about finding the next picture, room or floor of the gallery,
  • and the gallery owner
    • can always put the pictures into dry and cool rooms because visitors do not expect them to be at a certain place.

The Visitor Design Pattern is made for iterating through structures like lists, trees or graphs, without having to know how to get to the next item, thus providing great re-organization freedom for the data structure. Moreover it is a technique that allows type-safe iteration through "heterogenous" structures, that means the items can be of different type: paintings, photos, sculptures. At any item, the visitor would be called with its visit(item) method that declares the type of the currently visited item: visit(painting), visit(photo), visit(sculpture). Thus the visitor pattern is great for avoiding the instanceof operator.

The pattern defines two participants:

  1. the visitor and
  2. the data structure to be visited.

The visitor has to implement an interface, while the visit-able structure must provide an accept(visitor) method by which the visitor can enter the gallery.

The following article rolls out an example Java application that shows how test data can be organized and visited for different purposes in a unit test.

Test Data Set

The concept is to have

  • the id of an UI-field and
  • an intended value for that field

stored together in some visit-able data structure. This structure could be first

(1) visited by a visitor that puts the values into the according UI-fields (e.g. using Selenium).

Then the test would press the "Save" button and reload the UI. Without anticipating any persistence medium like database or filesystem, it then could secondly

(2) visit the structure by a visitor which asserts that the values match those in the according UI-fields.

This would be a meaningful unit test. The two visitors would have different tasks to do, but use the same iteration mechanism to perform their task. The advantage is that you don't need to duplicate the test data for (1) insertion and (2) assertion.

Here is the first outline of the data structure. It wraps a simple array of test data tuples (without duplicates, thus it is called "Set"). The term entity is used as synonym for what we know as "database record".

/**
 * Represents a set of test-data tuples.
 */
public class TestDataSet
{
    /**
     * Abstraction of a test-data tuple.
     */
    public abstract static class FieldAndValue
    {
        public final String fieldId;
        
        protected FieldAndValue(String fieldId)    {
            this.fieldId = fieldId;
        }
    }

    public final String uiEntityIdentifier;
    private FieldAndValue [] fieldsAndValues;

    /**
     * @param uiEntityIdentifier
     *         the "UI natural key" for the entity the test-data should go into,
     *         we want be able to re-load the entity by that key for assertion.
     *         For creating and re-loading the person "John Doe" it could be f.i. "Doe".
     * @param fieldsAndValues the test data tuples.
     */
    public TestDataSet(String uiEntityIdentifier, FieldAndValue [] fieldsAndValues)    {
        this.uiEntityIdentifier = uiEntityIdentifier;
        this.fieldsAndValues = fieldsAndValues;
    }
}

As you might have noticed, the FieldAndValue class does not contain a value, not even as abstraction, just the fieldId.

Because the tuples will have values of different data-types, I can not provide the value in the abstraction (except maybe as Object, but I want to avoid cast operations as much as possible). Here are my tuple-classes for three types of input fields:

  • textfield,
  • checkbox,
  • chooser (combobox, selectionlist, however you want to call the controls with predefined values)
public class TestDataSet
{
    .....

    /** Text field and value. */
    public static class StringFieldAndValue extends FieldAndValue
    {
        public final String value;
        
        public StringFieldAndValue(String fieldId, String value) {
            super(fieldId);
            this.value = value;
        }
    }
    
    /** Checkbox field and value. */
    public static class BooleanFieldAndValue extends FieldAndValue
    {
        public final boolean value;
        
        public BooleanFieldAndValue(String fieldId, boolean value) {
            super(fieldId);
            this.value = value;
        }
    }
    
    /** Combobox field and value. */
    public static class ChooserFieldAndValue extends StringFieldAndValue
    {
        public ChooserFieldAndValue(String fieldId, String value) {
            super(fieldId, value);
        }
    }

    .....
}

The public fields of this structure are immutable due to their final modifier. This is important to prevent the case that the insertion uses other data than the assertion, these two should be bound tightly together.
(Hint: never make public fields without the final modifier!)

Any constructor of TestDataSet will use instances of these inner classes to build the contents of the data structure.

Data Accept Visitors

The data structure is ready for use now, but it can not be visited. Moreover an interface is needed that defines the types a visitor can visit.

public class TestDataSet
{
    /**
     * Implementers visit test data without having to
     * cast to StringFieldAndValue or BooleanFieldAndValue.
     */
    public static abstract class Visitor
    {
        /**
         * Called before visitation starts. Does nothing. To be overridden for preparing the UI.
         * @param uiEntityIdentifier the uiEntityIdentifier of the TestDataSet to be executed.
         */
        public void init(String uiEntityIdentifier)    {
        }
        
        /** Visits any textfield-bound tuple in the set. */
        public abstract void visit(StringFieldAndValue stringFieldAndValue);
        
        /** Visits any checkbox-bound tuple in the set. */
        public abstract void visit(BooleanFieldAndValue booleanFieldAndValue);
        
        /** Visits any chooser-bound tuple in the set. */
        public abstract void visit(ChooserFieldAndValue chooserFieldAndValue);
    }
    
    .....
    .....

    public void accept(Visitor visitor)    {
        visitor.init(uiEntityIdentifier);
        
        for (FieldAndValue fieldsAndValue : fieldsAndValues)
            fieldsAndValue.accept(visitor);
    }

}

Here we have a type-safe access to the different tuple classes. Every visitor will be able to use the boolean field-value as well as the String field-value without any type-cast or instanceof operator.

The init() method is for performing optional preparations on the UI, e.g. pressing a "New" button, or loading a certain URL. It is not part of the original Visitor Design Pattern.

The accept() implementation is just a simple loop over the items that were passed to the constructor. We could extend it to a tree traversal at any time later.

One thing is missing: also the tuple classes must accept visitors. The visit() implementation always must be in the type that is to be visited. These are the ones declared in the Visitor interface.

public class TestDataSet
{
    ....
    
    /** Base class, holding just the field-id. */
    public abstract static class FieldAndValue
    {
        public final String fieldId;
        
        protected FieldAndValue(String fieldId)    {
            assert StringUtils.isNotEmpty(fieldId);
            this.fieldId = fieldId;
        }
        
        abstract void accept(Visitor visitor);
    }
    
    /** Text field and value. */
    public static class StringFieldAndValue extends FieldAndValue
    {
        public final String value;
        
        public StringFieldAndValue(String fieldId, String value) {
            super(fieldId);
            this.value = value;
        }
        
        @Override
        void accept(Visitor visitor)    {
            visitor.visit(this);
        }
    }
    
    /** Checkbox field and value. */
    public static class BooleanFieldAndValue extends FieldAndValue
    {
        public final boolean value;
        
        public BooleanFieldAndValue(String fieldId, boolean value) {
            super(fieldId);
            this.value = value;
        }
        
        @Override
        void accept(Visitor visitor)    {
            visitor.visit(this);
        }
    }
    
    /** Combo-box and reference-chooser field and value. */
    public static class ChooserFieldAndValue extends StringFieldAndValue
    {
        public ChooserFieldAndValue(String fieldId, String value) {
            super(fieldId, value);
        }
        
        @Override
        void accept(Visitor visitor)    {
            visitor.visit(this);
        }
    }

    ....
    
}

Looks a little repetitive, but is not possible otherwise. The abstract FieldAndValue super-class defines the abstraction of the accept() method, and all sub-classes must implement it and pass themselves to the visitor.

Now it is complete, ready to be used. If you put together all parts of the TestDataSet class now, you will be able to implement test cases. But first we need the visitor that does the insertion, and the visitor that does the subsequent assertion.

Visitors for Insertion and Assertion

Let's assume that we have a class SeleniumTest that provides following basic methods:

  • loadPage(String url) - load given application
  • clickRow(String itemText) - select an entity offered in a chooser-UI

and following field-related write-methods:

  • type(String stringFieldId, String value)
  • click(String checkboxFieldId, boolean value)
  • choose(String chooserFieldId, String itemText)

and following field-related read-methods:

  • String getTextValue(String stringFieldId)
  • boolean getBooleanValue(String checkboxFieldId)
  • String getChooserValue(String chooserFieldId)

Then we could implement the insertion-and assertion-visitors:

public class SeleniumTest extends TestCase
{
    protected void loadPage(String url) {
        .....
    }
    protected void clickRow(String itemText) {
        .....
    }
    
    protected void type(String textFieldId, String value) {
        .....
    }
    protected void click(String checkboxId, boolean value) {
        .....
    }
    protected void choose(String chooserId, String itemText) {
        .....
    }
    
    protected String getTextValue(String textFieldId) {
        .....
    }
    protected boolean getBooleanValue(String checkboxId) {
        .....
    }
    protected String getChooserValue(String chooserId) {
        .....
    }
    
    protected class TestDataInsertVisitor extends TestDataSet.Visitor
    {
        @Override
        public void visit(TestDataSet.StringFieldAndValue f) {
            type(f.fieldId, f.value);
        }
        @Override
        public void visit(TestDataSet.BooleanFieldAndValue f) {
            click(f.fieldId, f.value);
        }
        @Override
        public void visit(TestDataSet.ChooserFieldAndValue f) {
            choose(f.fieldId, f.value);
        }
    }

    public class TestDataAssertVisitor extends TestDataSet.Visitor
    {
        @Override
        public void visit(TestDataSet.StringFieldAndValue f) {
            assertEquals(f.value, getTextValue(f.fieldId));
        }
        @Override
        public void visit(TestDataSet.BooleanFieldAndValue f) {
            assertEquals(f.value, getBooleanValue(f.fieldId));
        }
        @Override
        public void visit(TestDataSet.ChooserFieldAndValue f) {
            assertEquals(f.value, getChooserValue(f.fieldId));
        }
    }

}

You will need to meditate about Selenium and the structure of your UI to implement the ..... methods. But when you're over that, we finally could write a short and elegant unit test, defining your test data just once-and-only-once:

public class PersonUiTest extends SeleniumTest
{
    public void testPersonUi() {
        // construction of test data
        final String uiEntityIdentifier = "Doe";
        final TestDataSet testData = new TestDataSet(
            uiEntityIdentifier,
            new TestDataSet.FieldAndValue [] {
                new TestDataSet.StringFieldAndValue("lastName", uiEntityIdentifier),
                new TestDataSet.StringFieldAndValue("firstName", "John"),
                new TestDataSet.ChooserFieldAndValue("country", "Antarctis"),
                new TestDataSet.BooleanFieldAndValue("internet", true),
                .....
                .....
            }
        );
        
        // insertion of test data
        testData.accept(new TestDataInsertVisitor()    {
            @Override
            public void init(String uiEntityIdentifier) {
                loadPage("createPerson");
            }
        });
        
        click("Save"); // data should be reloaded from persistence layer into UI now
        
        // assertion of test data
        testData.accept(new TestDataAssertVisitor()    {
            @Override
            public void init(String uiEntityIdentifier) {
                loadPage("choosePerson");
                clickRow(uiEntityIdentifier);
            }
        });
    }

}

Here we load a page where we can create a new person. With our TestDataSet instance that defines the person's data we perform the insertion by simply using a predefined insertion-visitor that knows how to bring the data into the UI. The init() override loads the page where we can do this.

Then we click onto the "Save" button and assume that the data get reloaded into the UI. For the assertion we simply call another visitation, using a predefined assertion-visitor that knows how to read data from fields and compare them to the according data values. The init() override loads a chooser page where the created person is selected for editing.

Thoughts about the Visitor Pattern

You might say that this pattern hardcodes and duplicates the data types that are contained in the visited structure. Any time you add another type (FieldAndValue sub-class) to that structure, you also have to declare a new Visitor interface method, and adapt all implementations to it.

You might also say that, although this pattern avoids the usage of the instanceof operator, the resulting code is less understandable than a simple loop that uses instanceof.

You may even say that design-patterns make an application unnecessarily complicated.
Nevertheless applications of this very thin pattern are elegant and type-safe. It is one of the patterns I use really frequently, because it separates the visited structure from the visitor in a way that gives that structure any freedom in maintenance. The visitor implementations will not need to be changed when the test data structure grows from a simple list into a tree or a graph. And that is really valuable.

Only forgetting to adapt the Visitor interface when a new data type is in the structure may create problems. Amazingly the instanceof solution shines in this case, because you could throw an exception when the type is unknown to the iterator:

if (f instanceof StringFieldAndValue)
    ....
else if (f instanceof BooleanFieldAndValue)
    ....
else if (f instanceof ChooserFieldAndValue)
    ....
else
    throw new IllegalArgumentException("Unknown type: "+f);





Mittwoch, 9. September 2015

Three Notorious Software Developer Habits

We software developers write source code every day, or we change or fix it. What we do wrong all the time are basically three things:

  • Repeats
  • Wordlessness
  • Too much

These weaknesses do not worsen things in terms of weeks or months, they do not diminish our short-termed success. But at some point they then strike fundamentally in a way that the code will be thrown away, including all knowledge in it. Even when it was working code.

Repeats

This is about Copy & Paste programming. Every beginner does it, and by that way he/she quickly succeeds in creating modules that actually work. The pain then starts when changes and fixes have to be done, and it turns out that concepts and bugs have been multiplied by Copy & Paste, thus the new concepts and fixes must be applied multiple times.

Moreover, repeats are boring. Who wants to read texts that are full of repeats? You get tired of always seeing the same names and identifiers. You have deja-vu all the time. You generate errors by confusing things, because they all are so similar. Everything seems to be unnecessarily blown up, and you don't take it seriously any more.

Repeats can be everywhere, in method names, variable names, class names, in code sections, even classes and whole packages are copied from each other.

Try to do it once-and-only-once. Stick to the Agile DRY principle. Try to remove repeats wherever you see them. Then everything will be simple, clear, short and precise. This is how it should be.

Wordlessness

This is about not realizing that others do not know what I know. Sounds absurd, but is reality.
And this is also about being both precise and simple, although this sounds like a contradiction.
But first of all this is about lack of communication, or missing willingness to share knowledge. Autism, and people that want even more autists to do software development.

Wordlessness manifests itself in missing // comments and /** documentation */. In the moment when we write source code we are not aware that the things we implement might not be understood any more later. In reality not even their specification will survive the time passing.

And we do not believe that anybody else will have to read and use this source code. A fundamental mistake, but even experienced programmers work that way.

The only way to avoid this is to stick to common sense. Talk to common sense all the time by commenting your code, and making good class-, method- and field-names in a common sense. In comments, do not tell what is obvious by the code itself, tell why you do this or that. Talk about the business logic, not the technical logic.

Make long names, do not use abbreviations and acronyms. Take yourself time to think about significant terms. We would like to read your source code fluently like a book.

Always ask yourself: "Could I understand this source code also a year ahead?". Source code is communication, not compiler directives. Write code for humans, not machines.

Too Much

We do too much. Outcome are many things that are in the way during maintenance.

Best example are all those public setters and getters that nobody needs nor understands. They expose the state of the object and make it vulnerable, and, once existing, it is risky to remove them. They might be used by some dynamically linked plug-in ...

When we created some cool class and it really works, we want to give it the final touch. Then we add and add and add, so that in the end you also can cook coffee with that class - will anybody want to use that :-?

Who told us to implement all those features? Do we get it paid? Why don't we spend some time by documenting the really needed code that we implemented and tested successfully?

Don't do it when nobody asked for it. Stick to the Agile YAGNI principle: You ain't gonna need it! This will make life much easier for all.