On the “advances” in web development since 1995

The first “web application” I worked on was written in a late version of WebObjects, version 4.5. An HTTP request was handled by an “adaptor” layer that chose a controller based on the parameters of the request, you could call this routing if you like. The controller accesses the data model, any relevant application logic, and binds the results to the user interface. That user interface could be an HTML and JavaScript document for presentation in a browser, or it could be a structured document destined for consumption by a remote computer program. The structured document format would probably have looked something like this:

{
  "first_name": "Graham";
  "last_name": "Lee";
}

The data can be bound on properties in objects called “components” that represent different elements in an HTML document, like images, anchors, paragraphs and so on.

Different frameworks for interfacing with various data storage technologies, such as relational databases, were available.

And basically nothing – apart from the cost – has changed since then. A MEAN application works in the same way, but with the “advance” that it makes it easier to support single-page applications so you can send a few megabytes of transpiled bundle over an unreliable mobile data network to run on a slow, battery-operated smartphone processor instead of in the server. And the data storage interfaces have been expanded to include things that don’t work as well as the relational databases. Other “advances” include a complicated collection of transpilers and packagers that mean every project has its own value of “JavaScript”.

It’s not like anything has particularly got much easier, either. For example, a particular issue I’ve had to deal with in a React application – binding a presentation component to properties of an element in a collection – is exactly as difficult now as it was when WebObjects introduced WORepetition in 1995. Before we get to the point where it becomes easier, we’ll give up on React, and Node, and move on to whatever comes after. Then give up on that.

In software engineering, if something isn’t broke, fix it ’til it is.

Updating my ObjC web app on git push

I look at SignUp.woa running on my Ubuntu server, and it looks like this.

Sign up for the APPropriate Behaviour print edition!

That title text doesn’t quite look right.

$ open -a TextWrangler Main.wo/Main.html
$ make
$ make check
$ git add -A
$ git commit -m "Use new main page heading proposed by marketing"
$ git push server master

I refresh my browser.

APPropriate Behaviour print edition: sign up here!

The gsw-hooks README explains how this works. My thanks to Dan North for guiding me around a problem I had between my keyboard and my chair.

AJAX via jQuery in an Objective-C WebObjects app

As with using jQuery for DHTML, this was surprisingly easy. To make it simple to follow along I’ve published the source code to SignUp, a sample app.

SignUp’s default page is comprised of two WebObjects components: Main is the top-level page (including the jQuery script) and SignUpForm implements the form. As described in the previous post on this topic, the form’s email field is only enabled and populated if you tick the ‘contact me’ button.

ScreenShot of SignUp.gswa's main page

We can submit the form via an AJAX request, rather than by making the browser do a full request-response cycle. To do this, install a handler on the form’s submit event that does an AJAX post of the form then cancels the default behaviour.

   var signUpForm = $("#signUpForm");
    signUpForm.submit(function() {
        $.post(signUpForm.prop("action"), signUpForm.serialize(), function(data) {
            $("#formwrapper").html(data);
        });
        return false;
    });

As I’ve said before, I’m a jQuery newbie, there might be an easier way to do the above but this is definitely easy enough. One thing to notice is that the form’s own action is used as the POST URL, meaning that the WebObjects code is still responsible for expressing the control flow through the app.

The handler’s completion function replaces the form’s content with the data it receives from the POST action. That’s going to be another component, specified in the action handler:

- (GSWComponent *)registerInterestAction
{
  GSWRequest *request = [self request];
  [SignUpForm processSignUp: request];
  return [self pageWithName: @"Thanks"];
}

The request object provides access to the form values which are used in the app to populate an Add Person command, which is handled by adding the user’s details to the database. Finally the action handler loads a component called Thanks and returns that, which will replace the form in the web page.

Capture of SignUp.gswa after filling in the form

One thing to notice is that the server side is stateless; unlike many WebObjects apps that use a WOSession subclass (and have fugly URLs incorporating the session ID, if badly configured) everything is done via Direct Actions in this app, there’s no server-side state, and no session should get created. This conveniently avoids a big lock in the WebObjects framework, where the WOApplication instance has to synchronise access to the session table.

A stateless server satisfies one of the REST constraints; obviously we’re also using code-on-demand via JavaScript and have a client–server, layered system. Resources can be cacheable by setting the appropriate HTTP headers, not shown here but certainly doable. The only constraint not satisfied is the uniform interface and even that is partially present as WebObjects is by its very nature a HATEOAS system. Indeed this application arranged to observe HATEOAS by allowing the form object to express its own action URI, rather than “knowing” the form destination in the client code. The only part that’s missing is a resource identification and manipulation interface: instead of POSTing a form as done here a client would PUT a new person.

At the old/new interface: jQuery in WebObjects

It turns out to be really easy to incorporate jQuery into an Objective-C WebObjects app (targeting GNUstep Web). In fact, it doesn’t really touch the Objective-C source at all. I defined a WOJavascript object that loads jQuery itself from the application’s web server resources folder, so it can be reused across multiple components:

jquery_script:WOJavaScript {scriptFile="jquery-2.0.2.js"}

Then in the components where it’s used, any field that needs uniquely identifying should have a CSS identifier, which can be bound via WebObjects’s id binding. In this example, a text field for entering an email address in a form will only be enabled if the user has checked a “please contact me” checkbox.

email_field:WOTextField {value=email; id="emailField"}
contact_boolean:WOCheckBox {checked=shouldContact; id="shouldContact"}

The script itself can reside in the component’s HTML template, or in a WOJavascript that looks in the app’s resources folder or returns javascript that’s been prepared by the Objective-C code.

    <script>
function toggleEmail() {
    var emailField = $("#emailField");
    var isChecked = $("#shouldContact").prop("checked");
    emailField.prop("disabled", !isChecked);
    if (!isChecked) {
        emailField.val("");
    }
}
$(document).ready(function() {
    toggleEmail();
    $("#shouldContact").click(toggleEmail);
});
    </script>

I’m a complete newbie at jQuery, but even so that was easier than expected. I suppose the lesson to learn is that old technology isn’t necessarily incapable technology. People like replacing their web backend frameworks every year or so; whether there’s a reason (beyond caprice) warrants investigation.

Short Objective-C on the server update

It’s been over a year since I looked at GNUstepWeb as a server platform for Objective-C development. I’ve recently had time to dig in a bit more, send the project some patches, and get the platform to a state on the Mac where I can start developing apps. That took a while, in my defence I was writing a book that I wanted to get out while it was sitting on my mind.

My next step (pardon the pun) is to set up a deployment platform on Some UNIX™, and set up post-update deployment of the apps: I already created pre-commit and post-commit hooks for development. It seems that a lot of people come through this blog looking for ObjC server info, I thought it was about time for an update :-).

Server-side Objective-C

Recently, Kevin Lawler posted an “Informal Technical Note” saying that Apple could clean up on licence sales if only they’d support web backend development. There are only two problems with this argument: it’s flawed, and the precondition probably won’t be met. I’m sure there is an opportunity for server-side programming with Objective-C, but it won’t be met by Apple.

The argument is flawed

The idea is that the community is within a gnat’s crotchet of using ObjC on the web, if only ObjC were slightly better. This represents an opportunity for Apple:

  1. Licensing fees
  2. Sales of Macs for development
  3. Increase share of Objective-C at the expense of Java
  4. Get more devs capable with Objective-C, which is necessary for OSX & iOS development
  5. Developer good will
  6. Steer development on the web

Every one of these "opportunities" seems either inconsequential or unrealistic. Since the dot-com crash, much web server development has been done on free platforms with free tools: LAMP, Java/Scala/Clojure + Tomcat + Spring + Hibernate + Eclipse, Ruby on Rails, Node.js, you name it. The software’s free, you pay for the hardware (directly or otherwise) and the developers. The opportunities for selling licences are few and far between—there are people who will pay good money for good developer tools that save them a good amount of time, but most developers are not those people. The money is made in support and in consultancy. This is why Oracle still exists, and Sun doesn’t.

Of course, Apple already knows this, having turned the $n*10^4-per-license NeXT developer tools into a set of free developer tools.

Speaking of sales, the argument about selling Macs to developers is one that made sense in 2000. When Apple still needed to convince the computer-buying public that the new NeXT-based platform had a future, then selling to technologists and early adopters was definitely a thing. You could make a flaccid but plausible argument that Java and TextMate 1 provided an important boost to the platform. You can’t argue that the same’s true today. Developers already have Macs. Apple is defending their position from what has so far been lacklustre competition; there’s no need for them to chase every sale to picky developers any more.

I’ll sum up the remaining points as not being real opportunities for Apple, and move on. For Objective-C to win, Java does not have to lose (and for that matter, for Apple to win, Objective-C does not have to win; they’ve already moved away from Apple BASIC, Microsoft BASIC, Pascal and C-with-Carbon). Having ObjC backend developers won’t improve the iOS ecosystem any more than Windows 8 has benefitted from all the VB and C# developers in the world. “Developer good will” is a euphemism for “pandering to fickle bloggers”, and I’ve already argued that Apple no longer needs to do that. And Apple already has a strong position in directing the web, due to controlling the majority of clients. Who cares whether they get their HTML from ObjC or COBOL?

It probably won’t happen

Even if Craig Federighi saw that list and did decide Apple’s software division needed a slice of the server pie, it would mean reversing Apple’s 15-year slow exit of the server and services market.

Apple already stopped making servers last year due to a lack of demand. Because OS X is only licensed to run on Apple-badged hardware, even when virtualised, this means there’s no datacenter-friendly way you can run OS X. The Mac Mini server is a brute-force solution: rather than redundant PSUs, you have redundant servers. Rather than lights-out management, you hope some of the redundant servers stay up. Rather than fibre channel-attached storage, you have, well, nothing. And so on.

OS X Server has been steadily declining in both features and quality. The App Store reviews largely coincide with my experience—you can’t even rely on an upgrade from a supported configuration of 10.N, N^≤7 to 10.8 to leave your server working properly any more.

Apple have a server product that (barely) lets a group of people in the same building share wikis and calendars. They separately have WebObjects: a web application platform that they haven’t updated in four years and no longer provide support for. One of their biggest internal server deployments is based on WebObjects (with, apparently, an Oracle stack): almost all of their others aren’t. iCloud is run on external services. They internally use J2EE and Spring MVC.

So Apple have phased out their server hardware and software, and the products they do have do not appear to be well-supported. This is consistent with Tim Cook’s repeated statement of “laser focus” on their consumer products; not so much with the idea that Apple is about to ride the Objective-C unicorn into web server town.

But that doesn’t mean it won’t happen

If there is a growth of server-side Objective-C programming, it’s likely to come from people working without, around or even despite Apple. The options as they currently exist:

  • Objective-Cloud is, putting it crudely, Cocoa as a Service. It’s a good solution as it caters to the “I’m an iOS app maker who just needs to do a little server work” market; in the same way that Azure is a good (first-party) platform for Microsoft developers.
  • GNUstepWeb is based on a platform that’s even older than Apple’s WebObjects. My own attempts to use it for web application development have hit a couple of walls: the GNUstep community has not shown interest in accepting my patches; the frameworks need a lot of love to do modern things like AJAX, REST or security; and even with the help of someone at Heroku I couldn’t get Vulcan to build the framework.
  • Using any Objective-C environment such as GNUstep or the Cocotron, you could build something new or even old-school CGI binaries.
  • If it were me, I’d fork GNUstep and GSW. I’d choose one deployment platform, one web server, and one database, and I’d support the hell out of that platform only. I’d sell that as a hosted platform with the usual tiered support. The applications needed to do the sales, CRM and so on? Written on that platform. As features are needed, they get added; and the support apps are suitable for turning into the tutorials and sample code that help to reduce the support effort.

    Of course, that’s just me.

On community

This is a post that had been boiling for a while; I talked a little about the topic when I was in Appsterdam earlier this year, and had a few more thoughts which were completely supplanted and rearranged by watching iOSDevUK. I threw away my earlier draft; you’re about to read something different. Where you see “we”, “us” or “our community” you should probably take it to mean Cocoa programmers, though read on to find out why “us” doesn’t always make sense.

Acknowledgements

So many people have contributed to this, by saying things that I agree with, by saying things that I disagree with, by organising conferences, or in other ways. I’ve tried to cite where appropriate but I’ve probably missed someone somewhere. Sorry :-(.

Introduction

This article is more the presentation of a problem and some thoughts about it than an attempt to argue in favour of a particular solution. I’ll investigate what it means to be in “the Cocoa programming community”, beginning with whether or not Apple is in a community of its own devising. I’ll ask whether there’s room for more collaboration in the community, and whether the community of Cocoa programmers encompasses all Cocoa programmers. Finally, I’ll notice that these are questions as yet unanswered, and explore what the solutions and non-solutions might be.

On Apple and the community

This is the bit that I’d done most work on already, as it was the topic of my Appsterdam talk. The summary of that talk is pretty much the same as Dave’s working-with-Apple pro tip in his iOSDevUK talk. As his was more succinct, I’ll use that version:

Apple is people too. Don’t be a dick.

(I’m a fan of people not being dicks.)

The thing is that as Scotty said, the community wins when all of its members win. But he also said that Apple isn’t in the community, so don’t they obviate themselves from this relationship?

Well, no. If we look at the community that most of the people reading this post – and that most of the people at iOSDevUK – consider themselves a member of, it’s the community of iOS app makers. It happens that all of these people depend on the same thing: on iOS. Being nice to Apple and helping them just makes good business sense. If you’re not helping Apple to win, they might decide to help you lose.

On a related subject: for Apple to win, it’s not necessary for anyone else to lose. In fact, I’m not the first person to say this. I’m stealing from a man who was, at the time this quote was coined, freshly CEO after having been a management consultant at Apple:

We have to let go of this notion that for Apple to win, Microsoft has to lose. We have to embrace a notion that for Apple to win, Apple has to do a really good job. And if others are going to help us that’s great, because we need all the help we can get, and if we screw up and we don’t do a good job, it’s not somebody else’s fault, it’s our fault.

So Microsoft, Windows 8 and Windows Phone 8 don’t have to lose. Google and Android don’t have to lose. Enterprise Java programmers don’t have to lose. Your competitors don’t have to lose. The team in Apple that make that thing that just crashed don’t have to lose.

On that last note, Apple is the biggest company in the world and you’re supplying one or a handful of 600,000 or so different replaceable components that helps them make a trivial fraction of their income. So if the choice you give them is “do what I need or I’ll stop working with you”, they’ll pick option 2. “Fix Radar or GTFO”? It’s cheaper and easier for Apple to GTFO.

That’s not to say the best strategy is always to do whatever Apple want. Well, actually it probably is in the short term, but Apple is real people and real people benefit from constructive feedback too.

Just who is “them”, anyway?

Around the time that I started to be a proper software writing person, there was a strong division in Mac development. The side I was in (and I was young, opinionated, easily led, and was definitely in this faction) was the Yellow Box. We knew that the correct way to write software for the Mac was to use the Foundation and AppKit APIs via the Objective-C or Java languages.

We also knew that the other people, the Blue Boxers who were using libraries compatible with Mac OS 8 and the C or C++ languages, were grey-bearded dinosaurs who didn’t get it.

This sounds crazy now, right? Should I also point out that I wrote a Carbon app, just to make it sound a little crazier?

That’s because it is crazy. Somehow those of us who had chosen a different programming language knew that we were better at writing software; much better than those clowns who just made the most successful office suite ever, the most successful picture editing app ever, or the most successful video player ever. Because we’d taken advice on how to write software from a company that was 90 days away from bankruptcy and had proven incapable of executing on software development, we were awesome and the people who were making the shittons of money on the most popular software of all time were clueless idiots.

But what about the people who were writing Mac software with WXWindows (which included myself), or RealBASIC, or the PerlObjCBridge (which also included me)? Where did those fit in this dichotomy? Or the people over on Windows (me again) or Solaris (yup, me here)?

The definition of “us” and “them” is meaningless. It needs to be, in order to remain fluid enough that a new “them” can always be found. Looking through my little corner of history, I can see a few other distinctions that have come and gone over time. CodeWarrior vs Project Builder. Mach-O vs CFM. iPhone vs Android. Windows vs Mac. UNIX vs VMS. BSD vs System V. KDE vs GNOME. Java vs Objective-C. Browser vs native. BitKeeper vs Monotone. Dots vs brackets.

Let’s look in more detail at the Windows vs Mac distinction. If you cast your mind back, you’ll recall that around 2000 it was much easier to make money on Windows. People who were in the Mac camp made hand-waving references to technical superiority, or better user interfaces, or breaking the Microsoft hegemony, or not needing to be super-rich. Many of those Mac developers are now iPhone developers. In the iOS vs Android distinction, iOS developers readily point to the larger amount of money that’s available in making iOS apps…wait.

O(community)

The community contribution fraction

As Scotty said, an important role in a community is that of the reader/consumer/learner, the people who take and use the information that’s shared through the community. Indeed in any community this is likely to be the largest share of the community’s population; the people who produce and share the information are also making use of it too.

The thing is, that means that there are many people who are making use of those great ideas, synthesising them, and making even new and better ideas. And we’re not finding out about them. Essentially there is more knowledge than there is opportunity to share knowledge.

It’d be great to have some way to make it super-easy for everyone who was involved in “the community” to contribute, even if it’s just to add a single thought or idea to the pool. As Scotty said, there’s no way you can force people to contribute, and that’s not even desirable as it’s a great way to put people off talking to you ever again.

So you can’t hold a gun up to people and force them to tell you a fact about Objective-C. You can ensure everyone knows what forms of contribution take place; perhaps they’ll find something that’s easier than they thought or something they’ll enjoy. Perhaps they’ll give it a go, and enjoy it.

Face to face

Conferences are definitely not that simple way for everybody to contribute. Conferences are great, though as I’ve said before there aren’t enough seats for them to have a wide direct impact on the community. Tech conferences will never be a base for broad participation, both due to finite size (even WWDC comprises less than one percent of registered developers on the platforms) and limited scope for contribution – particularly the bias toward contributors with “prior”.

One “fix” to scale up the conference is to run the conference all year long. This allows people who don’t like the idea of being trapped in a convention with the same 200 people for a week the option to dip in and out as they see fit. It gives far more opportunity for contribution – because there are many more occasions on which contribution is needed. On the other hand, part of the point of a conference is that the attendees are all at the same place at the same time, so there’s definitely some trade off to be had.

Conferences and Appsterdams alike lead to face-to-face collaboration; the most awesomest flavour of collaboration there is. In return, they require (like Cocoaheads, NSCoder or whatever you call your pub/café meet) that you have the ability to get to the venue. This can call for anything from a walk down the street via a couple of ten-hour flights to relocating yourself and your family.

Smaller-scale chances for face to face interaction exist: one-on-few training courses and one-on-one mentoring and apprenticeships. These are nearly, but not quite, one-way flows of information and ideas from the trainer or sensei to the students or proteges. There are opportunities to make mentoring a small part of your professional life so it doesn’t seem to require a huge time investment.

Training courses, on the other hand, do. Investment by the trainer, who must develop a course, teach it, respond to feedback, react to technology changes and so on. Investment by the trainees, who must spend an amount of time and money attending the course, then doing any follow-up exercises or exams. They’re great ways to quickly get up to speed with a technology by immersing yourselves in them, but no-one is ever going to answer the question “how can I easily contribute to my community?” with “run a training course”.

Teaching at a distance

A lower barrier to entry is found by decoupling the information from the person presenting the information. For as long as there has been tech there have been tech books; it’s easy (if you have $10-$50) to have a book automatically delivered to your house or reader and start absorbing its facts. For published books, there’s a high probability that the content has been proofread and technically reviewed and therefore says something a bit accurate in a recognisable language.

On the other hand, there are very few “timeless” books about technology. Publisher schedules introduce some delay between finishing a manuscript and having something to sell, further reducing any potential shelf life. If you’re in the world of Apple development and planning to say anything about, for example, Objective-C or Xcode, you’re looking at a book that will last a couple of months before being out of date.

Writing a book, then, takes a long time which already might be a blocker to contribution for a lot of people. There’s also the limitation on who will even be invited to contribute: the finite number of publishers out there will preferentially select for established community members and people who have demonstrated an ability to write. It’s easier to market books that way.

The way to avoid all of that hassle is to write a blog (hello!). You get to write things without having to be selected by some commissioning editor. Conversely, you aren’t slowed down by the hassles of having people help you make the thing you write better, either—unless you choose to seek that help.

You then need to find somebody to read your blog. This is hard.

Stats for this blog: most pages have only ever been read a couple of hundred times.

If someone else already has an audience, you can take advantage of that. Jeff Atwood previously wrote about using stack overflow as a blog, where you’d get great reach because they bring their audience. Of course, another thing you can do on stack overflow is answer questions from other people: so that quick answer you contribute is actually solving someone’s problem.

This is, in my opinion, the hallowed middle ground between books (slow, static, hard to get into, with a wide reach) and blogs (fast, reactive, easy to pick up, hard to get discovered). Self-publishing a book is a lot like spending ages writing a long blog post. On the other hand, contributing to a community resource like a Q and A site or a wiki means only writing the bit of the book that you’re best placed to contribute. It also means sharing the work of ensuring correctness and value among the whole contributor base.

Our community / People with ideas ≪ 1

Whatever your definition of “the community”: the iOS developer community, the object-oriented programming community, the developer community—there are many more people who aren’t in that community. But they still have things to say that could be interesting and help us see what we do in different ways.

I’m not so sure that there are people out there doing what we do who don’t even passively engage with the rest of the community. Maybe there are, maybe there are lots. But I’m sure most people have at least read a book, or done a search that ended up at a mailing list post or blog entry. Very few people will never have used community-supplied resources; although it’s possible that there are programmers out there who’ve learned everything they know from first party documentation.

What I am sure of is that if you’re an Objective-C developer building mobile apps and you only listen to other Objective-C developers building mobile apps, you’re missing out on the information and ideas you could be taking from everyone else. Dave Addey told us to go and visit museums and art galleries to get inspiration, but that’s not all there is to it. Talk to someone doing Objective-C in a different context. Talk to someone doing Java, or Clojure. Talk to business people, or artists, or musicians. Break out of the echo chamber, and find out whether what other people are doing could be applied to what you’re doing.

Conclusions

As promised, there aren’t really any conclusions here. It’s more a collection of my own thoughts dumped out from brain to MarsEdit in order to let me make sense of them, and to stop me having to think about them at bedtime.

What’s clear is that there are a load of different ways for people to contribute to a community. Consumption of other people’s thoughts, advice and ideas is itself a very beneficial service as it’s how new ideas get synthesised, how new practices are formed and how the community collectively improves its output. It would be even better if what those people were doing were also made available and shared with the rest of us, to achieve an exponential growth in experience and advancement across the whole community.

But that’s not guaranteed to happen. The best thing to do is not to try driving people to contribute, but to give them so many opportunities to do so that, at some point, someone in the community will be in the position that sharing something is really easy and they choose to do so.

Other techniques to improve the number of ideas you get from the community are to be less adversarial in your definition of community, and more broad in your inclusion. The “community of people making iOS apps with Objective-C” is small, the “community of people making things” is universal.

Adding components to a GNUstep web / WebObjects app

In WebObjects, Components take the role of a view controller in what passes for Cocoa’s version of MVC. Each is responsible for calculating the data that the view objects are bound to: you saw an example of this in the previous post. Each is also responsible for responding to user interface events—called actions—and preparing the next component where that’s required.

Navigating between components

Let’s add a new component to our HelloGSW test app. We’ve recorded the date that the visitor arrived at the site, we could (for sake of demonstration, not because it’s useful) find out how long it takes that visitor to get to the next page. We’ll come onto the mechanics of adding it to the project later, but for now we note that we require a way for the visitor to indicate their intention to see the next page. That means, as a simple way to do things, having a form with a submit button.

We could write the form into the HTML, but then we’d have to know what URL the WO machinery was going to use to call our action. So we’ll use WebObjects to generate the form, using this HTML:

 <webobject name=form>
   <webobject name=submit_button><INPUT TYPE="SUBMIT"></webobject>
 </webobject>

As you’ve seen, the data bindings for each webobject need to be defined in the WOD file:

form:WOForm {}
submit_button:WOSubmitButton {action = nextPage}

As with the value binding you saw last time, we can bind the action of the submit button to a method on the component. Those of you who have used Cocoa Bindings may be surprised to find that you can do the same with NSResponder subclasses, though it’s rare to see it done with Mac apps.

So finally, I GIVE YOU TEH CODEZ:

- (GSWComponent *)nextPage {
  ClickDelay *nextComponent = (ClickDelay *)[self pageWithName: @"ClickDelay"];
  nextComponent.startDate = accessedAt;
  return nextComponent;
}

As with view controllers on the iPhone, you just create the new component (-pageWithName: does that, and configures its context correctly) and configure state where appropriate. Unlike with iOS view controllers, you don’t specify how they get presented because there’s only one way that will (probably) ever happen: in an HTTP response. So you can just return the next component from the method and the Right Thing™ will happen. If you return nil, the visitor will see the current component again (though with a whole server round-trip and a fresh HTML response, so it’s best to do some AJAXey thing: on which more later!).

If you’re really interested in how the other component works, check out its source from GitHub.

But that’s not why we’re here.

Adding a component involves a boatload of boilerplate: five new files, and a change to the GNUmakefile. That’s one more boatload than you’d like to write every time you create a new page in your web app, yes?

Yes. Therefore what I actually did was to write a script to do all of that boilerplate for me. It’s really basic (error checking is for security boffins. Oh, wait.) but will do the necessary dance. Just be sure not to run it twice for the same component yet…

What I really need is a tool that’s both more robust, and that can generate the other things you need in writing a WO app. I’ll start right now, but pull requests are always welcome…

Using Objective-C on the server

My talk at NSConf was about cross-platform Objective-C. Those people who I talked to after the session will know that my goal is clear. There are plenty of people out there who have learned Objective-C to get onto the iOS or Mac app stores. Those people need some server-side smarts in their apps, and want to benefit from the skills they’ve already acquired. In other words: they want Objective-C on the server.

I’m now in a position to offer that :). I took a look at the GNUstepWeb project, a reimplementation of WebObjects 4.5. It was in a fairly parlous state, and wouldn’t even build on my Mac. I’ve fixed that. It’s still a bit of a faff, but we’re in a position to start playing with server-side ObjC and see whether there’s any value in having a better product.

Building GSW on the Mac

GNUstep-make

First, you need to grab GNUstep from SVN. Now you need to compile GNUstep-make, the build system. On Mac OS X you do the following:

cd modules/core/make
./configure --with-library-combo=apple-apple-apple
make
make install

The weird configure invocation tells GNUstep you’re going to use the Apple Objective-C runtime, and the Foundation (and AppKit) libraries instead of GNU replacements.

GNUstep-make includes a shell script that defines the locations of various folders. You should import that into your shell environment:

. /Library/GNUstep/Makefiles/GNUstep.sh

Consider adding that line to your .bash_profile.

GNUstep-base

Then you build the GNUstep-base extensions, some additional classes and macros for working with Foundation code.

cd modules/core/base
./configure
make
make install

GDL2

GDL2 is the GNUstep Database Library; an EOF-like framework for interacting with databases. If you’re going to use a DBMS like MySQL for your web apps, you should install that and its developer headers before doing:

cd modules/dev-libs/gdl2
./configure --disable-gorm-palette
make
make install

(Aside: GORM is the GNUstep version of Interface Builder. You don’t need the plugin for working with entities in GORM, and you can’t build it on Mac OS X so that’s why it’s disabled in the configure invocation.)

GNUstepWeb

Now here’s the good stuff. Build and install GSW. At time of writing, there’s an open bug that stops it building on Mac OS X, so you’ll need to grab the patch from this bug report. Apply that patch, then:

cd modules/dev-libs/gsweb
./configure
make
make install

A sample app

You probably want to see a sample GSW app, so it’s a good job I wrote one :-). Clone the HelloGSW project on GitHub. I’ll show you how to build and run that before we get into how it works.

Building HelloGSW

cd HelloGSW
make

Running HelloGSW

HelloGSW.gswa/Contents/MacOS/HelloGSW

this will spit a load of output to the console, including a URL that looks like http://localhost:9001/WebObjects/HelloGSW.woa/0/. Open that URL in your browser. You should see this:

Hello from GSW

HelloGSW code walkthrough

The interesting code is in the Main class, which is a subclass of GSWComponent (and conventionally the default component to show for a new visitor). Each “page” in a GSW app is a component, though of course you could arrange to return XML, JSON or any other format rather than HTML. HTML is the default and the easiest to work with, and indeed we’ll start by looking at a section of the HTML file, Main.wo/Main.html.

 <p>The time is <webobject name=now_string></webobject>.</p>

This is clearly the paragraph that puts the date onto the screen, but you can see that there’s this weird <webobject> tag in there. That’s going to be substituted with our date object at runtime, but how? To answer this question, look at the Main.wo/Main.wod file.

now_string:WOString {value = now}

This file contains bindings, which if you’re familiar with Cocoa work pretty similar to Cocoa Bindings. This tells us that there’s a web object called now_string, that it’s an instance of WOString, and that its value binding is bound to something called now.

That now binding is actually a key on the component object. We might expect to see a method called -(NSString *)now defined on Main to fill in the value of this string. Indeed, if we look at Main.m:

- (NSString *)now {
  NSDate *theDate = [NSDate date];
  return [theDate description];
}

Where to go from here?

The start is to build more GSW apps, and of more complexity. However there are things that need to be done along the way: all of the rest of the code and files in this project are meaningless boilerplate. This stuff needs to be hidden, automated or removed. Then we can also automate the process: compare how much of a faff setting up this app was with running a Rails app in Heroku (and I haven’t even set up an adaptor to a real web server!). It’d be really useful to simplify common tasks in modern web applications, such as exposing REST interfaces and non-HTML document formats.

Conclusions

Objective-C is not just a client app language. It’s got a long heritage as a server technology, but unfortunately the tools for doing that are quite out of date. They’re still useful though, so people who have come into the Objective-C fold recently can expand the use of their newly-found skills. Hopefully people will adopt—and contribute to—GNUstepWeb and help everyone to make it a useful modern server technology.

A Cupertino Yankee in the Court of King Ballmer

This post summarises my opinions of Windows Phone 7 from the Microsoft Tech Day I went to yesterday. There’s a new version of Windows Phone 7 (codenamed Mango) due out in the Autumn, but at the Tech Day the descriptions of the new features were mainly the sorts of things you see in the Microsoft PressPass video below (Silverlight required), the API stuff is going on in a separate event.

I want to provide some context: I first encountered C#, J# and .NET back in around 2002, when I was given a beta of Visual Studio .NET (Rainier) and Windows .NET Server (which later became Windows Server 2003). Since then, of course most of my programming work has been on Objective-C and Java, on a variety of UNIX platforms but mainly Mac OS X and iOS. But I’ve kept the smallest edge of a toe in the .NET world, too.

From the perspective of the phone, however, I really am coming to this as an iOS guy. Almost all of the mobile work I’ve done has been on iOS, with a small amount of Android thrown into the mix. I’ve used a WP7 phone a couple of times, but have no experience programming on WP7 or earlier Windows Mobile platforms.

The UI

The speakers at the Tech Day – a mix of Microsoft developer relations and third-party MVPs – brought as much focus on user experience and visual impact of WP7 apps as you’ll find at any Apple event. Windows Phone uses a very obviously distinctive UI pattern called Metro, which you can see in the demo screencasts, or the Cocktail Flow app.

Metro is almost diametrically opposed to the user experience on iOS. Rather than try to make apps look like physical objects with leather trim and wooden panels, WP7 apps do away with almost all chrome and put the data front and centre (and, if we’re honest, sides and edges too). Many controls are implicit, encouraging the user to interact with their data and using subtle iconography to provide additional guidance. Buttons and tiles are far from photorealistic, they’re mainly understated coloured squares. Users are not interacting with apps, they’re interacting with content so if an app can provide relevant functionality on data from another app, that’s encouraged. A good example is the augmented search results demoed in the above video, where apps can inspect a user’s search terms and provide their own content to the results.

In fact, that part of the video shows one of the most striking examples of the Metro user interface: the panorama view. While technologically this is something akin to a paginated scroll view or a navigation controller, it’s the visual execution that makes it interesting.

Instead of showing a scroll thumb or a page indicator, the panorama just allows the title of the next page to sneak into the page you’re currently looking at, giving the impression that it’s over there, and if you swipe to it you can find it. When the user goes to the next page, a nice parallax scroll moves the data across by a page but the title by only enough to leave the edges of the previous and next titles showing.

The Tools

It’s neither a secret nor a surprise that Microsoft’s developer tools team is much bigger than Apple’s, and that their tools are more feature-rich as a result (give or take some ancient missteps like MSTest and Visual SourceSafe). But the phone is a comparatively new step: WP7 is under a year old, but of course Windows Mobile and Compact Editions are much older. So how have Microsoft coped with that?

Well, just as Apple chose to use their existing Cocoa and Objective-C as the basis of the iOS SDK, Microsoft have gone with .NET Compact Framework, Silverlight and XNA. That means that they get tools that already support the platform well, because they’re the same tools that people are using to write desktop, “rich internet” and Xbox Live applications.

From the view-construction perspective, XAML reminds me a lot more of WebObjects Builder than Interface Builder. Both offer drag-and-drop view positioning and configuration that’s backed by an XML file, but in Visual Studio it’s easy to get precise configuration by editing the XML directly, just as WebObjects developers can edit the HTML. One of the other reasons it reminds me of WebObjects is that Data Bindings (yes, Windows Phone has bindings…) seems to be much more like WebObjects bindings than Cocoa Bindings.

Custom classes work much better in the XAML tools than in IB. IB plugins have always been a complete ‘mare to set up, poorly documented, and don’t even work in the Xcode 4 XIB editor. The XAML approach is similar to IB’s in that it actually instantiates real objects, but it’s very easy to create mock data sources or drivers for UI objects so that designers can see what the app looks like populated with data or on a simulated slow connection.

Speaking of designers, an interesting tool that has no parallel on the iPhone side is Expression Blend, a XAML-editing tool for designers. You can have the designer working on the same files as the developer, importing photoshop files to place graphics directly into the app project.

It’d be really nice to have something similar on iPhone. All too often I have spent loads of time on a project where the UI is specified as a photoshop wireframe or some other graphic provided by a web designer, and I’m supposed to customise all the views to get pixel-perfection with these wireframes. With Blend, the designer can waste his time doing that instead :).

Other tools highlights include:

  • Runtime-configurable debugging output on both phone and emulator, including frame rates, graphics cache miss information, and Quartz Debug-style flashes of updated screen regions
  • The emulator supports virtual accelerometers
  • The emulator supports developer-supplied fake location information and even test drivers generating location updates <3

The biggest missing piece seems to be a holistic debugging app like Apple’s Instruments. Instruments has proved useful for both bug fixing and performance analysis, and it’s pretty much become a necessary part of my iOS and Mac development work.

Update: I’m told by @kellabyte that an Instruments-like tool is coming as part of the Mango SDK, and that this was announced at MIX ’11.

The “ecosystem”

A couple of the demos shown yesterday demonstrated phone apps talking to Azure cloud services, ASP.NET hosted web apps (mainly using the RESTful OData protocol), SOAP services etc. Because there’s .NET on both sides of the fence, it’s very easy to share model code between the phone app and the server app.

That’s something Apple lacks. While Cocoa can indeed be used on Mac OS X Server, if you want to do anything server-side you have to either hope you can find some open-source components or frameworks, or you have to switch to some other technology like Ruby or PHP. While Apple ship that stuff, it’s hard to claim that they’re offering an integrated way to develop apps on iOS that talk to Apple servers in the same way that MS do.

To the extent that WebObjects can still be said to exist, it doesn’t really fill this gap either. Yes, it means that Apple provide a way to do dynamic web applications: but you can’t use Apple’s tools (use Eclipse and WOLips instead), you can’t share code between iOS and WO (iOS doesn’t have Java, and WO hasn’t had ObjC in a long time), and you can just about share data if you want to use property lists as your interchange format.

On the other hand, it’s much easier to distribute the same app on both iPhone and iPad than it would be to do so on WP7 and a Microsoft tablet/slate, because their official line is still that Windows 7 is their supported slate OS. I expect that to change once the Nokia handset thing has shaken out, but making a Silverlight tablet app is more akin to writing a Mac app than porting an iOS app.

The market

This is currently the weakest part, IMO, of the whole Windows Phone 7 deal, though it is clear that MS have put some thought and resources behind trying to address the problems. Given that Windows Phone 7 was such a late response to the iPhone and Android, Microsoft need to convince developers to write on the platform and users to adopt the platform. The problem is, users are driven to use apps, so without any developers there won’t be any users: without any users, there’s no profit on the platform so there are no developers.

Well, not no developers. Apparently the 17,000 apps on the marketplace were written by 7,500 of the 42,000 registered developers (and interestingly the UK has one of the lowest ratio of submitted apps to registered developers). By comparison, there are 500,000 apps on the app store.

Microsoft has clearly analysed the bejeesus out of the way their users interact with the marketplace. They have seen, for instance, that MO billing (essentially having your phone operator add your app purchase costs to your phone bill, rather than having a credit card account on the marketplace itself) increases purchase rates of apps by 5 times, and are working (particularly through Nokia of course who already have these arrangements) to add MO billing in as many marketplace countries as they can.

This makes sense. People already have a payment relationship with their network operators, so it’s easier for them to add a few quid to their phone bill than it is to create a new paying account with the Windows Marketplace and give Microsoft their card details. By analogy, iPhone users already have bought stuff from Apple (an iPhone, usually…and often some music) so throwing some extra coin their way for apps is easy. Incidentally, I think this is why the Android app market isn’t very successful: people see Google as that free stuff company so setting up a Checkout account to buy apps involves an activation energy.

Incidentally, some other stats from the app marketplace: 12 downloads per user per month (which seems high to me), 3.2% of all apps downloaded are paid, and the average price of a bought app is a shave under $3. Assuming around 3 million users worldwide (a very rough number based on MS and analyst announcements), that would mean a total of around $3.5M app sales worldwide per month. That’s nowhere near what’s going on on the iPhone, so to get any appreciable amount of cash out of it you’d better have an app that appeals to all of the platform’s users.

The subject of appeal is a big issue, too. Microsoft aren’t really targeting the WP7 at anyone in particular, just people who want a smartphone. With Mango and Nokia handsets, they’ll be targeting people who want a cheaper smartphone than RIM/Apple/Android offers: I bet that brings down that $3 mean app price. This is, in my opinion, a mistake. Microsoft should play to their strengths, and make a generally-useful device but target it at particular groups who Microsoft can support particularly well.

Who are those groups? Well, I think there’s Xbox 360 gamers, as WP7 has Xbox Live integration; and there’s enterprises with custom app needs, due to the integration with Azure and similarity with ASP.NET. It ought to be cheaper for game shop that’s written an Xbox game to do a WP7 tie-in than an iOS tie-in. It ought to be cheaper for an enterprise with an MS IT department to extend their line-of-business apps onto WP7 than onto Blackberry. Therefore MS should court the crap out of those developers and make the WP7 the go-to device for those people, rather than just saying “buy this instead of an iPhone or Android”.

The reason I’d do it that way is that you bring the users and the developers together on shared themes, so you increase the chance that any one app is useful or relevant to any given customer and therefore increase the likelihood that they pay. Once you’ve got gamers and game devs together, for example, the gamers will want to do other things and so there’ll be a need for developers of other classes of app. I call using Xbox games to sell utilities the Halo Effect.

Conclusion

Windows Phone 7 is a well thought out mobile platform, with some interesting user experience and design. It’s got a good development environment, that’s highly consistent with the rest of the Microsoft development platform. However, no matter how easy and enjoyable you make writing apps, ultimately there needs to be someone to sell them to. Microsoft don’t have a whole lot of users on their platform, and they’re clearly banking on Nokia bringing their huge brand to beef up sales. They should be making the platform better for some people, and then getting those people on to the platform to make WP7 phones aspirational. They aren’t, so we just have to wait and see what happens with Nokia.

Footnote: Nokisoft

Nokia do well everywhere that Microsoft doesn’t, by which I mean Europe and China mainly. Particularly China actually, where the Ovi store is pretty big. Conversely, MS phone isn’t doing too badly in America, where Nokia traditionally are almost unheard of. So on paper, the Nokia deal should be a good thing for both companies.