While at Sun he created training courses on a diverse range of Java topics, developed the original Sun Certified Java Programmer and Developer exams, and presented at JavaOne and other conferences on Java and Java performance topics.
Today, Simon is president of Dancing Cloud Services, LLC., based in Westminster Colorado, and he provides training, course development, and mentoring services in Java, Scala, JavaScript, Python, Go, along with design, and software architecture topics. Simon is equally comfortable offering training in classroom, recorded video, and live, remote-access, formats.
One of the features that distinguished Java from a majority of mainstream languages at the time it was released was that it includes a platform independent threading model.
The Java programming language provides core, low-level, features to control how threads interact: synchronized, wait/notify/notifyAll, and volatile. The specification also provides a “memory model” that describes how the programmer can share data reliably between threads. Using these low-level features presents no small challenge, and is error prone.
Contrary to popular expectation, code written this way is often not faster than code created using the high level java.util.concurrent libraries. Despite this, there are two good reasons for understanding these and the underlying memory model. One is that it's quite common to have code written in this way that must be maintained, and such maintenance is impractical without an understanding of these features. Second, when writing code using the higher level libraries, the memory model, or more specifically, the “happens-before” relationship still guides how and when we should use these libraries.
This workshop presents these features in a way designed to allow you to perform maintenance, and write new code without being dangerous.
One of the features that distinguished Java from a majority of mainstream languages at the time it was released was that it includes a platform independent threading model.
The Java programming language provides core, low-level, features to control how threads interact: synchronized, wait/notify/notifyAll, and volatile. The specification also provides a “memory model” that describes how the programmer can share data reliably between threads. Using these low-level features presents no small challenge, and is error prone.
Contrary to popular expectation, code written this way is often not faster than code created using the high level java.util.concurrent libraries. Despite this, there are two good reasons for understanding these and the underlying memory model. One is that it's quite common to have code written in this way that must be maintained, and such maintenance is impractical without an understanding of these features. Second, when writing code using the higher level libraries, the memory model, or more specifically, the “happens-before” relationship still guides how and when we should use these libraries.
This workshop presents these features in a way designed to allow you to perform maintenance, and write new code without being dangerous.
One of the more troublesome parts of creating good quality software is how we handle problems that interrupt the “happy path”. Exacerbating this problem, most of our design methodologies don't seem to offer much advice on the topic. In this session we'll investigate some general categories of failure and consider the macro behaviors that are appropriate to each and where–in terms of the call stack–those actions should be taken.
The discussion will compare the strengths and weaknesses of the most common ways of representing failure: sentinel values, exceptions (both Java's checked variant, and the more common unchecked approach), and the functional technique based on monads. Along the way, we'll consider the abstraction of error, the consequences of getting this design aspect wrong, and how the design of our APIs might make errors less common in the first place.
One of the more troublesome parts of creating good quality software is how we handle problems that interrupt the “happy path”. Exacerbating this problem, most of our design methodologies don't seem to offer much advice on the topic. In this session we'll investigate some general categories of failure and consider the macro behaviors that are appropriate to each and where–in terms of the call stack–those actions should be taken.
The discussion will compare the strengths and weaknesses of the most common ways of representing failure: sentinel values, exceptions (both Java's checked variant, and the more common unchecked approach), and the functional technique based on monads. Along the way, we'll consider the abstraction of error, the consequences of getting this design aspect wrong, and how the design of our APIs might make errors less common in the first place.