Showing posts with label development. Show all posts
Showing posts with label development. Show all posts

Monday, January 29, 2018

ServiceWorkers coming to Safari

If ServiceWorkers are coming to Safari for macOS and iOS, it looks like progressive web applications will be pretty plausible across all major modern browsers -- both desktop and mobile. You'll still have a problem with older browsers (and thus older machines that haven't updated), but this can still get you a single codebase across desktop and mobile, which is appealing to a lot of companies. It'll be curious to see how much of an impact this has on React Native traction.

Thursday, July 14, 2016

Using Ligature Fonts in IntelliJ

IntelliJ IDEA 2016.2 was released with improved support for programming fonts with ligatures. I tried a few of them to see how I felt about them. I do some Scala in IntelliJ, so I used Scala examples to compare how I felt about things.

Hasklig
Hasklig initially felt like the right font for me. It's based on Source Code Pro, which I like, although it's never been my favourite programming font. It's very round, and a bit wider than I normally choose, but legible, and the ligatures look nice.


However, I do like the idea of having a ligature for "!=", and Hasklig limited ligature set doesn't include one for this.

Fira Code
Fira Code looks a reasonable amount like Hasklig, really. It's a little narrower, a little less round. I found it very slightly less legible at first, but it was a close second place. Notice that it does include a not-equals ligature:


Although I started with Hasklig, I have since switched to Fira. 

Monoid
Monoid is big. It's the only one that I'm showing here in 12pt instead of 13pt, and even that feels bigger than the others. It's pretty legible, but the weight feels a little too light as a result to me. Feels like coding in Helvetica Neue Ultra-Light.

Pragmata Pro
Pragmata Pro is narrow and tall. The wideness of Source Code Pro is one of the reasons I stayed away from it at first, but Pragmata feels almost cramped to me. I like the idea of firing a lot of text in, but it feels less legible as a result of its narrowness, so I'm not sold.

The fact that it costs €199 for the complete family does not endear me to it either. I understand making fonts is a lot of work, but many programmers aren't going to bother with a custom font at all, and making it that expensive pretty much rules out the odds of it being an impulse purchase. Some way of trailing the font in an IDE would be nice.

If I felt this were the right font for me, I suppose I would probably purchase it anyway, but at that price I'd want to be sold right away, and I'm not. If it were cheap, maybe I would have impulse-purchased and given it a longer trial.

Pragmata does have a lot of nice features, so if you do feel so inclined, it's still worth looking at.

My Choice
To be honest, these are all pretty decent fonts, and if you're interested in having programming ligatures, I urge you to try some of them out and see which one fits for you.

For me, I think I'm going to try Fira Code for a while. If Hasklig or Source Code Pro adds more ligatures, I might consider going back. I'll also be watching for other ligature programming fonts (Inconsolata, for instance?).

Have any suggestions I should try?


Friday, June 19, 2015

Web Assembly is Backed by the Right People

There have been a few attempts over the years to take a more revolutionary approach to pushing the web forward. Google's Dart, Microsoft's TypeScript are some examples of these. While these have been interesting to skim, I have never followed them too closely because they lacked the kind of support they would need to succeed. JavaScript alternatives can compile to JavaScript, but without being built into the browser, they were never going to replace JavaScript.

Yesterday, news of the Web Assembly initiative broke:
It's far too early to decide whether or not this will work out, there's very little detail to go on at this point. However, I was pleased to see that the group of companies putting some support behind it seems to be the right group. If Apple, Mozilla, Microsoft and Google all put their weight behind an initiative to improve the web, there's a much better chance of it succeeding than if one, or none of them does.

Now, "weight" is a subjective term, and it wouldn't be hard to imagine one or all of these companies not putting enough force behind this to make it a success. But if they really do all commit significant resources to this kind of effort, there's a real chance that this could be a moment in the history of the web that we look back on as a turning point.

It's still too early to have much of an opinion, but I'm interested to see where this goes.

Wednesday, June 11, 2014

TweetDeck XSS Vulnerability in Desktop Application

TweetDeck's recent XSS vulnerability highlights one of the downsides to using web technologies to build a desktop app.

Of course, no app is immune to vulnerabilities, and using desktop application platforms certainly doesn't prevent all vulnerabilities. But TweetDeck's vulnerability exists in part because the content it displays is delivered in the same form as its user interface.

A desktop application that failed to properly control web content that it was displaying would still expose the web container in which the content was running, but that wouldn't make it vulnerable to manipulating the application controls. A badly secured web view to display a tweet within in a native application with native controls for displaying tweets would still make it hard to, say, trigger the application to retweet the content automatically.

Friday, January 17, 2014

HTTP 2.0 should simplify Web Development

It's nice to see that HTTP 2.0 should simplify aspects of web development by making it possible for browsers to optimize on our behalf rather than forcing web developers to know and care about things like how many requests a browser can make at once, and how to make your website load faster by pushing files together.

That sort of thing should be dealt with in the plumbing between the browser and server and shouldn't have to be the domain of web developers.

Thursday, January 16, 2014

Pivotal Tracker and Parallel Releases

I've used a fair number of issue trackers, but lately I've been leaving most heavily on Pivotal Tracker. It sits in the sweet spot between simplicity and complexity for me, does the key elements well and emphasizes some things that I mostly don't need.

In particular, I feel like Pivotal does a really good job of allowing you to keep a prioritized list of features / stories, work on the most important one, know what people are working on and how it's going, manage them with iterations and velocity. It's ability to predict release schedules is also reasonably solid, as is its implementation of subtasks.

Pivotal is very definitely opinionated software. It works well if you approach software from a particular perspective, but there are lots of situations in which Pivotal's approach might either not help or actively interfere with how you might want to run your own project. That's fine, that just means that Pivotal isn't the right tell to help you in that situation.

Its emphasis on user stories means that you can only put so much detail into a story before it starts to feel unwieldy. Some trackers are a more rich environment for describing requirements in detail, but Pivotal's agile mindset doesn't encourage that, and that works fine for me.

You can't really customize the workflow or the issue fields, but the standard workflow and issue fields that Pivotal supports are roughly the ones I would want anyway.

However, a few times I've noticed an area where Pivotal's approach isn't to my liking, around managing parallel releases.

Parallel Releases
It's not uncommon when working on software to have a couple of releases running in parallel. Unless you're doing something like continuous delivery, it's likely that after a significant release, you will sometimes want to deliver bug fixes for the recent release while at the same time working on features for the next release. This is easy to do in most source control systems, and not that hard to do in most issue trackers, but in this case, Pivotal's opinionated simplicity tends to get in the way.

Some examples:

  • If the patch release boundary is already in the 'current' section of pivotal, you can't move tasks above that marker without starting them. This can make it confusing to manage tasks that you want to include in a patch release that will be done during the current iteration. You either have to mark them as started when you may not be ready to do so, or to remember that when you do start them, they need to be moved into the patch release.
  • If you accept a feature for the next significant release while the patch release is still unfinished, the accepted story moves up above all incomplete stories, making it look like it's part of the patch release, when it might not be.
There are workarounds. You might:
  • Not accept features for the next release until the patch release is finished.
  • Always mark patch release stories as started as soon as they're created if you need them to move into the 'current' section.
  • Use labels or epics judiciously to help out.

These do work, and ultimately, it's nothing I'm going to quit pivotal over, but it is an annoyance.

Other Issue Trackers
What other issue trackers might you consider?

GitHub Issues
GitHub is great, and having issues built in works reasonably well for fairly small projects. I use it happily for some open-source projects, but I'm not at all certain that I'd like it for even a relatively small team. I haven't used it much in a team setting, but I suspect I wouldn't be that pleased with its ability to keep me informed about the progress of a team and a project if I were managing scope, timelines, deadlines and priorities for a team.

Basically, what's there works fine, but it's pretty limited and in particular I think it's limitations would be strongest on the planning and prediction side which tends to be pretty important in a corporate setting.

JIRA
Jira has a ton of features, and it's very customizable. If you need a lot of features and you want to customize heavily, Jira might be the tracker for you. That said, in my experience, Jira was always a little clumsy in places, and it seems to have gotten worse in that respect rather than better. It's very easy to end up feeling like you have a lot of good information in Jira but that you can't find all of it when you want to. It's not very good at giving you an idea of how a project is going, it's easy to misconfigure Jira in a way that will end up biting you in the butt. I've seen more than a few Jira configurations that I thought were absolutely terrible.

Still, if you really feel like you need these features and these customization capabilities, I don't know what else to recommend, so it still fills a niche.

Trello
While not strictly an issue tracker, I definitely know people who've used and enjoyed Trello as an issue tracker. It's closest to a kanban setup, so if you're choosing an approach closer to lean software development or kanban, this might be more your style.

I've played with it enough to know that I'd be willing to give it a try on a project, but I'm not certain yet how I'd feel about it.

Sprintly
Sprintly looks like it's a close competitor to Pivotal, but I don't know anyone who uses it and I haven't used it myself. Looks good from the outside.

Bugzilla
Bugzilla makes even JIRA look good. I don't understand why people use it.

Trac
Redmine
Neither of these are terrible choices but neither would be in strong consideration for me.

Lots and Lots More
There are lots of others. Some of them might even be good.

Thursday, May 16, 2013

Why Did Google build Android Studio on IntelliJ IDEA?

At Google I/O 2013, Google announced the availability of Android Studio, an Android development integrated development environment (IDE) based on IntelliJ IDEA.

Thus far, the primary target of Google's IDE integration efforts have been focused on Eclipse, the predominant Java IDE. Google has Eclipse plugins for GWT and AppEngine, Android, Dart, and possibly other projects I'm forgetting. So it's a bit of a surprise to see Google focusing so much energy on an Android Studio based on IntelliJ IDEA.

Google's being circumspect at this point in terms of how they talk about Android Studio. It's an early access preview. There's no clear language on whether or not ADT is now deprecated, replaced by Android studio, although rumor has it they will support both. Even if Google publicly commits to continuing development on both Android Studio and ADT, will one of the two see the lion's share of the investment? Will one languish while the other flourishes? Only time will tell.

Android Studio is a new set of plugin APIs, a new windowing toolkit (Swing vs. SWT), a new ecosystem, a new set of related plugins to consider integration with. There would be a lot of effort in supporting a new IDE integration for IDEA, even given that JetBrains had already started the work by supporting Android development in the first place. It may confuse new Android developers who now have to choose between two IDE options without identical feature sets. It will create a whole new support channel for people with Android Studio questions. At this point, they're still recommending ADT as the mature choice, but it seems like it won't be long before the decision is less clear-cut.

For a company that's talked repeatedly about putting more wood behind fewer arrows and focusing their efforts, supporting two IDEs for mobile development seems unnecessary, excessive.

So why are they doing this? Are they just so intent on getting developers to Android that they believe they need to support two distinct Java-based IDEs? It doesn't seem likely that there are enough dyed-in-the-wool IDEA supporters who want to build Android apps, but are unwilling to do so in Eclipse to justify the move.

It seems more likely that they have decided to switch horses midstream, and are backing Android Studio over the long haul and supporting ADT for now simply because it's too early to get people to switch and it's expedient and politically sound to wait until Android Studio is overwhelmingly better.

But if that's true, what about the other Eclipse plugins that Google supports? And why switch the build system to Gradle? There are lots of questions, few answers. I am interested to see how this feels in a year or two.

Friday, February 22, 2013

Application Cache is a D*bag

A List Apart's Application Cache is a Douchebag is great. It's well-written, filled with lots of useful details, and easy to read. Of course, it's also titled in a way that some find offensive (although I do think that in North America, the word "Douchebag" is used very often and has lost much of its sting).

I've been doing some work on an offline web application with one of my clients, and this article has already saved us some time, so if you're considering going down this path, I recommend you give the article a read.

I'd also note that if you're going to do any work with Local Storage, you'll probably want to do some profiling, probably with Firebug, inside Firefox, whose local storage implementation has some rough edges -- in particular, these methods:
  • localStorage.length
  • localStorage.getKey()
Both of these methods have a tendency to slow down pretty quickly as the number of keys mount in Firefox.

Friday, September 21, 2012

Smart App Banners in iOS 6

Often, when browsing the web on my iPhone or iPad, I'll get a full-screen banner suggesting that I get the iOS application that corresponds to this website. Because these notifications are full-screen, they prevent me from reading whatever it is I'm trying to read, and tend to fall into one of three categories:

  • Help Me Install an App I Already Have: I already have the app, but for some reason I'm not using it -- possibly I've come here from a web search. The custom notification will often only send me to the app store for an app that I already have, meanwhile prevent me from accessing the content I wanted to access.
  • Help Me Install an App I Don't Want: This is often true for things like forum systems. I just want to read something someone wrote somewhere on the web, I don't want to install yet another app for your particular website -- that's why I'm using the web.
  • You Have an App? Occasionally, they're actually telling me about an app that I don't have and would actually like to have. In this scenario, I may be willing to download the app right away, or I may want to do it later. Unfortunately, even if I follow the link to download your app, I might then still want to read whatever I came here to read, and if I go back to the link that brought me to your site, I might immediately fall into the first category again, where you tell me about the app I already have instead of showing me what I actually wanted to see.

This last option is the only one where the full-screen banner is actually useful, and even then it might be something I prefer to do another time.

Fortunately, iOS 6 has a new feature, smart app banners, that are less intrusive and more useful, not to mention very easy to implement. Using these, you can redirect from the web to an application without a custom full-screen banner.

Looks great -- I hope websites start using this path instead of building their own full-screen banners. And if you're looking for someone to help you implement smart app banners, get in touch.

Sunday, August 12, 2012

Err Chatbot

Although Hubot is fun, and is already in use for gluing development chatrooms to infrastructure of all sorts at companies like GitHub, there are alternatives. I've had a couple of conversations with Guillaume BINET whose Err chatbot might be the sort of alternative you might consider.

Err (pronounced 'R2') is written in Python, is extensible through plugins which look reasonably easy to write, and has a catalog of pre-existing plugins. If you'd rather use Python than node.js to extend your chatbot, Err might be a good choice for you.

I haven't tried it yet -- there are two blocking issues for me:

  • XMPP-only: I currently use CampFire, because I like the available clients and the native support for history/searching.
  • No Web Hooks / Notifications: Err is mostly built for responding to user requests in the chatroom. I often use Hubot to respond to external services, like an SVN checkin or CI build notification. You could presumably write this into Err yourself, but it doesn't make that easy for you yet.

These may come soon so if you're interested in Err, you could star or watch the project on GitHub and keep an eye on it.

Wednesday, March 28, 2012

Web Development in Pure JSP

On a recent project, my client needed a small web application to be developed in ‘pure JSP’ for a client of theirs.[1] In essence, their only route to deploy anything in the production environment was to commit it to a subversion repository which would later get deployed on their behalf. This made anything but the simplest deployments tricky. Adding frameworks to the project or deploying precompiled code was only going to cause problems.

If you haven’t done much web development in Java, this might not sound particularly unusual. Deploying a php, rails or python project typically doesn’t require much in the way of compilation, and while framework are common to both, doing without wouldn’t be a particular stumbling block.

For a Java project, this is fairly unusual – a classic Java web project uses the MVC pattern and establishes a fairly strict separation between the model, view and controller where the model is plain Java, the controller is a Java servlet, and the view is JSP:


There are lots of alternatives[2] depending on your preferences and technology choices, but I haven’t seen many Java projects implemented using only JSP.

Writing a Pure JSP project would rule out using Java classes[3] for the model and controller, and limit you to whatever you can accomplish in a JSP. Having said that, I couldn’t see any fundamental obstacles to building a project in pure JSP, I just hadn’t done it or seen it done. I did few quick google searches and didn’t see many people suggesting this approach, so I decided to conduct a quick exploratory spike.
After a little testing, I quickly found that there were at least two choices that would work, which I’ll call “JSP Controller” and “Embedded Controller”.

JSP Controller

In this style, you simply replace the controller servlet with a JSP page that acts like a controller servlet. JSP pages are essentially Java servlets in a different form, and if you write a JSP page that contains no HTML or CSS, but instead parses the request from the browser, does any necessary processing and then renders the response using another JSP page, then you have what amounts to a controller written in JSP:


Of course, if you’re avoiding precompiled Java classes, you still can’t use an external Java-based model, but you can use the standard Java class library, as well as inner classes. This isn’t the cleanest way to model your domain, but it’s enough to get by.

Embedded Controller

If your control logic is pretty simple, you might simply embed the control logic in the view up-front. This mixes the view and controller in a way that some might find unpalatable, and a little retro[4], but it does simplify things a little and makes it a little easier to share model code with inner classes. This is the simplest approach, but also the one most likely to make an unmaintainable mess if your project will be growing:


This client project was a very tightly-scoped piece of functionality, so I used Embedded Controller and was reasonably happy with the end result, all things considered.

When to use Pure JSP

I’m not advocating for Pure JSP projects as a generalized solution to web development in Java. It adds a lot of constraints to your development style for benefits that are of limited value in most projects.

But if you need to build a small project that will run in a Java-based environment and you don’t have a lot of access to the production server or detailed knowledge about how it is configured, these approaches do simplify things.

By writing this up, I hope to save some of you a similar exploration; if you’re in this position, you’ll know this is a path that others have taken and that it all worked out in the end.



  1. The project was developed under a non-disclosure agreement (NDA), so I’m going err on the side of non-disclosure here and keep the details vague.  ↩
  2. The model could be an enterprise Javabean; the controller might be plain/annotated Java front-ended by a “front controller” servlet provided by your framework; the view could be Thyme. All three might be replaced by a somewhat different model under JSF or Tapestry.  ↩
  3. Incidentally, JSP pages typically end up as compiled Java classes, but that happens under the cover without your involvement, so it’s a little more suited to an environment over which you have limited control.  ↩
  4. When the web was born, this kind of mixed presentation-and-logic approach was the simplest, and thus, most common approach to adding very simple functionality to websites. In the early days of Java, this was the "Model 1" approach as compared to the "Model 2" MVC separation that came to dominate as a development style.  ↩

Tuesday, November 29, 2011

What Ails Java

Listening to Hypercritical #44: A Little Bit More Sad, about what ails Microsoft, it's hard not to draw parallels to what ails Java.

In particular, John Siracusa suggests that Microsoft:

  • Catered to the enterprise even when that damaged the health of their platform.
  • Failed to capitalize on the strength of their hand by moving the platform forward when their customers had nowhere else to go.
  • Has tended to react to moves made by others rather than being first-mover.
These are tightly coupled with one another, there's a surprising amount of overlap between them, but they each describe some nuance that the other does not.

Each of these has a strong parallel in the history of the Java platform.

Because the control structure of Java is distributed, with Sun, IBM, Apache, open-source contributors, the JCP and so forth, I'm mostly going to talk about Java personified, as if Java itself could have made decisions. That's clearly not true, and it shapes some of that which follows, so I'll talk about that as well.

Catered to the Enterprise
Java developers, as a group, are mostly people who build server-side database-backed web applications for medium-to-large corporations for internal and public use. There are lots of exceptions to the rule in terms of desktop software, non-web-based or non-database-backed server-side code, gaming servers and so forth, but these are a small subset of the overall Java marketplace.

Those guiding the Java platform have set their sights on various markets, from client and desktop software (AWT, Swing, Applets, Java Web Start, JavaFX) to the Web (Servlets, JSP, JSF), media, gaming and the enterprise (Java EE, Enterprise  Javabeans, CORBA), but it's clear that the Enterprise/Web market has always been the stronghold for Java.

Although Java would make attempts at these other markets, they were usually half-hearted and quickly abandoned. It was too easy to continue to emphasize the technologies that mattered to the enterprise and too hard to push into other markets. This also meant that any new announcement about media, gaming, or a client technology would generally be greeted by skepticism by analysts, development companies and individual developers -- each expected that these technologies, interesting though they might be, were probably going to die on the vine out of sheer neglect.

Failed to Capitalize on a Position of Strength
Java started with a number of innovations -- it really popularized namespaces with packages, garbage collection, thorough object-orientation, a virtual-machine-based platform. All of those things existed before Java, but Java really brought those to the masses, made them popular.

However, as Java became more popular, it became far more cautious about innovation, choosing to favor backwards compatibility over significant change. This caused the language to settle down, to stagnate or mature, depending on how you feel about the results. It became a language in which you could get things done, but a language about which one might cease to be excited about.

The runtime started to take on bloat as things would be added (JavaDB, CORBA), but never removed, no matter how little they were used. There has been some talk about modularizing the JVM, but it's only talk, and too little, too late at that.

In order to ensure that conservative development organizations could upgrade without having to think about it, classes and methods would be marked as deprecated, but never pruned.  As a result, you could start to tell when an API was created by the age of its dependencies. For instance, HttpServlet in Java Enterprise Edition 6, delivered in 2009, still uses Enumeration despite the fact that it has been essentially replaced by Iterator in Java Standard Edition 1.2, delivered in 1998, eleven years earlier.

It didn't need to be this way. Throughout much of its history, Java was in a position of strength with its primary customer-base, the enterprise. If the guiding forces behind Java had said, "Ok, this has been deprecated for two major versions, let's get rid of it now" I'm entirely sure that their most cautious enterprise customers (e.g. major banks) would have grumbled and complained, but gone on to modify their code to remove Enumeration, Vector, Date.va getYear() and other similar pieces of outdated Java code.

Sure, it's a pain to update your code on a mature program to reflect changes in the platform, but think how much more of a pain it would be to port that mature program to .NET, let alone Ruby or Python. Where did Sun and Java think these enterprises were going to go if they pushed back a little?

Java could have capitalized on this strength and taken the opportunity to move the platform forward even when that meant some grumbling from the enterprise customer base, because the cost of switching was too high. This has to be done carefully -- you can only push so hard without alienating your customers, but Java didn't push at all.

Reactionary
Because Java has catered to its enterprise customers and failed to capitalize on a position of strength, the rate of innovation dropped off precipitously. This put Java into a reactionary mode where changes were only made as perceived threats grew stronger and reacting to those threats became vital.

This means that for years, Java hasn't been the innovator, but simply introduced changes to stem the bleeding caused by other languages and platforms innovating around it. Look at the rate of change to the C# language in the same timeframe that it's overlapped with Java. Look at Java continue to struggle with generics and closures, let alone platform modularity and aging libraries.

People don't look to Java to innovate anymore, and that means they're not excited by Java, and as they get excited by other languages and platforms, their attention wanders. Java has been ripe for disruption for years, and sooner or later another platform or language is going to make that happen.

Java's Control Structure
Java's distributed control structure and odd profit models have encouraged much of the above. Sun, Oracle and IBM, key figures in steering the Java platform, are all large businesses targeting enterprise software development. They all make most of their Java-related money from consulting rather than selling tooling, or direct sales to end-users.  So it's no real surprise that these organizations would choose to cater to the enterprise. 

The control structure is also very distributed, with a committee based on these organizations and individual expert contributors. This kind of control structure is good for getting consensus, but is often cautious and rarely innovates. That tends to result in making cautious moves, rather than bold ones that might capitalize on a position of strength, and this tends to lead to a reactionary approach.

Ultimately, you could probably argue successfully that much of what ails Java are a direct result of its control structure and participants. This structure is very different than Microsoft's, although you could probably also argue that their problems are structural.

In Summary
Java, like Microsoft, has not aged gracefully. As each got popular, it also got more cautious and settled into some long-term patterns that guaranteed that it would please its primary customer-base, the enterprise, at the cost of long-term health. Both are in decline and ripe for further disruption.

Neither is likely to go away any time soon -- they both have their hooks in deeply with the enterprise, which will hang on to avoid the cost of change, but both have their best days in the rear view mirror and can only hope to age gracefully, rather than find new life.

In Java's case, there's some possibility that another language will find strength while building on top of the rest of the Java platform, in particular the virtual machine. I suspect that even these are simply stop-gap measures while the libraries attached to the JVM continue to decay, but that's the subject of another post.

Ultimately, Java is still a perfectly solid environment on which to build enterprise software, but it's now the safe choice, not the interesting one. That's been true for years, and it's only a question of time before some other language and/or platform finds dominance over Java and increases the rate of decline.

Tuesday, March 1, 2011

View-Presenter Interaction Patterns in Google Web Toolkit (GWT)

In Building Testable Applications in Google Web Toolkit (GWT), we talked about using the Model-View-Presenter (MVP) pattern. I also noted that there are different patterns, or styles of describing the interaction between the view and the presenter.

Let’s start with the example I’ve already used, a login form like this:



Your view has two text fields (username, password) and a button (login), as well as a few labels, possibly a title and some explanatory text. We’ll assume that the presenter needs to interact with the text fields and buttons, but that the labels, title and any explanatory text can be encapsulated into the view.

When you build your presenter, you’ll need to decide how the view and the presenter will interact, and there are a few approaches you can take.

Abstracted Control View

Ray Ryan’s Best Practices for Architecting your GWT App uses views that act as containers for controls. Rather than returning the widgets themselves (e.g. Anchor, Button, TextField), the views return interfaces that abstract the specifics of the control from the presenter. This allows the presenter to be completely decoupled from GWT widgets classes, as well as increasing your ability to substitute one control for another.

So, for our example login view, we’ll need to expose the username, password and login button, and we can do so through interfaces already supported by these widgets. For instance, the TextBox and PasswordTextBox widgets used for the username and password respectively implement the HasText interface, which would allow you to retrieve the text that has been entered, and the login button supports HasClickHandlers, which would allow you to add a ClickHandler event-handling class to the login button.

For our simple case, an abstracted control view would look like this:



This works well for simple cases, but quickly gets complicated. For instance, what if you want to expose an aspect of a control that doesn’t have a convenient interface, like setVisible(), which most GWT widgets inherit from UIObject, but which isn’t part of an interface.

One alternative would have you create the interfaces that you need, extend GWT widgets and implement these interfaces. For instance, you could create HasVisibility, then create a new class, VisibleAnchor which extends Anchor and implements HasVisibility:



Since setVisible() comes from UIObject, each class that inherits from UIObject has the same consistent method signature, so as long as you’re willing to apply this subclassing approach pervasively, you can create the necessary interfaces.

This also gets complicated when you need to expose two or more aspects of one widget. For instance, if your login view chose to change the text on the login button to “logging in …” and disable it while the login process was underway, this requires you to expose three aspects of the login button — enable/disable, setting the text, and adding a click handler.

You can do this by grouping the interfaces you need to expose into interfaces that expose the exact right combination for a given view. You could build interfaces like like EnableableClickableText:



While this gives you lots of control over the level of abstraction, and gives you a lot of substitutability (StyledText could be implemented by TextBox and Label while VisibleClickable could be implemented by Button and Anchor), this approach can quickly get out of control. On a project of any size, there are likely to be more combinations here than you care to count let alone implement.

Ultimately, if you end up exposing multiple aspects regularly, you’re probably better off accepting that it’s too awkward to maintain every combination of exposed aspects as a separate interface, and simply create an interface that combines all of the aspects you want to expose, either for each class, or for a cluster of related clsses. For instance, you might create a ‘TextInput’ interface that combines all the interfaces that you wish to expose on a TextField, and then create a TextInputBox class that extends TextInput and TextBox:



As an alternative, you could expose each aspect of a control through an independent accessor. Using the previous example, you could expose the login button control through independent methods that expose the enable/disable, text setting and click handling:



This style is fairly similar to the Interaction View style which follows; most people will find the Interaction View style more appealing.

Interaction View

Where the Abstracted Control View exposes abstractions of controls, the Interaction View exposes the interactions themselves.

For instance, although our login view has three controls, it has six known interactions:


  • get the username text

  • get the password text

  • add a click handler for the login button

  • set the login button text

  • disable the login button

  • enable the login button



Each of these can be exposed through a single method:



Alternately, you might choose to group the interactions if they’re likely to be invoked together:



This is closer to the approach used by Daniel Danilatos in GWT Testing Best Practices. If most of your controls expose a large number of unique aspects, this can get tedious — where an abstracted control view might need a single method per control, the interaction view might require several times that. Imagine a data-entry screen with twenty controls and complex behavior to show/hide fields, change styles, display field-level validation, and you'll start to see that this could get pretty messy. In practice, I find that relatively rare, but your mileage may vary depending on your project.

In addition, Interaction View tends to mesh well with mock testing, which is sometimes called Interaction-based testing, in that it allows the test to more clearly expect the intent, rather than needing to mock controls and expect certain messages to be passed to the controls.

View Delegate

Finally, there’s the view delegate style, where the view handles the events, but delegates them to the presenter. This is of particular merit if you’re using GWT UiBinder and its support for @UiHandler to reduce boilerplate code, and can be seen in Large-Scale Application Development and MVP. In this model, the view will respond to the events of its controls, but delegate the processing of that event to the Presenter.

In the case of our LoginView, this is something you’d use for the login button click event:



This event delegate style fits most naturally as an extension of the Interaction View.

In Summary

If you’re writing a Google Web Toolkit (GWT) application and you’re using the model-view-presenter (MVP) pattern, you have some choices in terms of how you want your view and your presenter to interact. You can expose the controls through an abstraction layer, you can expose the interactions and you can optionally use a delegate approach, particularly if you’re using UiBinder with GWT 2.x.

Monday, January 17, 2011

Building Testable Applications with Google Web Toolkit

If you’re interested in developing web applications with Google Web Toolkit (GWT), and you’re used to writing applications with pervasive automated testing, you’re going to find that it isn’t always easy to build a testable application in GWT.

These are some of the challenges to automated testing in GWT.

JSNI


GWT allows you to develop software in Java, but runs in a browser in Javascript. Most of the code that you write will be compiled from Java into Javascript, but parts of GWT itself and potentially some pieces of your code will simply be replaced by a Javascript equivalent, called using JSNI (JavaScript Native Interface). These pieces of code may rely on the capabilities of Javacript or the document-object model exposed by the browser.

For instance, if you were to attempt to match a regular expression against a String using Java, your Java code will use the Java implementation of regular expressions, but the final Javascript version will use Javascript’s regular expression capabilities. This can lead to subtle differences between behaviour the code that you tested and the final code that you’ll deploy, and even to behaviour from one browser to another.

Similarly, most of the GWT widgets are, at their core, tightly coupled to browser objects and events. As a result, they are not perfectly emulated in Java, and almost every GWT widget is built so that it cannot be easily constructed in Java — it will realize it’s not being run in Web Mode and throw an exception immediately. This makes it very difficult to use a simple JUnit test on widgets or on code that interacts directly with widgets.

GWT Compilation is Slow


Parts of the GWT development cycle aren’t terribly fast, particularly compilation. GWT is doing all sorts of great optimizations during compilation, but those optimizations come at a cost to development speed. That means that if you need to compile your application and launch it in order to test it, you might find that the test cycles are taking too long.

Even with those challenges in mind, you have options.

GWTTestCase


GWT explicitly supports automated testing through a test harness can you can use to load a unit of code within the GWT environment: GWTTestCase. This allows you to test your code thoroughly in an environment that is very similar to the one in which your code will be running ‘in production’, one which supports constructing and using GWT widgets directly.

That sounds like a pretty good setup, until you spend some time with it and discover that it’s very slow, a typical problem with integration testing. Due to the non-trivial nature of compiling your Java to Javascript and starting up the full testing environment, hosted browser and all, each test method might take twenty or more seconds. If you have 500 of these tests (which really isn’t that much for a test codebase), you could be talking about a test suite that takes over an hour and a half to complete.

GWTTestCase has a lot in common with integration testing; it’s slow because of the infrastructure required to do it, but the tests have the capability of being fairly thorough and cross-cutting if you’d like them to be. If you do want to do integration testing of your codebase, it may be the best option, since other integration testing tools are not always well-suited to AJAX-heavy applications.

GWTMockUtilities


As a result of the challenges posed by GWTTestCase, many people try and reduce their exposure to GWTTestCase by using it sparingly or not at all. GWTMockUtilities is intended to make it much easier to perform mock tests of classes that interact with GWT widgets. It does a few different things, the most important of which is to allow calls to GWT.create to go through without throwing an exception.

This allows you to write unit tests of code that interacts with GWT widgets in Java that run much more quickly than tests written using GWTTestCase. However, in order to allow you to mock all the widgets within a GWT view, you’ll need to write your user interface in a way that separates the widgets from the logic sufficiently that you can mock out all of the widgets being used. Isolating one piece of code from another is a very common problem in building testable code. This kind of test isolation can be encouraged using dependency injection, with or without a framework like Google GIN, and with patterns like the Model-View-Presenter pattern.

Model-View-Presenter


In Ray Ryan’s Best Practices for Architecting your GWT App at Google I/O 2009, he suggests reducing the view to something so simple that it doesn’t need to be tested. The display logic and code to connect your model to the controls can then be tested using JUnit rather than something like GWTTestCase, and those tests can be fast. He calls this Model-View-Presenter in reference to Martin Fowler’s article on the subject.

Martin Fowler has since sub-divided his MVP pattern into two possible implementation styles: Supervising Controller and Passive View. Supervising Controller puts all the event-processing logic and anything complex in the presenter, but allows the View to still perform simple data model bindings. Passive View takes on even those responsibilities, leaving the view to exist primarily as a composite set of user interface widgets. The Passive View style seems more in keeping with the approach Ray Ryan describes in his talk, although if you chose not to test data bindings, then Supervising Controller might be another approach worth considering.

By way of example, let’s imagine a simple login form that looks like this:



This might be represented by a view class like this:



And the presenter would listen for the click event of the button, then get the text from the username and password controls, attempt a login, and then update the view on the basis of the results of the login attempt:



Exposing Widgets through Interfaces


While the Model-View-Presenter pattern can help you make better use of GWTMockUtilities, it’s also true that once you’ve established a clean separation of the view from the presenter, you can often skip GWTMockUtilities altogether by exposing interfaces that represent your widgets from within the view. Mocking interfaces is often a preferred approach, and this is the approach that Ray Ryan demonstrates in his presentation.

Instead of having your presenter access a Button from the view, it could access a control that implements HasClickHandlers. TextBox controls could be replaced with the HasText interface:



In addition to allowing you to avoid the additional complexity of GWTMockUtilities, this also reduces the coupling between view and presenter, allowing you to, for instance, replace a Button with an Image or an Anchor as long as it implements the same interface that you’re exposing.

Although GWT has a number of interfaces that you can expose, you’ll find there will be methods that you wish to expose that are not covered by an interface. For instance, if you need to change the styles associated with a widget, you’ll find that addStyleName and removeStyleName are not covered by a GWT interface. If you wish to follow this approach, you’ll find you need to introduce new interfaces to GWT, as follows:



You’ll also find that although granular interfaces communicate your intent most clearly and increase your ability to substitute implementations, they break down as your interaction between view and presenter increases. If you want to get/set the text of a control as well as adjust the styles, you either need to expose both HasText and your new HasStyle interface, or you need to combine them into a common HasTextAndStyle interface. You may quickly find that the number of combinations you need grows nearly without bounds, and that you’re better off introducing an interface for each widget that exposes all of the methods that you’re likely to invoke on that widget. You can do this with your own set of packages or with a nomenclature like IButton for the Button interface.

If you find yourself wanting to substitute one widget for another (see Liskov’s Substitution Principle), you may need a hierarchy of interfaces, possibly mirroring the hierarchy that GWT provides (UIObject, Widget, FocusWidget, etc.). The tradeoff between granular interfaces at the one end of the spectrum and monolithic ones at the other is awkward, and different teams are likely to take different positions on this point.

It’s worth noting that GWT Testing Best Practices at Google I/O encourages a slightly different style of integrating presenter event handlers with view widgets. Where Ray Ryan suggests:
getLogin().addClickHandler( loginHandler );

Daniel Danilatos suggests:
setLoginHandler( loginHandler );

I’ve used the former style in the above examples, but either approach is viable.

Passive View


Passive View makes it possible to assemble complicated GWT user-interfaces and yet still test the bulk of the logic within the user interface. By turning the view into a simpler container for UI widgets, you create a very simple object which is hard to test, but for which automated testing would be of limited value.

The presenter takes on the responsibilities of moving data in and out of those widgets and reacting to events from the user or other parts of the application, and the presenter can be tested using standard Java testing frameworks which run quite quickly. At that point, the choice of testing framework and extensions (JUnit, TestNG, JMock, EasyMock, Mockito) is mostly a matter of taste.

Unfortunately, this kind of separation of the user interface widgets from all the logic that interacts with it has some costs. The view and the presenter are very tightly coupled and have lots of individual interactions. While the sequence diagram for the login view probably seemed reasonable, a complicated view might need to expose tens of widgets, or possibly a dynamic collection of widgets depending on how much information has been displayed on the screen. Each of those widgets may also have a relatively high number of interactions — setting and getting text values, adding and removing styles, showing and hiding the widget, adding click handlers, and so forth.

In an object-oriented application, you typically use encapsulation to contain complexity and reduce the number of external interactions by combining portions of the view into components with their own presentation logic. The Passive View approach can make encapsulation difficult and increase the number of external interactions. This is not simply a matter of design aesthetics — it also means that presenter tests can themselves be quite complicated and require quite a bit of painstaking mocking and stubbing. This may still be preferable to a glacial test suite, but it’s time-consuming and brittle.

If you’ve used other object-oriented user interface frameworks in Java, such as Tapestry or Wicket, you’ll find yourself wanting to encapsulate elements within your pages as components that bundle user interface widgets with logic. It’s certainly possible to do so, but well-encapsulated component that contains both logic and GWT widgets is no longer amenable to simple JUnit testing and you’ll have fall back to the GWTTestCase approach. Achieving encapsulation often requires a parallel hierarchy of views and presenters at each level. Orchestrating and wiring these all can be challenging, but it’s still usually better than the alternatives.

Decomposition for Testable Views


If you find that you need a complicated view, you might find some scenarios where a portion of the view can be isolated from GWT widgets and remain testable. GWT Testing Best Practices uses a good example where a view implements paging using a high-level view and two lower-level elements, one of which uses widgets and the other is a simple POJO storage model. The high-level view and POJO detail view remain testable, while the widget-detail view, which deals directly with GWT widgets, cannot easily be tested using a simple JUnit test. This sort of decomposition is only likely to work with larger, more-complex views, but it’s something to keep in mind.

Combining MVP and GWTTestCase


There are times where you can develop a sort of hybrid model that allows you to encapsulate elements of the presenter logic into smaller classes which are themselves like miniature presenters but for a component rather than a view, which offer some of the benefits of both encapsulated code and testability, but it’s difficult to develop an approach that you can apply consistently in this vein.

Finally, you can mix these two strategies together, making a conscious decision about when you’d like to build encapsulated components that require slower testing approaches and when you’d like to achieve fast, testable presenter code that reduces your ability to encapsulate and makes for complicated test harnesses. For instance, you could test widget code, particularly custom widgets, using GWTTestCase but use Passive Views and test your presenters using JUnit and Mockito or JMock.

In Summary


There’s no silver bullet to writing testable applications in Google Web Toolkit. There are several common approaches, each with their own set of tradeoffs, and it’s likely that anyone wishing to build test-driven applications with GWT is going to have their own set of complaints, but forearmed with the knowledge of these approaches, you can reduce the pain that you experience while developing a well-tested GWT application.