Word Chop

Word Chop

A Flutter Project Retrospective

I recently released version 1.0 of my word game Word Chop on the Apple App Store and Google Play Store. Since this is my first Flutter app, I thought I would write a little about my experience with Flutter and the Dart programming language. Usually when I write about anything I end up writing way too much, and I am sure this will be no different. I really love the sound of my own typing.

The Project

Word Chop, as the name suggests, is a word game. 99.9% of the code-base runs on both iOS and Android, which a few plug-ins helping me in the very few instances where I needed platform-specific code. Google's Flutter toolkit makes it very pleasant to write cross-platform software. I will discuss a little later where Flutter may or may not be right for your project.

Word Chop is a single-person project, built over a period of around seven full-time weeks. Those 280 hours were actually stretched over several months, which tells you a little about my work ethic and attention span. [1]

Flutter

The Pros

Whilst Flutter can be used to make apps that look like stock native iOS or Material apps, I think the best Flutter apps I have seen are strongly branded and have custom UIs. A few features make custom UI building a pleasure:

  • Hot Reload: This is probably the killer feature that attracts many developers to using Flutter in the first place. It definitely was for me. Without gushing too much, it is amazing. I am using the now 7-year-old trash-can Mac Pro, and hot-reload means I can save any code-changes and see the results in the simulator or on a device in under a second. I can have multiple simulators and connected devices and see the results in around a second too. Even in rare situations where I need to force a Hot Restart, this only takes a few seconds. (I know SwiftUI and React Native also support hot reload, but I cannot comment on how Flutter's performance compares to those options.)
    The obvious benefit of hot reload is that I can tweak my UI very quickly. Where this really shines is getting 'responsive' layouts to work on different shaped phones, on iPads in portrait, landscape, split-screen, etc.
  • The Widget library: Google attracts some incredibly capable engineering talent and it has very clearly invested a lot of resources into both Flutter and Dart. Looking at the architecture of Flutter, by reading the documentation or digging into the code, so much thought has been put into making a standard library of useful and well-designed UI elements.
    The built-in Flutter widgets generally adhere to a principle of 'do one thing well'. For example rather than setting a 'padding' property on a button, you wrap your button in a Padding widget. Because refactoring support is so good (next bullet point), there is no reason that your Widget tree has to get unwieldy. Having a large nested tree of widgets doesn't seem to be a problem for performance either. I test on phones as old as my trash-can Mac and it is easy to get buttery smooth animations and scrolling.
  • IDE support: I have stuck mostly to Visual Studio Code for the past few years because it has been 'the easiest path' for much of the work that I have needed to do. I started building Word Chop in VS Code and the Flutter/Dart support is fantastic. It definitely pays to spend a little time learning or customizing the keyboard short-cut to bring up the Show Fixes menu:

    The 'Show Fixes' keyboard shortcut is the same shortcut used to offer fixes to problems in your code - unused variables, unused packages, linter warnings, etc. The Flutter plugin extends these fixes to offer a number of very frequently used Widget manipulations - wrap the current widget with another one, remove a widget, move a widget around, etc. It is invaluable.
    (In Android Studio this menu is called 'Show Context Actions'.)
    Whilst Visual Studio Code is excellent, I ended up using Android Studio for most of my project. JetBrains makes amazing IDEs, so it is great that Android Studio is available for free. I used Android Studio because I find the debugging experience superior to VS Code. The Flutter team does a great job on the plugins for both Android Studio and VS Code.
    Android Studio also has a few Flutter tools - Flutter Inspector, Outline, Performance, which I don't think VS Code has. There is also the Flutter 'Dev Tools' which is browser based and offers some nice features tracking down performance problems as well.
  • Great documentation: The documentation on flutter.dev and dart.dev is excellent and most of the documentation is right there in the source-code. Navigating to great documentation inside your editor is only a keyboard short-cut away.
    The Flutter YouTube channel has heaps of great content as well. There are dozens of 'Flutter Widget of the Week' videos that show how common widgets work in about 90 seconds or less. I have watched all of them. It is a great way to get some familiarity of what is available out of the box. 'The Flutter Boring Show' has much longer and in-depth discussions of many Flutter topics. I think they are also a great resource.

The Cons

  • Easy to learn, difficult to master: As is often the case, I progressed quite quickly at first when building Word Chop. The first time I hit a bit of a road-block was when adding a particular animation - animating letter tiles returning to their original positions on the board if the user chooses to undo their current word.
    Flutter has very powerful animation support so I thought this task would be quite easy. However I had build the 'board' and the 'tray' (the row below the board) as separate widgets, as an excellent software engineer would be expected to do. (In fact the Board and Tray widgets are based on the same widget because they share a lot of the same behaviour and child widgets.)
    Widgets in Flutter cannot directly discover or communicate with their siblings so my Tray widget couldn't ask the Board widget the on-screen positions to animate the tiles back to. This encapsulation is of course quite deliberate and stops hacks like myself from building a pile of unmaintainable silly-string.
    My 'undo' animation feature sent me down a rabbit hole to discover that the Flutter widget tree is actually just one of three trees that Flutter maintains at run-time and that widgets don't really know anything about their on-screen position. Also getting the Tray and Board to communicate got me learning about Dart streams and Flutter Provider (InheritedWidget) and the various common ways that developers architect their Flutter apps. After quite a few hours and a few missteps I managed to get my animation working and gained a better understanding of how Flutter works. This work gave me a pattern to achieve similar animations, including my 'victory' tile animations, as well as other more advanced features.
  • Not For Every Project: I think Flutter was a perfect choice for my particular project. I never encountered any significant roadblocks to getting the project to 'version 1.0'.
    Notably, Word Chop does not require any platform-specific features. If I wanted to take advantage of the rich text editing features in iOS, for example, Flutter would possibly not be a very good choice. Flutter is a bit like a game framework like Unity or Unreal Engine. It renders the entire screen and even though it is possible to make apps that look very much like native iOS apps, they are not using any native iOS UI rendering code. Flutter is 'faking' it.
    It is possible to build 'hybrid' apps that host native Android and iOS views, but there are some trade-offs of course.

Dart

As well as building the Flutter app itself, I also wrote quite a bit of supporting code to generate the puzzles and to parse Wiktionary into a form that I could use as my game dictionary. My Dart program is able to process the tens of gigabytes of Wiktionary EN XML in a few minutes on a single Mac core - in interpreted mode.

A lot of the success of Flutter as a platform is due to the hard work of the Dart compiler team. Dart should be a very comfortable language to use for anyone who has written C#, Swift, Java, JavaScript, etc. It also has a few nice extras thrown in.

I have a very strong preference for statically-typed programming languages, so Dart 2.0 (released in 2018) ticks that box for me. They also have null safety in beta, so that will make many Swift programmers very happy. (I love Swift optionals, but I haven't yet moved Word Chop to null safety.)

Here are another touches that I like about Dart

  • optional new: when constructing an object, the new keyword has been optional for quite a while and practically no new code uses it. It removes a lot of noise from Widget trees, for example.
  • constructor short-cuts: A constructor like MyWidget({@required this.property1, this.property2}); will automatically assign the values of property1 and property2 if passed by the caller. It is nice to eliminate that obvious boiler-plate.
  • async/await: very common in programming languages these days, but I am old enough to still appreciate it.
  • Fast AOT-compile or fast interpreter for Hot Reload: Release builds are fast. Running your interpreted Dart code in the Simulator or on a device is still fast enough to be productive using Hot Reload. It is truly the best of both worlds. I have already mentioned this feature, I know, but I am still totally enamoured.
  • Control your code layout with commas:

    Android Studio and VS Code can both automatically format your Dart code on save. I am constantly saving to reformat my code which saves a lot of busy work. By choosing to place an extra comma at the end of parameter lists or arrays you can control if your code is automatically split on multiple lines or kept together. The formatter also obeys your margin. I love it!
  • linter: The linter works nicely with Android Studio and VS Code. I use the 'pedantic' package with some extra rules in to give myself an even greater sense of self-satisfaction and smugness.

Conclusion

This turned out to be less of a blog post and more of a list of reasons that I am smitten with Flutter and Dart. I am guessing that you can tell that I had a great time building Word Chop. I really did. I have been programming for more years than I would like to admit and Flutter has rekindled a lot of the feelings that I got from playing with Logo back in the eighties as a kid. (Okay, I guess I did admit how old I am.)
The immediacy is addictive. It is going to be pretty hard to go back to some paying gig writing back-end ASP.NET APIs and waiting a seeming eternity for my code to recompile. As the project drags on the compiles get slower and slower...

Word Chop

If you made it this far, then maybe you can see if Word Chop is actually any good? Here are the store links below:

Footnotes

[1]: If it looks like a pretty simple app for seven weeks of effort, then please choose one of the following options:

  • I am an unproductive software developer (strong possibility)
  • I did a great job of making something not-so-simple look simple
  • Flutter is an unproductive toolkit for building software (nope)

Also, the 280 hours includes about 50 hours of me futzing around with graphics and animation, an area where I am absolutely not an expert.

[2]: So I only bothered making one footnote, until I added this one.