A few weeks ago, I unveiled a weekend project that I’ve been involved in for several months called ChessJam. I am now making good on my promise to share why we the selected the technologies behind this desktop application for playing online head-to-head chess. Obviously this is primarily a personal project but there is a very good Adobe-technology basis to it, so I feel compelled to “evangelize”! My first instinct was to post all of the source code but my development partners quickly reminded me that this is a commercial product so I’m going to be walking a thin line in this post.
User Interface / Front-end
This was by far the easiest decision we made. Adobe Flex was a no-brainer. We simply didn’t have time to do it in anything else! We considered doing a browser-based game but Adobe AIR offered some compelling advantages:
- Network detection – we can detect network connectivity issues and react accordingly
- Idle user detection – we can detect if the user has stopped using their keyboard and mouse and cleanly log them out
- UI control – we can better control the user experience by managing every aspect of the UI including position, size, chrome, etc.
We didn’t have the time (nor the desire) to write our own AI engine that understands the rules of chess, so we purchased a third-party library for this. Our first build vs. buy decision.
Choosing the right server technology required a bit of discussion. I knew that I would be the primary developer for the back-end so this decision was a big one for me! The main purpose of the server-side code was to act as an interface between the client app and the database. The server would also be a message “dispatcher” to the multiple clients notifying them of other user’s activities such as moving pieces in the game, entering rooms, initiating challenges, and so on.
We considered the following technologies:
- Java – I have prior Java experience and have built multiple products, both commercial and free using Java. I also knew that Java was well suited for Flex but I was concerned about the time it would take.
- PHP – My development partners have some prior PHP experience but my PHP experience is only at the hacker level, so I felt that the learning curve would add too much time to the schedule.
- ColdFusion – Despite the fact that I work for Ben Forta, I wasn’t sure ColdFusion was a good fit for our project. I had only a little experience with ColdFusion and did not consider myself an expert. During a conversation with Ben about our back-end requirements, he made some very good points. (1) Writing ColdFusion to do basic database work is super-fast and easy to learn. (2) ColdFusion and Flex work very well together. (3) ColdFusion has good messaging support with LCDS or BlazeDS. (4) ColdFusion administration is simple. After this conversation, I did some additional research and decided that ColdFusion might actually be the right choice. I grabbed a copy of the 3-book “ColdFusion 8 Web Application Construction Kit” series and did some selective speed reading. At the time of this decision, ColdFusion 9 was not even in beta yet so I decided to stick with 8. When it comes to production software, I tend to be a bit conservative. A side effect of my newly found affection for ColdFusion was that I participated in the CF user group tour for CF9 which was a lot of fun. I refuse to get on stage in front of a bunch of developers and “evangelize” about something I’ve never seriously used but now that I was doing the CF deep-dive, I finally felt I was qualified.
There’s not really much to say here other than I love the stability, efficiency and flexibility of Linux. I have many years of experience developing and managing large-scale applications built on Unix-based operating systems so it’s definitely my comfort zone. I chose 64-bit Ubuntu 8.x (was the latest at the time – I have yet to upgrade to 9.x).
We selected MySQL for the database engine. It’s solid, fast, easy to setup and administer, and it just works. I’ve never used MySQL in a large-scale application with this many anticipated transactions so we’ll see how it holds up. The data model itself is fairly straightforward. I avoided triggers and stored procs to keep our options open moving forward. So far MySQL is doing well. I’m even using a couple of memory-only tables for very transitional/temporary data such as a list of who is logged in, etc. I typically would create a memory structure for this but using a memory-only table reduced the amount of code I had to write.
Flex applications can make remote calls to ColdFusion out-of-the box with no additional software so we were set. However, we needed a middleware technology for sending messages from client to client and server to client. These messages are used for player-to-player chat, notifications that a move has been made and many other game events.
BlazeDS vs. LiveCycle Data Services (LCDS):
Both BlazeDS and LCDS offer publish/subscribe messaging. ColdFusion 8 comes bundled with LCDS (although a separate license purchase is required if you use it for more than one CPU) so this was the path of least resistance. LCDS also supports RTMP (real-time messaging protocol), a very high-performance, scalable option.
Note: ColdFusion 9 now comes with BlazeDS, not LCDS, but LCDS can be integrated. We used ColdFusion 8 so no additional integration work was needed.
Proof of Concept
At this point, we had selected the tools and technologies we would use to build ChessJam. However we still were not 100% convinced that we had what it would take to build this complex application so we decided to build a series of mini proof-of-concept apps.
- Flex calling a CFC that returns data of various types – check!
- Subscribing to a real-time message feed using a Flex mx:Consumer – check!
- Publishing real-time messages from Flex using mx:Producer – check!
- Publishing real-time messages from ColdFusion using an Event Gateway (DataServicesMessaging) and receiving them in Flex – check!
Todd Williams (twitter) and I had several discussions about how this application should be structured. There were many factors to consider because our long-term plans were lofty. We wanted to support multiple simultaneous games, multi-level chat, auto-reconnection to ongoing games, tournament play, team play and much more. We agreed that this project was well beyond the scope of the “just sit and code” approach. We needed a plan!
I’ve worked with Holly Schinsky (twitter) for over 10 years on several very large projects and I know that she has a good sense for architecture and design patterns so I shared our basic requirements with her and asked for recommendations. A couple of days later, Holly sent us a skeleton Flex project based on a MVCS architecture that she felt would be a good starting point for us. Todd and I studied it and decided that it was a great starting point.
So, with our lists of requirements, screen mockups, mind maps and weekend enthusiasm, we started coding!
Some code snippets
I wish I could post the entire Flex project and CFCs but that’s not possible. However, I at least want to give you a flavor of it.
Flex calling ColdFusion
Below is a snippet of code showing how we call backend ColdFusion functions defined in several CFCs. There are backend functions for user validation, logging of moves, game initiation and much more. Calling ColdFusion from Flex is super-easy. Once you get it working for one function, it only takes a few seconds to implement new ones. Most of our functions return a string, number or query result (array collection). You’ll find tons of additional information on ColdFusion remoting at http://www.adobe.com/devnet/flex/flex_cf.html. There are additional resources on Adobe TV including one that Ben Forta created that helped me get started at http://tv.adobe.com/watch/adc-presents/building-flex-applications-powered-by-coldfusion
Implementing pub/sub messaging for client-to-client communications via LCDS
We use pub/sub messaging extensively in ChessJam for game event notifications and chat. Below is a simple example of how we implemented in-game chat.
Implementing pub/sub messaging for server to client communications via LCDS
There are several features in ChessJam that require messaging from the server to the client app. For example, every time someone enters a room in ChessJam, the server broadcasts the event so that anyone monitoring the room will see the person enter. We also use server-produced messages for other notifications, message broadcasts and automated chat messages. Below is a snippet from both the ColdFusion side and Flex side. In order for the ColdFusion sendGatewayMessage() function to work, you’ll need to set up an instance of the DataServicesMessaging gateway type in the ColdFusion administrator. Here’s our setup (with certain data obfuscated of course):
Once configured, I can use the ColdFusion sendGatewayMessage() function to produce messages that any subscribed Flex consumers can consume:
From proof of concept to production
The first few development milestones were ugly and simple web-based clients that allowed a basic game to be played between two users. Here’s a rough list of early milestones:
- Person to person game in a browser (no artwork yet)
- Basic chat capabilities
- Game reconnects (if you shutdown your app and reconnect while the game is still going, you will automatically rejoin the game)
- Game observe functionality (you can watch someone else’s game being played – useful for tournaments, etc.)
- Towers and rooms – real-time updates to the clients when other users leave and enter.
- Idle user detection (server-side) – a simple CFM that goes through a bunch of queries every 5 minutes to manage timeouts of idle games, etc.
- Artwork and our first AIR build. This was a fun one! Todd completely blew us away with his designs
- Login, create profile, update profile, reset password and other boring things that had to be done
- Extensive server-side logging of activity so we could keep an eye on things in real-time
- The first ChessJam Shakedown – we invited 20 friends and family members to install our early build and play so we could see how things worked. As we expected, we found tons of bugs! For example, a game observer could click the forfeit button and end a game that they were not participating in! This is one of about 100 bugs we found.
- Code, build, test, code, build, test, code, build, test, code, build test, …
- Auto-update, idle user detection (client-side), network connectivity monitoring, etc.
- 1.0 complete!
- Robots! – blogged about here – 24 computer-based players for practicing your skills
- Challenge court and buddy lists – blogged about here
- More coming soon! We need more weekends!
A few stats
We continue to see good, consistent growth of our user base with practically zero marketing. We wanted to ramp up slowly so we could get a few more features implemented and bugs flushed out. As of this writing, here are some stats:
- 80,000 moves made! This is one of our primary metrics since it is a direct indication of how much people are playing.
- Between 5,000 and 6,000 moves a day with consistent growth
- 1900 games played
- Almost 1,000 users from over 88 countries (less than 50% are from USA, which surprised us considering that we’ve done no marketing)
I’m not going to share all of our dirty laundry but like any new application, we have a few open issues. Memory management is a bit of a challenge for us, especially for users that stay in the game for several hours. We continue to make progress in this area so I’m not worried about it. We also occasionally see issues with players who have low-bandwidth/high-latency connections when making rapid moves, although for now, the latest version seems to be holding up well.
As time allows, we’re working on some new things:
- Simultaneous game play – a tab-like interface that allows you to play multiple games at once.
- Correspondence chess – for people that don’t have time for live play. This feature allows each player to move when they can. You can play several games at once and make a move only once per day.
- Tournaments! We have some fun plans for tournaments. We already have enough “regulars” to put together our first tournament. Based on my personal game record, I can tell you that I will most likely NOT be the winner of this tournament! When I do have time to play a game on ChessJam, I typically get destroyed.
- User game tracking and reporting. The data is there now. We just need some time to build out a nice interface.
- A few surprises that I won’t unveil here
- From a technology stack point of view, I’ll be upgrading to ColdFusion 9 soon. I usually don’t jump on the latest version of anything this soon but so far, I’m hearing very good reports from other ColdFusion administrators. ColdFusion 9 will buy us a bit more performance and we are eager to take advantage of some of the new features such as an expanded cfscript support, improved CFC performance, default data sources, and some of the new EXT2 functionality including an improved datagrid. For now, I’ll probably stick with Ubuntu 8.x since there is no compelling reason to go to 9 for our app. If it ain’t broke, don’t fix it! We will definitely be testing with AIR 2.0 soon. AIR 2.0 promises to improve memory consumption, CPU consumption and offers a lot of new APIs.
If you haven’t tried ChessJam, check it out. It’s free for now. We do intend to monetize this some day for the obvious reasons but for now, we’re focused on building a fun community.
UPDATE: ChessJam is now upgraded to ColdFusion 9 / LCDS 2.6.1.