Author Archives: Michael

PanelMatic 101 (Reprint)

Long long time ago, I can still remember, how I used to do Java Swing applications for living. Swing has a lot of strong points, and I really admire its design and architecture. When one needs to make a desktop application in Java, it still rocks. Of course, Swing is not bereft of annoyances. One of these is creating panels with complex layouts.

To my pleasant surprise, I had some Swing-related projects recently. So I revived an old open-source library of mine, which was originally hosted on Kenai.com (yes, that was that long ago). It was called “PanelMatic”, and it enjoyed a mild success back then.

So, PanelMatic is back. It’s using Java 11, it’s on GitHub, and it’s on its way to Maven Central. Below is an slightly modified intro that was published originally at Java.net (yes, that was that long ago).


PanelMatic 101

Every Swing developer knows this feeling: you’ve got the design of a UI panel. It’s the ‘right’ design. It ‘works’. It’s what the user would expect. Hell, it’s even what you would expect had you been the user. But it is going to be an awful lotta’ coding to lay it out in Swing – even before you take into consideration issue like panel re-sizing and localization.

Some developers nest numerous panels to get it working. Some try to “fake it” using the null layout (please, don’t). Others try to fit everything into a single panel and use the GridBagLayout – this involves quite a bit of trial-and-error, as can be seen in this documentary. Some even turn to graphical UI builders, which does not support dynamic panel creation, and whose designs are hard to maintain.

I’d like to suggest a slightly better solution: PanelMatic.

Figure1: Sketch => Code => GUI

PanelMatic allows swing developers to create common UI panels with ease. Panels are built top-to-bottom (or, more precisely, on the page axis). There is an intuitive connection between the way the code looks and the way the created panel will look. Components can be added to the panel with a label and/or an icon (lines 3-7 in Figure 1), or alone (line 9). By default components stretch to occupy all the space they get, but this can be changed using modifiers (lines 9, 10). L_END (stands for “line end”) and GROW (stands for “grow”) are statically imported constants, and are in fact full-blown objects that implement the BehaviorModifier interface – so you can create your own modifiers if you need ’em. Client code can add headers (lines 2, 8) and flexible spaces (not shown). The default implementation uses a pluggable component factory to create all the extra components involved (e.g. JLabels), so you can customize them when the defaults won’t do.

As you’ve probably guessed, panels are built by builders that are obtained by invoking a static method on the PanelMatic class. PanelMatic is designed around an API/SPI approach – all the client code gets to hold is an interface, so the implementation can be changed without affecting client code at all. Builders are pooled, so you don’t have to think twice before asking for one. You can create your own implementation – just implement the service provider interfaces, and point the PanelMatic class to it. This can be done either by code or via a system property.

So this is PanelMatic. Use it to create common UI panels quickly, and use your freed up time to go to more meetings and catch up on some quality powerpoint presentations.

We could stop here, but we’d be missing half the fun.

Beyond Layout

PanelMatic’s approach to building UI panels allows for some surprising improvements over normal layout-based code. Here are some of my favorites.

Customizers, or Listening to All Components

Components are passed to the builder, and eventually get added to the produced panel. But before they are, they pass through a chain of PanelMaticComponentCustomizers, or “customizers”, for short. Each builder has two customizer chains – one that applies to all the panels it builds, and one for the current panel being built. The latter is disposed after the get() method is called. Customizers have a customize method, which gets an returns a JComponent. This allows client code to apply uniform customizations to all components in the created panel, or in the application in general. These customizations can be used for, e.g:

  • Changing the background of the focused component
  • Automatically wrap Scrollables in a JScrollPane
  • Listen to all components in a panel

Let’s look into the latter example. A very common requirement is to have a “save” button enabled if and only if the user changed some data on the screen. This involves listening to all components the user can interact with. Normally, this requires a lot of boilerplate code. Instead, we can create a customizer that adds a change listener to every component added to the panel, and then add a single listener to that customizer. Incidentally, PanelMatic comes with such a customizer out of the box:



ChangeDetectorCustomizer cdc = new ChangeDetectorCustomizer();
panel = PanelMatic.begin( cdc )
	.addHeader( H1, "Song Details")
	.add("Name", txfName)
	.add("Album",txfAlbum)
	.add("Artist",txfArtist)
	...
	.add( btnSave, L_END)
	.get();

cdc.addListener( new ChangeDetectorCustomizer.Listener() {
	@Override
	public void changeMade(ChangeDetectorCustomizer cdc, Object o) {
		btnSave.setEnabled(true);
}});

The ChangeDetectorCustomizer adds the appropriate listeners to all common swing components, so any change made to any component makes the save button enabled. It also recurses down the containment hierarchy, so changes made to JCheckboxes nested in some sub-sub-sub-panel are detected as well.

Localizations

PanelMatic’s PanelBuilders can pass the labeling strings “as-is”, like we’ve seen so far, or use them as keys of a ResourceBundle. Resource bundles are set using static methods of the PanelMatic class itself, and affect all builders generated afterwards. The same goes for ComponentOrientation. So it takes only two lines of code to move from an English left-to-rigth UI to a right-to-left UI in Urdu/Hebrew/Arabic or any of the other RTL languages. That, and someone to translate the texts.

Figure 2: Localizations can be easy (as long as you have someone that can write the texts in the target language)

Building GUI Using Expressions – Anonymous Panels

PanelMatic allows panels to be created and laid out using a single expression. This is contrary to the normal UI construction process, where one first creates the panel, then applies a layout, and then adds sub-components – each in a statement of its own. The problem with statements is that they cannot be combined – they just sit there, one after the other, as if in a shopping list.

Expressions, on the other hand, can be nested and composed with other expressions. They are “first class citizens” in java, and can appear anywhere. So, one can create a sub panel while adding it to a bigger component:

JTabbedPane tabs = new JTabbedPane();
tabs.add( "Tab 1", PanelMatic.begin()
	.addHeader(HeaderLevel.H1, "Tab 1")
	.add("User Name", txfUserName )
	.add("Password", txfPassword )
	...
	.get());

This is somewhat similar to Anonymous Classes (those are the classes with no names that are created, say, when you implement an ActionListener). As anonymous panels can go anywhere, the below code works:

System.out.println("A panel with two JLabels would "
	+ "have a preferred height of "
	+ PanelMatic.begin()
		.add( new JLabel("Label 1"))
		.add( new JLabel("Label 2"))
	    .get().getPreferredSize().height + " pixels.");

On my mac, it says:

A panel with two JLabels would have a preferred height of 40 pixels.

Advanced Customizations

PanelMatic takes the “convention over configuration” approach. Everything can be customized, but you normally don’t need to bother with it. When you do, there are several levels of customizations available: one could subclass a PanelBuilderFactory (easy) or implement the entire stack (builders and factories) or get to some level in between. The exact details are beyond the scope of this article. Bottom line – as long as you can build your panel along the PAGE_AXIS, you can customize PanelMatic to build them. The client code should not be affected when you switch from the default implementation to yours.

Wrapping up

PanelMatic is a small library that allows swing developers to quickly create common UI panels. It helps with localizations and customizations and makes the code creating the UI readable and intuitive. It’s easy to pick up and hard to put down, though I might be slightly biased. Why not give it a go and see for yourself?


https://github.com/codeworth-gh/PanelMatic


Maven: Local is the New Remote

Often I stumble into a case where I need to use Maven, but also use specific, non-published .jar files. In Ant’s world, you’d just throw these in a local directory in the project’s dir. That would be simple. Handling the transitive dependencies of the rest of the jars would not be. Which is why Maven rocks and we should all be using it.

But then there are the local-only jars.

So here is the solution I ended up using: have a local repository in the project’s directory, and deploy the jars there. This way, that repository can go into your version control system (i.e. git repo) and you can use Maven normally. Here’s how it’s done.

a) Create local repository. This is easy, just make a directory, and call it “lib” or something.

b) Register the repository in your pom.xml. Like so:

<repositories>
  <repository>
    <id>project.local</id>
    <name>project</name>
    <url>file:${project.basedir}/lib</url>
  </repository>
</repositories>

c) Add a jar to that repo. This is done from the commandline, using mvn:deploy-file command:

mvn deploy:deploy-file \
-Dfile=/path/to/jarfile.jar  \
-Durl=file:///path/to/the/project/lib/ \
-DgroupId=somegroupname \
-DartifactId=artifactname \
-Dversion=0.9 \
-Dpackaging=jar \

Clarifications:

  1. backslashes (“\”) are for escaping new lines, so the command is easier to read. They can be omitted, along with the newlines (“\n”s).
  2. version 0.9 is as made up as the group name and the artifact id.

d) Use your jar the Maven way by adding it as a dependency

<dependencies>
     <dependency>
         <groupId>somegroupname</groupId>
         <artifactId>artifactname</artifactId>
         <version>0.9</version>
     </dependency>
    ... regular dependencies ...
</dependencies>

That’s it! Pretty simple, and now that I’ve finally written it down, I won’t have to search for this solution over and overt again. Hopefully.


PSPS

At CodeWorth.io we create many web applications. Unless there’s a very compelling reason not to, we’re using the Scala flavor of Play Framework, which we find performant, fun to work with, and generally easy to maintain (static typing FTW! There. I’ve said it.).

Now, Play is a very non-opinionated framework that’s happy to work with multiple database servers, front-end kits, etc. It’s great since it provides us with the flexibility a software studio like us needs. On the flip side, though, we found ourselves re-implementing various functionalities, such as nav-bars, page layouts, and logins (including “forgot password” flow and such). The textbooks say that re-implementing functionality is wrong. That’s only partially right – when you implement a functionality for the fourth time, you’re doing a much better job at it. But enough is enough – one would also like to write some new functionality from time to time.

Enter PSPS. This is a very opinionated application seed. We built it by collecting our best implementations, and then cleaning and brushing them up one more last final time (hmm, actually, we could improve this a bit by…) . PSPS is based on technologies we found to be reliable, and easy to work with and extend. Nothing fancy or surprising, really: PostgreSQL, Bootstrap4, and Slick.

Out of its proverbial box, PSPS supports many features common to web applications:

  • User management
  • Public and user-only sections
  • Navigation bars (including menus, and created using type-safe Scala code)
  • Database connectivity
  • UI Components and functionality (paging, page headers, buttons, JS alerts…)
  • Page templates that support localization, CSRF, informationals, etc.
  • Basic localization
  • Ajax functionality (wrapping Play’s JS Routers)
  • Scripts for deploying on UNIX boxes
  • Documentation (yay AsciiDoc and antora)

We have been testing PSPS internally for a while now, and believe it’s ready human consumption. It might even be good for said human, e.g. if they’re a part of the Play Framework community.

So feel free to try it out – it’s open sourced under Apache v2.0. We’re happily accepting improvements, suggestions, and pull-requests. Hopefully, together we can get the Play community an excellent application seed, so we can all focus on writing new things.

I can’t forget what you did last bp.sync

An evening of hunting memory leaks

‘Twas a lovely early afternoon in the Be’er-Sheva campus of Ben-Gurion University, when AS mentioned that a system based on BPjs is slowing down after running for about ten minutes. I’m generally happy when I get bug reports (it means that people use the software), but this reports sounded like it might be an issue that could be caused by something that may or may not – but quite probably may – be a memory leak.

I don’t like memory leaks. They can be pretty hard to nail down.

We opened JConsole to sample the suspected running JVM, and looked at the memory usage graph for a while. It did go down when the GC kicked in, but never quite to the level it was before. I was toying with the hope that a major GC would kick in an get us back to a civilized level of memory consumption, but for no avail. We were, indeed, looking at a memory leak.

I don’t like memory leaks. They can be pretty hard to nail down. And have a tendency to appear when one needs to write two papers and a PhD thesis.

There was one hope, though – it could be a leak in the using system, and not in BPjs. To find that, we created a simple b-program that waits for external tick events, and then toggles a virtual switch. The program used a static set of a few events (the “new” keyword was never used).

This time, looking at the JVM using Java Mission Control (JMC), there was no doubt:

Where did 119820 extra BEvent instances come from?!

Memory consumptions didn’t look to good either:

After the usual start-up mess, the familiar saw-tooth graph slowly creeping upwards appears. Yep, that’s a memory leak, and in BPjs.

I hate memory leaks. The good news where that I didn’t have any plans for the evening.

We did some extra tests, and noticed that when we release a BProgramRunner instance, the leaked memory is freed. I’ll have to start there.

Seek-a-Leak

The main issue with memory leaks – you need to understand your system in all its levels. Every method and value are suspects. I once hunted a leak in a Java (1.4.2) Swing application, and it turned out that hiding the caret in a JTextPane prior to displaying the JFrame containing it leaked the entire window through references left in the timer mechanism that was responsible for blinking the caret. I chased references using an Eclipse debugger and a block of paper for a three whole days to prove that.

Even more annoying, that bug was already reported when I realized what was going on.

Luckily, BPjs is much smaller than the Java standard library – about 4600 lines. But it relies on Mozilla Rhino, which is also a suspect.

I started from BProgramRunner, and traced all references it had. The JMC report showed that the sync statements and BEvent counts were in the 100Ks, so that had to do something with the runtime of the JavaScript code itself. My hopes for some classroom example of a map somewhere caching instances were gone.

The good news where that I didn’t have any plans for the night, either.

Scopes and Proxies

I was poking around the code drawing blanks, so I started doing some clean-ups and solving old issues, trying to come up with something. Issue #32 caught my eye – I wanted to get rid of the BThreadJsProxy class, but never got around to doing it. OK, issue #32 it is.

At the beginning of BPjs, b-thread could call “bsync” to synchronize with their peers. That method was implemented in BThreadJsProxy, a class whose instances were made available to the JavaScript client code by placing them as a scope in the scope hierarchy under which the JavaScript code runs. Later, other runtime features found their way to this class.

As the BPjs library evolved, we moved everything BP to a “bp” object that BPjs made available to the b-program code in a similar way. That bp object, implemented by BProgramJsProxy, is b-program global, and is not aware of any specific b-threads. The only BPjs runtime feature that required a specific b-thread is the ability to set interrupt handlers. Boilerplate aside, that was the only method left in BThreadJsProxy. Moving it to BProgramJsProxy is non-trivial and seemed unimportant at the time, so this class stayed. With nothing better to do, I’ve moved the interrupt handler mechanism to BProgramJsProxy, thanking whoever decided to add ThreadLocal to Java’s standard library. That’s it – BThreadJsProxy can be removed. The leak stays, but at least #32 would be solved, so the evening won’t be a complete waste of time.

I started removing references to BThreadJsProxy from the runtime and analysis sub systems, when I encountered the code where I’m placing the proxy in a scope, so that the JavaScript code can call it:

    void setupScope(Scriptable programScope) {
Scriptable bthreadProxyScope = (Scriptable) Context.javaToJS(proxy, programScope);
bthreadProxyScope.delete("equals");
<more deletes>

bthreadProxyScope.setParentScope(programScope);
// setup entryPoint's scope s.t. it knows our proxy
Scriptable penultimateEntryPointScope = ScriptableUtils.getPenultiamteParent(entryPoint);
penultimateEntryPointScope.setParentScope(bthreadProxyScope);
scope = entryPoint;
}

I was quite proud of this code when I wrote it – I rarely get a legitimate excuse for using the word “penultimate” in a variable name. But since everyone are suspects now, I looked closer. This code adds another scope to the scope hierarchy within which the JavaScript code runs. That’s cool. The not-so-cool part, is that it runs each time a “sync” is called. So, each time a “sync” is called, another scope is added to the hierarchy, caching things like BEvents. And, effectively, causing a memory leak.

I hate memory leaks.

Removing the BThreadJsProxy class was one of those nice refactors where you delete more than you add. It also solved the leak:

The memory itself also looks better now. After the initial startup mess, the same program occupies less than 32 MiB consistently:


Takeaways

  1. Love thy early adopter. And be prepared to get some serious bug reports when a framework starts to get traction.
  2. Mozilla Rhino is pretty performant even when one uses it badly – that leak was there for a while, and nobody noticed until the system was used to execute long-running tasks for a long time.
  3. Profiling and inspection tools like JMC and JConsole rock.
  4. Don’t leave design related fixes laying around for too long.
  5. Don’t make plans for the evening – you can never tell whether you’ll have to deal with a memory leak.

NetBeans on GraalVM

Last Devoxx I attended an interesting talk about GraalVM, an alternative JVM from Oracle. Among other features, it offers better performance in many cases. So, why not try to run NetBeans on it? The setup is quite easy, and works on my machine (MacBook Pro, running Mojave).

    1. Download GraalVM. I use the community edition. Note that, on a Mac, you may also need to install xquartz. I had it already, and it doesn’t run, but the important part is that it makes some required libraries available.
    2. Unzip and put somewhere. I put it with the rest of the JVMs, at /Library/Java/JavaVirtualMachines/
    3. Get to NetBeans’ configuration file. On a Mac, this is done by right-clicking the application icon, selecting “show package contents”, and navigating to Contents/Resources/NetBeans/etc/netbeans.conf
    4. Open the conf file, and make it point to the Home directory of Graal, by adding the below line:
      netbeans_jdkhome="/Library/Java/JavaVirtualMachines/graalvm-ce-1.0.0-rc9/Contents/Home"
    5. Save, close, relaunch NetBeans.

DONE:

The Curious Case of the Maze Walker and the Cow’s Tail

The Backslash Incident

I guess it’s never a good time to find out your code has bugs. But there are exceptionally bad times to do so. A middle of a live demo is one such example. Immediately after said demo, when you’ve invited the attendees to take your code for a spin, is not too good either.

Case in point: I had the honor of presenting BPjs at a seminar at Harvard School of Engineering and Applied Sciences (SEAS). BPjs is a tool suite for running and verifying programs written in JavaScript, using the Behavioral Programming programming paradigm. In short (very very very short): It’s a paradigm that focuses on how the system should behave, rather than on how its implemented (e.g. objects, functions, or procedures). Because behavioral programs (“b-programs” for short) can be verified against a set of formal specification, BPjs allows writing verified systems in JavaScript. Which is, admittedly, weird. But in a good way.

As part of the above mentioned demo, I’ve created VisualRunningExamples, an application that allows playing with a behavioral program for a maze walker. Users can load and modify the walker’s behavioral model and formal specification, and then run or verify it, using a friendly GUI. It also serves as an example of how to build a program around a BPjs model.

VisualRunningExamples – Maze solution obtained by formal verification of the maze and walker model.

One fun part of VisualRunningExample’s UI is the selection of the maze the walker would roam in. My favorite maze has a cow (created using cowsay, of course). During the presentation I let the walker walk around the cow a bit, and I thought I saw it demonstrating a bad behavior – it seemed like it was going through a wall. I’m not an expert in maze walking, but I assume maze walkers should not do that.

Immediately after the presentation, I looked into this in more depth. It seemed like the walker was moving diagonally. Which it should never do, since no part of the program requests such a move. It ostensibly went from point X to point Y:

_______
<BP(moo) >     @@@@@@@@@   t
-------
        \Y  ^__^    @@@@@@@@
@ @@@@@ X\  (oo)_______
s           (__)~~~~~~~)\/\
@ @@@@@        ||----w~|
               ||     ||

Was this really happening? Using VisualRunningExamples, I’ve added the following b-threads, and verified the program against it. The idea behind this code is that whenever the maze walker gets into a cell, a set of b-threads that look for diagonal entries is spawned. These b-threads blow the program up if they detect a diagonal mode. Pretty neat pattern, I think (reminiscent of LSC’s symbolic charts used to forbid events):

bp.registerBThread("no-diagonal", function(){
    while (true) {
      var crd=getCoords(bp.sync({waitFor:anyEntrance}).name);
    	noEntryNextMove(crd.col-1, crd.row-1);
    	noEntryNextMove(crd.col-1, crd.row+1);
    	noEntryNextMove(crd.col+1, crd.row-1);
    	noEntryNextMove(crd.col+1, crd.row-+1);
    }
});
 
function noEntryNextMove(col, row){
    bp.registerBThread("nenv(" + col + "," + row + ")", function(){
        var evt = bp.sync({waitFor:anyEntrance});
        var newCoords = getCoords(evt.name);
        bp.ASSERT( newCoords.col !== col || newCoords.row !== row, "Diagonal Movement detected");
    });
}

Verification did not find anything wrong, yet that parallel movement is happening, live, in front of my eyes. So, verification is broken too. Highly embarrassing, given that I just presented the tools at Harvard SEAS’ SPYS group. Time to do some runtime verification.

Runtime verification really boils down to adding these b-threads to the b-program (“model”), and running it. Easily done, and we know the runtime works. So, yay, next time mr. maze walker wants to do a diagonal jump, one of these b-threads will catch it red-handed. With an evil grin, I click the Run button.

Nothing. The walker does diagonal jumps like a boss. But only between points X and Y. Luckily, VisualRunningExamples’s UI is fun to play with, so I change the \ to *.

No more parallel jumps, which never really happened. Good news: BPjs’ verification works. As does its runtime.

What Went Wrong

What really happened was that when creating the source Javascript b-program, the Java layer was copying the maze into an array of strings, verbatim. This meant that \ was really an escaped space, which translates to a single space in JavaScript:

jjs$ var s = "\ "
jjs$ "|" + s + "|"
| |
jjs$

The Java UI, on the other hand, displayed the backslash in the maze monitor table. In short: the JavaScript b-program saw a space there, whereas Java saw a backslash. The ostensible diagonal jumps were just the maze walker going from X to Y through an empty cell, that was marked by the Java layer as a \ cell.

Lessons Learned

  • Need to be careful when constructing code from user input (OK, that’s not a very new lesson, more of a reminder really. But still).
  • If you have a suspicion something is wrong in a b-program, BPjs makes it easy to verify.
  • Tooling and UI that make the b-program easy to play with are very important. All in all, I went from having a suspicion to verifying the code in about an hour of casual coding on the couches at an empty student center somewhere in the Harvard campus.
  • Since BPjs uses the same structures for verification and for modeling/execution (namely, b-threads written in JavaScript), it is trivial to share code between the b-program and its formal specification. That’s important, e.g., when one wants to extract data from strings.

My experience with this whole BPjs as a verification platform, is that it enables “casual verification” – it is very easy to create and run verification code, all the tools are there already, and you’re probably in the mindset as well. Compared to re-creating the system by modeling it in, say, PROMELA, it’s much more casual. Not to mention translation errors between model and actual software.

VisualRunningExamples now has a shiny new cow that does not contain any backslashes. I kept the old cow too, but it’s now called “cow (bad)”. Escaping the maze text properly is followed by issue #1.

My NetBeans Favorite Five

NetBeans 8.2 is out, multiple cursors and all, so it’s a fitting occasion to post my five favorite features. First, some background to avoid making a just-downloaded-an-went-a-bloggin’ impression: I’ve been working daily with NetBeans since version 6 (so this post has been brewing for a while). I mostly work with Java (core, Java EE and some Swing) and with HTML/Javascript. I’ve also used NetBeans for Markdown, Scala, PlantUml, Sphinx, Python, Ruby, and making coffee. OK, forget the Ruby part.

When joining the data science team at the Institute of Quantitative Social Science at Harvard, I was happy to see they were using NetBeans as well. Dataverse, our institutional data repository system, is based on Java EE and is developed with NetBeans. It’s currently more than 97K lines of open-source code*. So you can see I have some milage using this tool.

BTW, I’ve worked with the common alternatives (both paid and free) but somehow I always come back to NetBeans. I guess I just don’t like my code being eclipsed.

OK, OK, no need to throw a BadPunException. Let’s get to it:

Little Comforts/Going the Extra Mile

Such as the suggested variable names, auto-pasting traces to the stack trace analyzer, the fact that the stack trace analyzer exists, “view differences” in the Unit testing result pane, get + code-completion generates the proper getter (there’s also a setter, of course).
And then there are the top-of-block popup and the file-too-long label. Love these.

top-of-block extended-label

Additionally, NetBeans includes the required stuff out of the proverbial box. JUnit, Git etc. No need to install manually and decide between various conflicting versions of third party plugins.

Project Groups

Switch quickly between groups of projects. Or, really, working contexts. Since I have a few separate contexts I’m working on in parallel, this feature is a huge timesaver.

Great Java (+EE) and Javascript Support

Great language support for Java (including the next version). Very good Javascript support as well. The code warnings are useful, and the “convert to functional operation” refactoring had taught me some new Java 8 features I was not aware of.

Good support for Java EE features, such as integration and plugins (JPQ modeler etc.). Integration with application servers etc. is easy. There’s also Docker integration, I hear. I’m not using Docker currently. I hope I can still keep my developer license.

Not reinventing the wheel

For example, using Apace ant at the core of the native project type make these projects useful outside of NetBeans too (an anti-vendor-lock-in vendor!).

It Just Works

It does. Srsly. It’s a very dependable tool. And I’m looking forward to seeing it graduating from its Apache incubator.

 

 

*  Count generated using David A. Wheeler’s ‘SLOCCount’.

Some remarks on The Repeated Deaths of OOP

I like people that heartily dislike a programing language paradigm. First, this means they think about how programming is done, rather than about programs only. Second, as far as hate go, hating a paradigm is much better than, say, hating people for being born with the wrong skin color, faith or sexual preference. You can trust me on this one – I’m from the middle east.

But if one is to hate a programing language paradigm, one should do it in an informed way. Case in point: @Loup’s recent post, “the repeated deaths of OOP” (@Greptilian sent me a link to this post not long ago, which was quite nice of him). While this post has some interesting ideas, presented with an envy-inducing eloquence, I’d like to constructively disagree on a few issues. Before I do, let me stress that some of the mistakes in the post are very common, which might have misinformed the fact-checking stage of it. This is the reason I write a post of my own, rather than just an internal answer email. And thanks @Greptilian for suggesting that I write one. Quite nice of you.

OK. Let’s start. (Or, to quote Pascal language, BEGIN)

The post begins by stating that “Current mainstream programming languages all support OOP — except maybe C, and it is no longer that mainstream”. There’s some echo chamber effect in the PL blogosphere, and we should be aware of it. C is very mainstream. It’s currently #2 in the TIOBE index. It has more than double the rating of language #3 – C++. It is true, however, that it is not mainstream while writing web applications. I guess it’s just harder to blog when you have a daytime job (note to self: revisit this statement once I get a daytime job).

The post continues by stating that the it is unclear what “OOP” means, and then describes the eight “fundamental building blocks”, constructed from a survey done by Deborah J. Armstrong. That’s a classic straw-man argument. Why would a survey of a population that can’t agree on anything end up in a definition coherent enough to base a very successful programming paradigm on?

When I learned OOP – Based on Timothy Budd’s “An Introduction to Object Oriented Programming” (current edition), we were presented with four blocks that make sense, instead of eight that don’t. It was argued that an object is a 4-tuple:

  • structure – what the object looks like in memory
  • state – the values the object currently holds
  • protocol – the set of messages a given object can “understand”
  • behavior – what said object does when it gets a message from its protocol

Note the lack of classes and inheritance, which are a way of code reuse within an object oriented context. Abstraction, encapsulation and polymorphism naturally flow from these four principles. Budd’s book is pretty popular and I assume I’m not the only one that remembers his presentation on the subject (and the cute Platypus on the cover). At any event, when looking for a definition, it’s better to go to the books rather than the allegedly confused public. I mean, imagine how monads would look if we applied this approach to them (here’s Gilad Bracha on this subject).

“Then Java came. It was presented as an “easier C++”. Same syntax, similar abstractions, garbage collection… At that point Smalltalk was hardly used any more, and “OOP” basically meant Java and C++.”

One does not simply conflate C++’s version of OOP – multiple inheritance, supermarket principle, no GC – with Java’s. Java has a direct influence from SmallTalk and Objective-C, and the original staff hated C++. And played hockey with Scott McNealy. Here’s Patrick Naughton, a member of the original team that worked on Java (“Oak”, at the time):

… I thought Objective-C was the coolest thing since sliced bread, and I hated C++.
So, naturally when I stayed to start the (eventually) Java project, Obj-C
had a big influence. James Gosling, being much older than I was, he had
lots of experience with SmallTalk and Simula68, which we also borrowed
from liberally.

source

It is important to stress that the garbage collection is key in an object-oriented language, rather than a utility that makes life easier. With no garbage collector, any object creation has to be matched with precisely one object destruction (and of the same object as well). This means objects are not “first class citizens” in the language – the programmer cannot create anonymous ones. Java has to have garbage collection, because of the exact same reasons LISP has to have it when it allows programmers to create anonymous functions.

C++, on the other hand, is governed by the “supermarket principle” – the language accommodates many programming styles (including OOP, modular, procedural, and to some extent, functional. See Bjarne Stroustrup’s introduction to “The C++ Programming Language“), but you only pay for what you use. Garbage collection runs against this principle, as it has a heavy price tag.

Onward, to the second death.

“suddenly we hardly needed Object any more.”

Dude, you realize where toString(), hashcode() equals() and come from, right?

Onward – I’m skipping the “third death”, as I disagree that the grim reaper operates on a programming paradigm by adding more languages that support it.

“Lambdas are everywhere…”

A lambda is an object with a single method. Since it’s a single method, it does not need to have a name. When the need to name it rises, it is commonly called “apply”. In fact, OOP is a generalization of FP – FP only allows objects with a single method; OOP allows many methods. FP objects – “lambdas” or, more accurately, “closures” – can even have state: captured values from the internal calculations that created said closure. That state may even be mutable, e.g when it contains box values. So, yay FP, but FP and OOP are not mutually exclusive. You can do both. At the same time. In the same language. We’ll get to that.

Yet from a popular perspective, first class functions are not OO at all: they come from functional programming. Yet they managed to invade every single mainstream OOP language.

They didn’t invade. They where there at the beginning. SmallTalk had them. And again, FP was one of the two main influences on SmallTalk. Here’s Alan Kay, reflecting on his work (from ACM Queue)

We had two ideas, really. One of them we got from *Lisp*: late binding. The other one was the idea of objects.
source

By the way – this is a really good read. Long – but good.

“There is an easier way: don’t mutate state. Always construct new stuff, never throw away anything. Then let your smart pointers or your garbage collector take care of unreachable references.”

And I assume the garbage collector does everything in O(1), and was sent by to us from the heavens? More to the point – I think we can turn the hubris knob down ever so slightly, and construct the following argument from the above quote (at the risk of being accused of constructing a straw man myself):

“Application programming can be done with no mutable state. Code that mutates state is inherently low-level, and can be left to system programmers, the same way we treat assembly code today”

Now that’s a statement I see the merit of. I don’t agree, though – garbage collection has a real cost, and sometimes it does make sense to minimize it. There are programming models that accommodate mutability, while being safe and simple even in concurrent contexts. The actor model is probably the most popular, but there are others (shameless plug – my ongoing PhD thesis works with behavioral programming, developed by Harel, Marron and Weiss, which also offers that, in its very experimental way).

I agree that Entity-component-systems (ECS) is an interesting approach. Also, indeed, relational databases and OOP don’t mesh well, once OOP starts to use stateful inheritance. I guess this impedance contributes to the growing popularity of NoSQL databases (should ECS support that?).

Functional Reactive Programming is very interesting too. But do note that, at least in the web context (Elm, React) it is used to change the DOM, which is one of the poster boys of OOP (inheritance, composite design pattern, the works). This may actually be a good case for the aforementioned statement, where higher level programming is done in FP, while the underlying layer is done in OOP.

So is OOP not dead yet?

Prophecy, as the old proverb goes, was given to the fools. Well, I’ve been called a fool numerous times, and thus am happy to offer my opinion of the future of OOP: It’s not going anywhere. It will mutates (or rather, has mutated) to include FP. We already see this in Scala and Javascript – these languages model functions as objects, and take it from there. Martin Odersky calls this “postfunctional programming“. The term seems to be taking off. I think in the forthcoming years we’ll see OOP gobbling up logic programming as well. Some sort of merging between Prolog and Java/Scala. LP has been quiet for too long now.

P.S.

Oh, and regarding the game industry leaving OOP – I have no idea if the game industry is indeed leaving OOP. Some hard numbers are in order. But even if that’s true, and even if we accept that “games are simulations” – they are simulations that have to be done fast enough to be rendered, smoke, explosions, blood, gore, background music and all. In real time. And at least partially on GPUs, rather than CPUs. I’m not sure how strong a classifier the game industry is, given these traits. But hey, interesting development nonetheless (if true. Braaaaains! I mean, Nuuuuuuuumbers!).

Print a filled rectangle in Scala

@puppies , over at StackOverflow, had a question about how to print a filled rectangle in Scala. I guess s/he has an imperative background, because a) we all do, and b) s/he made an attempt to do this using loops. But in Scala, you can also do this with mapping and list concatenation.

Here’s my initial take (all code is printed on the scala REPL):


val ec="@"
val cc="X"
val cols=8
val rows=5

((ec*(cols+2)) +: Range(0,rows).map( _ => ec+cc*cols+ec) :+ (ec*(cols+2)) ).foreach( println(_) )

Which results in

@@@@@@@@@@
@XXXXXXXX@
@XXXXXXXX@
@XXXXXXXX@
@XXXXXXXX@
@XXXXXXXX@
@@@@@@@@@@

So then, Ben Reich suggested using until in stead of Range. Also, we can replace the side-effect in foreach with mkString:


((ec*(cols+2)) +: (0 until rows).map( _ => ec+cc*cols+ec) :+ (ec*(cols+2)) ).mkString("\n")

Can you print this rectangle using a shorter snippet? Post your version in the comments.

Uninheritance Using Undefined in Javascript

Javascript has a value called undefined. It’s an interesting little fella, which is the value of everything that is not defined. One common use of it is trolling your javascript console:


> defined
ReferenceError: defined is not defined
> var o = {}
undefined
> o.defined == undefined
true

Ha ha, silly javascript, not can’t even tell defined from it’s opposite. Except that it can. And it’s also very elegant.

See, unlike other dynamic languages that requires programs to test the symbol table for symbol presence (e.g. ruby’s defined?() method), javascript does not have to test the table, since every valid expression (such as a variable reference) has a value. It just may be that this is undefined.

Common inheritance models allows programmers to refine behavior (when overriding methods) or to extend them (when adding new methods). But javascript, with it’s undefined and its prototype-based inheritance, has a new type of inheritance – inheritance with method deletion.

Suppose we want to model vehicles. Vehicles can go, er, I mean go(), and they also have a number of doors. Easy enough, here’s the vehicle object, and a car and a truck.


var vehicle = Object.create({});
vehicle.go = function() { return this.name + " is going"; };
vehicle.doors = function() { return this.doorCount; };
// make a truck
var truck = Object.create( vehicle );
truck.doorCount = 2;
truck.name="Truck";
// make a car
var car = Object.create( vehicle );
car.doorCount = 5;
car.name="Car";

This works fine (all examples here were executed using Firefox Developer Edition):

> var aCar = Object.create(car);
undefined
> aCar.name="MyLittlePony";
"MyLittlePony"
> aCar.go()
"MyLittlePony is going"

Nothing new so far. But how do you go about modeling a broken car? When using languages that use class-based inheritance, such as Java, one might result to throwing an IllegalStateException, since brokenCar is a vehicle and thus must have a go() method. In javascript, however, there’s another option:


> var brokenCar = Object.create( car )
undefined
> brokenCar.go = undefined;

And now:

> brokenCar.doors()
5

But

> brokenCar.go()
TypeError: brokenCar.go is not a function

In other words, brokenCar is a car that can’t go, just like in real life, where a broken car is a car that can’t go.

Achievement “modeling bliss” unlocked.