“Java is Dead”, “Java is Dying”, “Java is Obsolete” and other variations on the meme of Java mortality appear frequently on line in the IT “press”. These are click-bait, intended to draw your attention to a headline, or get some cheap SEO. For the more complex and nuanced truth about trends in Java usage – look beyond opinions for evidence.
About two years ago, I was working on a project written in the Go language. Go was originally developed by Google in 2007 for internal use, but was later released (open source) for general use. The project I was on was a large enterprise-wide service that collected large amounts of data (and did it well). This article introduces some of the interesting aspects of the language that might entice you to consider it for your own use, while pointing out a few things of which to be aware if you do.
Microsoft’s WPF bindings are a fine piece of technology. They are flexible and powerful, allowing changes to your objects’ properties to ripple through the rest of your application with a minimal amount of coding effort.
by Larry Van Sickle, Senior Software Engineer
AngularJS is a versatile toolset for building browser-based applications.
How can a developer make the elements of a chart clickable using NVD3 in an Angular application?
By Paul Bostrom, Senior Software Engineer
Choosing a programming language for a project is difficult. As technology progresses, new languages emerge exponentially, each one with a particular set of features; others come along that seek to improve existing features, as well as solve new problems. Clojure is a relatively new language, released in 2007 by Rich Hickey. Clojure is a Lisp-like, functional language that runs on the Java Virtual Machine. Let’s look at some of the features that make Clojure a compelling choice.
The Java Virtual Machine
The Java programming language was introduced in 1995 and provided a powerful general purpose programming language. One particular feature it provided was automatic memory management and garbage collection, so that programmers did not have to write code to manage memory like in a C or C++ program. Java also provided an execution environment called the Java Virtual Machine (JVM) to allow programs to be portable across a number of different platforms. For these and other reasons, Java has grown to become one of the most popular programming languages.
The popularity of Java has made the JVM an ideal target for the development of newer programming languages like Clojure. Just as the Java language provided features not available in C or C++, Clojure attempts to provide additional features that Java may not include, while building upon the many features that are included in the Java programming environment. Clojure also provides a number of Java interoperability features to work with the many stable Java libraries in existence. What this means in practical terms is that Clojure code can exist in a variety of forms. Perhaps you just want to write a Clojure program that is simply “glue code” to integrate several reliable Java libraries into a single application. Another option is to create a specialized library in Clojure that Java programs can utilize. Of course, Clojure provides a rich core library that allows the creation of general purpose programs that do not require any direct interaction with existing Java code.
Clojure code is a lot shorter than equivalent code in Java. There are a number of reasons for this, but it’s important to note that the length of the code in a software program has a direct correlation with the cost of developing and maintaining the software. Suppose a Java program is 50 lines, while the equivalent Clojure program is 20 lines, which in my experience is a typical code reduction factor between Java and Clojure. The programmer will spend less time thinking about, writing, and testing the 20-line Clojure program than the 50-line Java program, even though both programs accomplish the same task. One of the reasons Clojure programs are so much shorter is because it has dynamic types, meaning the code doesn’t require a lot of extra statements to declare the various constructs that make up the program. Other factors contributing to the conciseness are its functional programming constructs, as well as its macro system. These will be discussed in more detail below.
Functional programming is a very broad topic, but one of the main concepts is the idea of first-class functions. What this means is that the programming language can define functions that are used as values throughout the program. These functions can interact with other functions by being passed along as arguments or returned as values. This differs from programming in an object-oriented program like Java, where every function (or method) must be contained within an object, which is then passed along as an argument and returned from methods contained in other objects. By allowing functional programming, Clojure lets you define exactly what your program should do without having to wrap everything in unnecessary class declarations.
Immutable, Persistent Data Structures
Clojure forces programs to use immutable data structures by default. While at first this may seem like a limitation of the language, it actually turns out to be an advantage, because it avoids the incidental complexity that is involved with mutable data structures. A data structure created in one part of a program is usually passed along to another part of the program to be used in some other computation. If that data structure can be modified during its lifecycle, it makes the program harder to reason about, and the programmer has to use more mental energy to account for the various transformations that the data might undergo. With immutable data structures, the programmer can take it for granted that the data structure will never change. Immutable data structures are even more important in multi-threaded environments, discussed in the next section.
Advances in technology have brought multi-core processing into all facets of computing, down to the hardware that runs mobile phones. Multiple cores allow programs to create different threads of execution to be performed simultaneously. In many cases, these threads will all want to share the same data structure. In Java there are several tools to synchronize a program across multiple threads, but these tools can be unwieldy and in some cases introduce performance penalties and are hard to diagnose bugs. Clojure provides a number of features to safely and efficiently design multi-threaded programs. One feature was mentioned above: immutable data structures. If data is immutable, there is no need to provide any coordination across threads since the underlying data cannot change. In most cases, however, it is desirable for a program to share some amount of state across its threads of execution. For these instances, Clojure provides a tool called software transactional memory (STM). This is a mechanism similar to how transactions are processed in a database and allows for safe coordination of updates to application data to prevent it from reaching an inconsistent state.
Macros are a powerful feature of Clojure and other Lisps that allow the creation of code that manipulates other code. Stated slightly differently, a macro is code that takes code as input and performs some transformation which returns an expanded version of the code as output. With macros, a program can create new syntax rules and language constructs to make a specific task easier to implement. Macros can even be used to create wholly new languages, known as Domain Specific Languages, which might cater to a particular class of programming tasks.
Hopefully the information in this article has revealed a number of advantages to using Clojure in your next software project. In some cases, just the ability to concisely construct a program is enough of an advantage to warrant choosing Clojure. With additional requirements for concurrent execution, Clojure becomes an even more compelling choice.
by Jerry D. Cavin, Senior Software Engineer
How many times have you coded an equation and the results produced are not what you expected? Then you rearrange the equation and get completely different results! If the computer is calculating correctly, why does it produce incorrect answers? Could it be the ‘Ghost in the Machine?’
Gilbert Ryle’s notion of the ‘Ghost in the Machine’ was introduced in his book, The Concept of Mind, a critique of Rene Descartes’ discussion of the relationship between the mind and the body (the mind-body dualism). The expression has been widely used in the context of a computer’s tendency to make unexplainable numerical errors. Are the errors the fault of the human, or is it the fault of the ‘Ghost in the Machine?’ To gain insight into these mathematical errors made by computers let us examine how the ‘mind’ of the computer views our concept of numbers.
The ‘mind’ of the computer perceives finite number sets. The size of the number set depends on the size of the space where the number is stored. If the number is stored in 8 bits, the number set starts with 0 and ends at 255. One of the bits can be reserved to represent the sign of the value (i.e. + or -). In this case, the numbers that exist are from -128 to 127. Numbers can also be stored in a larger space, but that does not change the fact the ‘mind’ of the computer still perceives finite number sets. So what happens when 1 is added to the maximum value in a finite integer set? It wraps around to the smallest negative value in the set. In our previous example for 8-bit values, when the computer adds 1 to 127 it would give the answer of -128. This overflow, or wrap around error, can occur if you are adding, subtracting, multiplying or dividing. Integer overflow errors are dangerous because they cannot be detected after it has happened. The ISO C99 standard states an integer overflow causes ‘Undefined Behavior.’ This allows compiler manufacturers, conforming to the standard, to implement anything from completely ignoring the overflow to causing the program to abort. Most compilers totally ignore the overflow, resulting in erroneous results being calculated. Depending upon how the integer variable is used, the overflow can cause a multitude of serious problems. If an overflow occurs with a loop index variable, it may cause an infinite loop. If an overflow occurs with a table index variable, the buffer overflow may cause data corruption. Another strange condition can arise with integers that we do not see in the human world. Under some circumstances an equation may give an answer of +0 or it may give an answer of -0. These two values of 0 are the same, but it may cause some confusion. This is a problem to many older compilers; some compilers detect this condition and simply change the answer to +0. Newer compilers use two’s complement mathematical operations and never encounter this issue.
What does your computer do?