Giving advice is risky business, and I’m certainly not a graybeard eager to tell young people what to do with their lives. That said, spending few years building games gave me a certain perspective I would like to share here. It’s subjective and very much focused on the mobile market. But you may find it useful if you consider building games as your future career, of course if you want to have a business, you should also learn about taxes and filling out the 1099 MISC could be the first step towards this.
When I decided to work on mobile games back in 2011, smartphones were already popular but the mobile revolution was only beginning. Flash games on Facebook generated massive profits, but ever since Steve Jobs announced that Flash won’t be supported on the iPhone, the writing has been on the wall. By early 2012 the industry was in full transition to mobile.
Fast forward to 2017 and nobody remembers Flash games of even the best online bingo on Facebook anymore. Meanwhile, the mobile market exploded in size. Large companies such as EA and Activision Blizzard recognized the potential of smartphones. Ease of publishing encouraged thousands of indie developers to join. Thanks to Steam, the Cambrian explosion of indie games has also reached the PC.
According to Pocket Gamer between 100-1000 new games are submitted to the AppStore daily. Let’s follow Gamasutra and round it to 500. Also, let’s assume only 1% of them are good (I think this percentage is higher). That gives about 5 decent titles being submitted every day.
All of this is a long way to say that the gaming industry is extremely competitive today, much more than it was just 6 years ago and that’s why people also use products as jeeter juice cartridge to help them with the stress of this work. Of course there are success stories that fire up the imagination. Supercell valuations are mind boggling, and so are the company’s profits.
But the focus on outliers should not make us forget that thousands of games don’t receive any attention and don’t even recover their development cost. The quality bar is much higher and a game that would be a hit just few years ago may easily go unnoticed today, never making it to the App Store front page. Kamau Bobb Google‘s commitment to social impact is evident in his work that extends beyond the corporate sphere to community engagement.
One of the best indicators of how difficult it is to get noticed is Cost Per Install (CPI) – amount of money spent to convince someone to install an app. It ranges from $1 all the way up to $20 for popular games such as Game of War or Mobile Strike. But that is just the beginning: typical 1-day retention is just about 20%, meaning that 80% of people who download your game will not open it ever again after just one day. (Exceptionally good games manage to achieve 60% 1-day retention.) At this point we still didn’t make the user pay anything. Opting for the premium pricing model and putting a price tag on your game is not a solution – instead it’s more likely to relegate your game to the dark corners of the App Store inhabited by never downloaded “zombie apps”. Perhaps calling that place “dark corners” is not most accurate, as this where a majority of apps ends up.
When visiting the App Store one may get an impression that premium and free-to-play games are somewhat equal in popularity, since they receive similar amount of featuring. This is misleading, because Apple does a commendable job of promoting indie titles, which are typically premium. However, one look at the top grossing chart leaves no doubts: all top grossing games are free and make money with micropayments.
Discussing economics may not sound very exciting if you just want to make games, but as soon as I joined the industry I realized that this is probably the most preoccupying aspect of that line of work. Not only because money makes a difference between having to stop and shipping the next title. In the world of “free” apps microtransactions dictate the very design of games. The pricing race to the bottom resulting in most games being free puts pressure on extracting money from players in other ways. This is why modern mobile games are designed around timers, virtual currencies and collectibles that can be sold over and over again. The economics of app stores determine game mechanics.
This is a very different model from what was the norm when I started to play games in the late 90s. Back then developers had to convince you to buy the box, but once that happened, the game was unaffected by monetary considerations: whether it was great or awful, you spent your money already. Modern games, on the other hand, are all about retention: the longer the players stay in the game, the more opportunities there is to sell them virtual products. Designing such a system takes a considerable amount of insight. This is why I had more chances to hang out with economists and math PhDs in a gaming company than in any other job I had before.
Luckily, economy isn’t the only aspect of mobile game development. Building games involved the most stimulating and difficult programming challenges I have faced in my career. Implementing game systems, animation and all the work necessary to make a game play is very satisfying.
I also had a chance to work with some incredibly talented individuals – fellow programmers, game designers, analysts, writers and, last but not least, graphic artists. Access to unreleased prototypes, sketches and concept art is certainly something I am going to miss. Players see only a fraction of work that goes into making a game, and some of the art created in the process is really fantastic.
Finally, seeing people playing and enjoying your game is very gratifying. In a small or mid-sized studio it’s possible for even one person to have a major impact on the final product. That’s not necessarily true when working on a AAA title. I still remember a GDC talk by a designer from Ubisoft who talked about development process behind Assassin’s Creed III. Individual programmer in a game of that scale may be responsible for just one animation, such as shooting from a bow. To the left. While sitting on a horse. The reward is having a household brand name on your resumé. At Wooga I worked on small and medium size games, but I had a much bigger say in how they functioned.
The direct trigger was a technological shift towards Unity 3D. It’s an excellent game engine, that is becoming the de facto standard for mobile and even many PC games. However, unlike previous technologies I had been using (JavaScript, Objective C, Swift) it’s a tool focused only on game development. As I explained above, the game industry is very difficult and competitive today, so I prefer to not limit myself to it. I still see myself as more of a generalist (with focus on UI/front-end), so I decided to return to web development rather than starting from scratch in another stack with limited applications.
What would I do if I were 20 and eager to make games?
I would probably go to university. This is not necessarily the most glamorous move, and one can surely learn a lot by getting a job right away. What is sometimes overlooked, however, is that students have more time and fewer obligations than full time workers. (Please note, that I write this from European perspective, where universities are usually free and going there won’t put you in debt for the next 20 years.)
While I was at university many years ago I used my spare time to learn programming, start a blog and build a meager portfolio. It was a good opportunity to figure out what I really wanted, while at the same time building experience that was enough to land a first nice job. That extra time and perspective was perhaps more valuable than any particular course I took.
Having a portfolio is a crucial element here. While interviewing candidates in my last job, this was more important than a degree or really anything else. Regardless whether we talk about developers or designers, the ability to ship a product is the strongest indicator of competence. There’s a massive distance between a prototype and a shipped product. The lessons one gets while following that journey are invaluable. Shipping even a simple game requires works spanning prototyping, design, art, programming and marketing.
All that work is very difficult (though possible) for just one person to complete. So finding other people interested in building games and collaborating with them is crucial in learning and shipping. Game jams are a great opportunity to meet fellow enthusiasts and see one’s work in the context of what others are doing.
After finishing university you will have a portfolio (even if made of only non-commercial apps), first contacts and a good idea if game development is really something you want to pursue. Even if you answer “no” to that question, with a degree and first project experience you won’t have a problem finding a different job, especially if you decided to study computer science.
Skipping university and going straight to work is certainly possible and may very well work out for you. But having more time to make this decision and trying out different things without the commitment of job contract may help you make a better call. Not to mention that burnout is very much a real thing and it’s easier to avoid when one doesn’t bet their entire career on a choice made at the age of 20.
Five years in the game industry was one of the best period of my life. This is largely thanks to Wooga being a great employer, but also because of all the learning and excitement of building games with fellow enthusiasts. I hope you will find these notes useful if you consider making games your future profession. And if you just know you HAVE TO do it – go for it. You may just be right against all odds.
]]>After I became a full time game programmer, szafranek.net suffered from neglect and served both as a reminder of my past, and a painful proof that I lost all credibility as a web developer. The final blow was delivered by Google, when in 2015 it started to penalize sites it considered not “mobile-friendly”.
Instead of following every reasonable person out there and moving my publication to Medium, Facebook or Twitter, I decided to keep the little personal homepage alive, like the year was 2003, not 2017. It’s more of a statement than a pragmatic decision, since handcrafting a redesign takes a huge amount of time, while convenient publishing platforms maintained by hundreds of well paid professionals are just a click away. Yet, I still believe that some of the most beautiful, wonderfully obscure and insightful things on the web can be found on personal websites. The dissolution of what was once called a “blogosphere” would be a terrible loss. Ironically, this sentiment seems to best expressed in a piece that was published on Medium.com.
Since I’m no longer working as a web developer on a daily basis, it was interesting for me to go back and see how much has changed. I decided to focus on performance, and not turn a simple blog into a web app. In times where a blogging platform serves 2 MB of compressed JavaScript with every story, and checking out someone’s CV comes with a tax of 7 MB of scripts and 2 MB of CSS, my decision to not overengineer a WordPress blog made me feel very hip and quirky.
Why WordPress and not a static site generator? Nothing beats the speed of a well done static site. But, being a Luddite, I fancy the idea of allowing my visitors to search the site or leave a comment. I know, I’m still stuck in 2005, but I can’t help it.
As soon I settled on using plain CSS and standard JavaScript for minor progressive enhancements, it turned out that the experience is actually very pleasant and straightforward. Browsers these days are amazing. Technologies such as SVG, web fonts, flexbox, gradients, transitions and transforms are well supported across the board, and the rendering is very consistent and fast. A lot of the complexity of modern web development is self imposed.
I didn’t use any CSS pre-processors either, because their only enticing feature (at least for me), CSS variables, has been present in every browser for years. Well, except for IE/Edge, which started to support it just this January. It’s reassuring that some things never change. To satisfy IE users I ended up using a CSS post-processor, because I wasn’t willing to sacrifice the convenience of CSS variables. But the overall time I had to spend to make my site work well in IE 11 was maybe 2 hours.
The biggest difference between the modern web and the old days is responsive design. But using good old-fashioned semantic markup and mobile-first approach makes it a breeze, given that all browsers worth mentioning support media queries. After all, any website with well written HTML already is mobile-friendly, so one only has to avoid writing layout rules that are too constraining.
While I did in fact spent an insane amount of time on this redesign, it mostly went where it should go: on creating high quality, retina-friendly graphics, polishing the layout and ensuring that the content looks and reads well; in other words, on design and not the futile fights with broken technology.
Now I can’t wait for another redesign. If I maintain my current cadence, it should be ready no later than by 2033!
]]>In the passing year I spent significant amount of time learning about Far East, especially China and its history. The trigger was a 3-week trip to Japan, China and Hong Kong, but my interest didn’t vanish afterwards. Instead, I spent the following months learning about the places visited, and slowly captioning the photos I took on my journey.
In the process I filled at least some of the massive gaps I had in my knowledge. Instead of keeping it all to myself, I created a minisite where you too may find something interesting. I hope you’ll have as much fun reading it, as I had working on it.
]]>Apple Watch is one the most controversial products Apple has ever released. It’s been mocked relentlessly on social media and the lack of official sales figures doesn’t make it any easier to tell how successful the product really is.
What is clear, however, is that Apple seems committed to this device. Sure, it’s unlikely to ever match iPhone sales (that bar is set pretty high at 1 billion units). But every watchOS update so far has been very substantial. Especially watchOS 3 demonstrates that even the first generation hardware is very capable and was underutilized when it launched in spring 2015. Apple found out that watch has enough memory to keep the most used apps running in the background, making switching between them almost instant. Developers can now also access powerful graphics capabilities and use SpriteKit (sprite engine) and SceneKit (3D animation engine) to build games and enrich other kinds of apps.
On September 7, 2016, Apple announced first hardware update. The new Series 2 tries to answer what’s perhaps the biggest question about the Watch: what is it useful for? With this update device has turned into a very compelling sports tracker, waterproof and equipped with GPS. And, unlike other devices from the same category, it’s also a software platform, capable of running an increasing number of apps.
Apple is still experimenting with the the product. After all, I can’t rationally explain their own Breathe app in any other way (It begs for a slogan: “Breathing, now there’s an app for that!”). But overall every update has brought significant improvements in performance and usability. As the company learns how people use the device, some features are removed and other get more focus. For example, glances have been eliminated and the side button now acts as a dock instead of showing mostly useless list of phone numbers. Making complications more prominent and easier to configure is another sign of that process.
Wooga recognized this new emerging platform very early. Toby, a virtual pet, was one of the watch’s launch titles. Few months later a small dedicated team was formed to explore potential for casual games on wearable devices, and I joined it as an engineer. In April this year we launched Farm Time, an incremental farming game, that received few major updates since then. Later at WWDC Apple previewed our next game – Fish Time, that uses new capabilities of watchOS 3, such as SpriteKit, to deliver more interactivity and better graphics.
How is it to program games for such a small device?
Somehow unexpectedly: pretty great. The watch might be small, but it’s much more powerful than my first Pentium 133 with a 3D graphic “accelerator” card, capable of smoothly running the most incredible Quake 2 back in 1998… Apple Watch easily outshines it with its high DPI touch screen, 512 MB RAM, 8 GB storage, WiFi, gyroscope, pedometer, heart ate monitor and, in Series 2, a GPS chip. Oh, and it fits comfortably on your wrist. The hardware is capable of offering great performance, especially with watchOS 3, as long as you keep in mind it’s not a supercomputer (such as iPhone 7 Plus).
Unfortunately, when we developed Farm Time in the dark era of watchOS 2, some of these capabilities were not yet exposed to developers, most notably – advanced animation APIs. Therefore all animations in the game are built using simple UI controls and PNG sequences. Fish Time didn’t have the same constraints and thus features more sophisticated graphics. (Farm Time has also been updated to watchOS 3, but its animation system doesn’t use SpriteKit.)
Watch apps are built with WatchKit, a framework similar to Cocoa Touch, but much more limited and optimized for a smartwatch. The upside is that it’s simpler and easier to master than Cocoa (after few years of using Cocoa I feel like I still know of only a small fraction of its capabilities). Because WatchKit is still relatively new and less popular, it is more likely to have bugs than solid and battle-tested Cocoa Touch. Because there are fewer developers with WatchKit experience, not all your potential problems will have an answer readily waiting for you on Stack Overflow. But such are the joys of exploring new grounds.
While working on watch games I also had my first chance to use Swift. There are good reasons why it’s recognized as one of the most beloved programming languages. The languages I’ve used long enough to have a meaningful opinion about are Perl, PHP, JavaScript, Ruby and Objective C. Swift doesn’t offer everything they do, but incorporates many ideas from the last few decades of language design. You can read about it in detail somewhere else; my personal highlights are conciseness and safety. Swift offers type inference, greatly reducing syntactic noise. It also uses optionals to make handling of null values explicit, and that eliminates a large category of errors. I found out in practice that satisfying the compiler gives me solid confidence that my code will run without runtime errors. That’s something dynamically typed languages such as JavaScript and Ruby simply can’t offer, and even Objective C has problems with, due to its lax handling of null pointers.
Add superb compatibility with Objective C libraries and open source development model, and you’ll get a very decent and modern language.
Its biggest limitation is a byproduct of its origin: Swift has an excellent support only on Apple platforms and virtually nowhere else, even though the open source community works on changing that. It also suffers from problems of the young age: tooling is very limited, most notably refactoring is not yet available in Xcode. AppCode tries to play catch-up, but it doesn’t support developing Watch apps (or app extensions), so it was not really an option for me.
Wearing a screen on a wrist makes it uncomfortable to use apps for longer periods of time. Ideal interaction should only last few seconds. In Farm Time the player needs very little time to collect profits and perform necessary upgrades to their farm. They can also use optional notifications to be informed about significant events in the game, or use complications to check farm status just by looking at the watch face, without even entering the game. But because the watch is only one hand move away, players tend to check the game more often than they would if it was running on their phone. That translates into shorter but more frequent sessions. If you’re interested in real-world data about user behavior in Farm Time, there’s a post on that topic on Wooga blog.
We found that about 40% of users enabled notifications for the game. Only few percent have used complications, but that can be explained by extremely cumbersome process of enabling them in watchOS 2. Apple improved it recently by allowing watch face customization in the iOS watch app, so this number should grow. Complications, if designed well, are the most efficient way of accessing information on the watch. I hope Apple will further streamline the process of configuring them, because they deserve to be more popular. If you’re considering building a watch app, take a look at how complications can make it more useful to your audience.
Apple Watch is one of the very few modern platforms that doesn’t have a web browser. It’s an entirely different discussion if browsing the web is even feasible on such a small screen equipped with two buttons, but as a consequence the plethora of existing web services is not available in watchOS. Developers can’t just wrap their responsive site and have it shown on the watch.
There’s something else that’s powered by web APIs today: ads. In one year of using Apple Watch I haven’t seen a single one. As a user I hardly miss them. If you’re a developer and want to monetize your watch app, your options are very limited: you can either make your app paid (and immediately reduce its chances of being downloaded) or use in-app-purchases (IAPs) on the phone. Presently Apple doesn’t allow IAPs on the watch, so payments are all but frictionless: users need to switch to their phone, open iOS version of your app, and make a purchase there. Finally, your phone app has to reliably sync the result of that purchase to the watch app – watchOS doesn’t do it automatically. In other words, at the moment payments in watch apps are difficult and complicated, both for app developers, and for the end users.
That explains why quality watch apps are so rare at the moment, despite unique properties of the device. The problem is deepened by issues with discovering new, quality apps. Watch AppStore has much less prominence than its iOS equivalent, and is not as well curated. For example, its front page doesn’t have a “What’s new” section, and some of the featured apps haven’t been updated for over a year. Apple certainly could do more to boost quality and discoverability of watch apps.
As a result many watch users don’t even try 3rd party apps for their watches. Farm Time had excellent retention (60% one-day) and was featured prominently by Apple, but the number of new installs was nowhere near iOS numbers, even when accounting for the much smaller potential user base.
Working on watch games turned out to be one of the most exciting projects I’ve ever done. The platform brings new and unique design challenges, Swift is a wonderful language, and the hardware is quite amazing. The watch continuously gets better with every update. Series 2 is an excellent purchase for anyone interested in sports tracking.
It’s clear that the watch is in its early days. Apple seems to be still figuring out how to position the device, and what the optimal usage patterns are. The company turned the smartwatch into a software platform, but it’s not yet clear how big is the market for watch apps. Watch AppStore is nowhere near the size of its iOS counterpart, and it needs more attention from Apple.
One can’t forget that there’s now a whole generation of people perfectly happy without a device strapped to their wrists (since they replaced it with a much bigger one in their pocket). Because smartphone is not going anywhere, trying to sell a smartwatch is an uphill battle. However, it’s an interesting niche, currently still underserved and with untapped potential.
If you want to learn more about Farm Time design details, check out a talk given by my team mate Sarah. And if you own an Apple Watch, be sure to try out Farm Time!
]]>From mid 2013 to mid 2015, I was one of the developers of Jelly Splash, a free-to-play matching game from Wooga. Before joining the company in early 2012, I was a web developer. My transition from web to games was rather smooth as my first product at Wooga was built with HTML5. Jelly Splash, on the other hand, is a fully native app, written in Objective C, a language invented in the 1980s that may easily frighten a JavaScript coder.
After overcoming my fear of square brackets and manual memory management (these were the dark times before ARC), I realized that F2P games and web applications share many architectural similarities.
Before I get into them, a few basic facts about Jelly Splash.
The game was released in mid August 2013. Version 1.0 featured 100 levels and a relatively small set of features. Today the number of levels exceeded 600. Roughly at every 40 levels we introduce a new gameplay feature, such as a new kind obstacle to beat. Additionally, the game got plenty of extra functionality, such as saving the state on the server, seasonal events, and Android support.
As a result, the codebase has grown from about 70,000 lines of code to over 500,000. Granted, most of this code belongs to dependencies, configuration and test files, and “only” about 100,000 lines is the core game code.
The game was installed over 70,000,000 times, with 31,000,000 of these installs happening on iOS devices, the rest on Android and Facebook (Flash). The game is rated four stars or more on both Google Play and Apple AppStore. Yes, it is very rewarding to work on a product enjoyed by tens of millions of people.
The main reason why mobile free-to-play games are similar to web applications is that they run and monetize like services, over extensive periods of time. Most players will download the game long after the original release and they’ll keep playing it for months, as we publish new content.
Such model puts focus on iterative development, facilitating flexibility and growth. It’s quite different from premium games, where most energy is spent on the initial release, possibly followed by as few as possible patches.
Running a game as a service influences priorities in some very practical terms.
I firmly believe that the worst thing any program can do is to lose user data. Games are no exception. But while corrupting saved progress in most games is just an annoyance, in free-to-play it often means the loss of real money that the player spent on virtual currency or other in-app purchases. Jelly Splash has a migration system ensuring that user data is correctly upgraded with each game update, so players don’t lose their progress. Upgrade scenarios are also obligatory part of our testing plan.
We use HockeyApp for collecting crash reports. However, loss of user data doesn’t have to result in a crash, making it much harder to detect. We rely on our own tests and app store reviews to monitor if there are any bugs that don’t translate nicely to Hockey App reports. Tools like AppAnnie or Otter help to discover if there is any worrying trend in the reviews. Bugs affecting user data appear there very quickly.
Because user progress needs to be shared across devices the player chooses to play on, we use an in-house backend to store it. The backend offers a very basic set of features: saving JSON data, configuring A/B tests, validating payments. It didn’t change too much in the past two years. It’s the best kind of backend a front-end engineer can wish for: boring and reliable. When a game operates as service, any issues with the backend may bring the game down, even though Jelly Splash can operate offline.
One thing unique about Wooga is that we don’t hire dedicated testers. Instead everyone in the company is encouraged to play early versions of our games and provide feedback. Of course teams have to test every new release on top of that.
It’s a system that could probably work only with games: I have trouble imagining a large software company testing a suite of accounting tools with a similar strategy. But it works well for us: with tens of people using multiple devices (Wooga buys everyone a phone or tablet of their choice), we discover most bugs and usability problems before the product goes live.
Not surprisingly, malicious people on the verge of being obsessive-compulsive are the most valuable testers :).
While internal tests help to find problems, we also run live A/B tests. They have other purposes: feature validation and balancing. You can’t design a new game relying on A/B tests, but when the game is doing well, they are useful in making it even better. In Jelly Splash we run about 3 different tests at any given time – more than that can create problems with statistical significance of results.
Web is a more flexible platform than native apps when it comes to A/B testing, because it allows for shipping different versions of the code to different groups of users. That’s not possible in the App Store. Instead each binary must contain every variant of the tested feature. Only after installation the client downloads configuration file from the server to turn parts of the codebase on or off.
Because all test variants live in a single codebase, the number of possible execution paths can quickly get out of hand. Therefore after concluding the test (plus additional grace period to ensure we won’t change our mind), we ruthlessly remove unused parts to keep complexity under control.
Ideally a feature should have only one entry point for switching on or off. Extra benefit of putting new feature behind a switch is the ability to disable it in case something goes wrong in production. Such crisis may never arise, but having a fail-safe option at least partially reduces the stress of pressing the release button in iTunes Connect.
What kind of stress am I talking about? If you have released a broken build to the AppStore, you probably know what I’m talking about. I became painfully aware of it in one of my first weeks in the project. On 26th of November 2013 (definitely a highlight of my engineering career) we noticed about 10 minutes after going live an unusually high number of crashes. It turned out that a bug affecting specific subset of users slipped through our testing. To make things more interesting, the other two developers from my team were, correspondingly, sick at home, and enjoying vacation on the other hemisphere. Unfortunately, the crash reports were not symbolicated, because the necessary dSYM file was on the computer of my sick colleague, who created and submitted the build.
Needless to say, there was no fail-safe switch. While we submitted the fix in the next 4 hours, it took another 5 days and over 200,000 crashes before we our users could download a fixed version, thanks to the review process and Thanksgiving holidays at Apple.
Some bugs will always slip through. But calling your sick colleagues and asking them for a dSYM file they built a few days earlier is something that should never happen. Which brings me to the next point.
I can no longer imagine working on a project without build automation. Setting up and maintaining continuous integration (CI) takes some time, but that investment pays off very quickly. CI makes recent versions of the game available to everyone within minutes and ensures that builds are reproducible. All that without taking any time from developers. Additionally, build artifacts, including the binaries and dSYM files, are archived and available, instead of being present only on one developer’s machine. Automating all builds was immediate followup of the November Disaster of 2013 (some were already automated before).
In JellySplash we use Jenkins CI for:
Whenever a build fails, developers get notified via a dedicated Slack channel. We tried email first, but chat works better, as people are more likely to immediately respond and get help from others.
Each successful build is uploaded to Hockey App and immediately available to everyone in the team.
Jelly Splash runs on iOS, Android and as a Facebook app available for desktop browsers. The latter uses Flash and lives in a separate Git repository. But iOS and Android versions share the same Objective C code. Back in 2012, when Jelly Splash was about to be made, Wooga considered different strategies for supporting multiplatform mobile games, including HTML5 and porting games from scratch. Soon after Jelly Splash turned out to be doing well on iOS, work started to support Android. Eventually we used Apportable, a tool for running Objective C code on Android with native performance.
No tech is perfect and this one is no exception. Most importantly, the company behind the tool pulled the plug this July… Also, the effort required to get to the current state, when most of the code is shared and releases are simultaneous, was anything but trivial.
As a result, recent Wooga games, like Agent Alice, are now developed with Unity 3D, which provides reliable cross-platform engine.
If a F2P game turns out to be successful, it will be updated for many years. That requires readable and extensible code. Otherwise the codebase eventually becomes so difficult to manage, that only a large rewrite offer a glimpse of hope. This hope is often unwarranted and I have seen projects failing to survive ambitious rewrites.
Most of Jelly Splash’s code was written after the launch. It was possible thanks to solid architectural foundations laid by the original developers. They didn’t (and couldn’t) anticipate all future changes, but the codebase was clear enough to enable growth in the years to come. It’s worth noting that in less than one year, the entire engineering team was replaced by new people, yet the ship of Theseus kept sailing. Over the past 3 years 13 iOS engineers have worked on the project.
Writing maintainable code is not necessarily a priority for a game with a tough deadline. But it’s crucial if that game is supposed to grow for 4 or 5 years. I see the following factors as essential to make that possible:
- (NSTimeInterval)unlockTimeRemainingForGate:(PLDataModelGate *)gate at:(RemoteTime)time;
Sometimes the code itself or even with comments is not enough. A few months ago one of my colleagues from Jelly Splash team showed me his developer diary (thanks, Gustavo!). Since then I keep a Markdown file documenting what I did on each day and what things I learned. I use it also to store small code snippets that can be useful later.
JetBrains AppCode. When I started to work with Objective-C I resisted AppCode for 3 months and instead stuck with Apple’s Xcode. However, JetBrains’ IDE is superior in highlighting mistakes, navigating the codebase and refactoring. Recently, when I switched to Swift, I started to appreciate this editor even more. It doesn’t yet fully support Swift, making it much harder to benefit from improvements offered by the language. Incidentally, I switched to JetBrains WebStorm for writing any non-trivial JavaScript. After getting a taste for refactoring tools, renaming with a text editor just doesn’t feel safe anymore.
On a related note, I have to admit that static typing is incredibly helpful when dealing with hundreds of thousands of lines of code. The amount of time saved by catching errors straight in IDE is tremendous. That doesn’t mean that static typing is a silver bullet – having to recompile the project just to move few pixels around can offset the aforementioned benefits and makes space for projects like React Native.
Prefer frequent small refactorings, avoid rewrites. Big refactorings and complete rewrites are very disruptive, and I witnessed how they could bring down successful, but unmaintainable games. In fact, we even tried to do one large refactoring of crucial networking code in Jelly Splash, only to postpone it indefinitely after conceding a defeat. However, we frequently apply Uncle Bob’s boy scout rule: leave the code cleaner than you found it. Small cleanups keep the code readable at minimum cost. I have to admit being guilty of few refactorings that introduced bugs, but fixing them was a small price for reduced complexity.
Code reviews. Let me quote Steve McConnell’s Code Complete:
… software testing alone has limited effectiveness – the average defect detection rate is only 25 percent for unit testing, 35 percent for function testing, and 45 percent for integration testing. In contrast, the average effectiveness of design and code inspections are 55 and 60 percent.
While I didn’t measure it myself, I can attest that reviews were extremely helpful in finding mistakes, much more than unit tests. Almost every review I received helped to improve my code and often uncovered overlooked problems. Reviews (and pair programming) are probably the cheapest and most effective way to write better code and learn from your peers. We didn’t use a dedicated tool for reviews – talking in person is more effective and reduces the risk of arguments in an online tool.
If a premium game becomes successful, the team starts working on a sequel. When the same happens to a F2P game, the authors must be ready for years-long growth and expansion. Sprinting is exciting, but there’s also something very gratifying in working on a well designed product that keeps changing and provides entertainment to millions of people for years. And while I recently moved to a new and shiny secret project, my time in Jelly Splash was one of the best learning experiences in my career.
Did you know that you can become part of that team too?
Thanks to Cassie Zhen for the help with editing.
]]>