During a gap year between my second and final year of studies, I delved into mobile development with the Flutter framework and spent about 3-4 months upskilling in framework.

The largest project I worked on was a dream journal that had a few unique features that mainly concerned the location of dreams while linking together similar appearing locations.

Learning From Mistakes

Although the app wasn’t completed, it was a project that introduced me to the most programming concepts. Since it was the first medium sized project, many problems that are quite common during any projects development were encountered. The small issues that compounded taught a wealth of knowledge and are listed here:

Database

For local storage (Isar DB) was used. It was fast and very easy to use (developer friendly) - but it had stopped maintenance as the apps development started so it wasn’t noticed until later. The DB was a community driven project and was mainly led by one person. With Flutters fast update cycle the DB was essentially legacy code in a few months - other more recent packages that were used were conflicting with Isar. And since development started with backend for this project (repositories, services, controller model was what was used as it was what the Flutter docs recommended), the more packages that were added, the more arduous the project became to manage with dependency conflicts mainly occurring between Isar and Flutter. Flutter couldn’t be updated since Isar would break, and the other packages used would also need to be used with their old versions since they wouldn’t work with older Flutter versions.

Too many packages

This brings me to the next problem - too many packages were being used. The term dependency hell was only understood after building this project. Before starting this project I believed that frequent use of dependencies was smarter as it sped up development - ‘don’t reinvent the wheel’. Multiple dependencies for UI, dependency injection, some ease of life features and other small additions - these all compounded into not being able to keep up with what was added.

When using dependencies, a developer has to learn their respective functions.The more dependencies that are added, workload increases exponentially on the developer with each package having it’s own numerous functions and it’s docs to sift through to find the specific feature that’s needed. Not to mention sifting through forums if something breaks down. LLMs do help with exploration but it’s worse when the package isn’t used by many people.

Flutters material theme

It’s always been fun for me to make something unique - like this websites theme for example. Flutters adherence to the Material 3 UI scheme made this quite difficult for the apps development. It makes Flutter applications look somewhat the same. The types of buttons, symbols on them, the layout - it didn’t feel extensible and was almost locking the app to a certain style. A neomorphic aesthetic was tried for the app, but it felt like the code was working against the framework the entire time. Compared with css and html to make a website, Flutter felt too limiting.

Project Structure

The project may have been getting too large (for a small medium sized app). There were folders that weren’t intuitively organised and if a break was taken from the project for a week or so, coming back to it would be very confusing. This was likely due to inexperience. After completing my CS degree and looking back, it feels as though managing larger file structures is a lot easier after having experienced more of them. Still - a carefully thought out project structure is a better experience than a rushed one.

Dependency Injection

Dependency injection was an important concept that was learnt for larger projects. Flutters in-built dependency injection framework wasn’t great and other developers online recommended other third party packages that handled it. Implementing third party dependency injection (Riverpod) after already having built some of the project wasn’t a great idea as it became another one of the numerous packages to manage and keep track of.

Flutters update speed

At the time Google was updating Flutter relatively quickly. Functions from first-party packages could be deprecated within a few months. It isn’t a great developer experience creating something requiring persistent upkeep.

Summary

These mistakes were made due to inexperience and I am glad to have experienced them quite early. They taught me that great programs can be built with minimal code. Less code is less error prone and can be easily managed - making it safer and more enjoyable to work with.

The main takeways from this project were:

  • Try to build with less code
  • Don’t heavily rely on third-party frameworks
  • When choosing frameworks, choose based on stabiliity and utility