Inside ImaginationOverflow Apps – Folder and Project Structure
For the last three years I’ve been developing apps for Windows Phone/Windows 8.1. In the beginning it was just for fun, and also an attempt to understand the app ecosystem and the technology involved, very soon I figured out that making app is much more than coding. Everything you do in an app, starting with code organization, all the way to how you talk with users, is critical to an app success. This is my way to contribute to the community that has helped me in the last 3 years, I’ll try to share all the technical and non-technical knowledge that I’ve acquired by building apps.
In this post I’m going to talk about how we, at ImaginationOverflow, structure our app folder and project, the idea is to explain why and where we store our code and resources, how we organize them on a Visual Studio Solution and on the common file explorer
How should we organize our assets on the file system? You can follow any project directory layout like Maven, or any other found on the web, or just organize the resources as you need them; at ImaginationOverflow we divide the app development process into three iterative phases: design, development and production. The goal here is whenever you are working on one of those phases you quickly get to the target folder where the related resources are. With this we get to the three root folders of our projects Design, Code (or Source) and Production. We’ve also added another root folder named External, where we store all the third party libraries, in both deliverable or source code form. Although it may sound strange to store some open-source library code, we primarily do it when we change the source to simplify the app integration, or correct bugs, but it can be a safe guard when for some unknown reason the source vanishes. Most recently we started to fork the projects, removing the libraries source from the apps repository, this reduces the amount of code you have to manage on the app repository and makes it easier to share custom changes between apps and pushing bug fixes to the original repository.
The Design folder is where we store all images, vectors, psds (Photoshop Project Files) and other design related stuff; we don’t really have an organization convention for this one, when we use a designer this folder is merely a soft link to the dropbox/onedrive/etc folder. Please note that having all your visual resources stored is really important, from the main app icon (tile) to those little ones scattered though the app. When we design some icon/image we always try to make it much bigger than the actual production size, as an example we make our tiles 4000x4000 pixels, we do this so we only have to scale down our resources which, although it reduces some details it’s better than the alternative of scaling up, scale up makes everything blurry and ugly. We use the same approach for icons and other visual resources, always get the biggest possible or preferably the vector file that “always” scales perfectly.
The Code folder has all the code we produced for an app; it usually contains the Visual Studio solution file(s) (.sln), a folder named Common (or Portable) where all our Portable Class Libraries (PCL) projects are stored and a folder for each supported platform. For example we have one upcoming app that will be available for Windows Phone, Android and iOS, so we have a folder for each platform. This folders store the platform specific projects making everything organized and easy to follow.
We add a lot more stuff to the code folder, as an example, if the app has a website we usually add to the Code folder a separate .sln and a Web folder, if we do unit tests we create a Test folder and so on.
The Production folder is where we store all the app deliverables (xaps, apks, etc), the store descriptions, the images, store kits and other production related resources. Usually it has 4 subfolders:
Deliverables – where we store all public and beta xaps, usually has one subfolder for each public version with the respective deliverable plus a beta subfolder where again we have a subfolder for each version with its file.
Descriptions – containing all the localized app descriptions and keywords.
Screenshots – where we store all localized screenshots, usually contains a subfolder for each supported language.
Misc – random place to store production related stuff, like in app purchases images and descriptions, press kits, ad banners, etc.
When we have more than one platform, we replicate the structure we use on the Code folder, creating a platform specific subfolder under Screenshots and Deliverables.
To wrap up this section here is an example of our folder structure:
root
—- code
——— Common
——— Windows
——— WindowsPhone
——— SomeOtherPlatform
——— MyApp.sln
——— MyApp.Web.sln
—- design
—- external
——— code
——— deliverables
—- production
——— deliverables
————- v1.0.0.0
————- v1.1.0.0
——— descriptions
————- en-en.txt
————- pt-pt.txt
——— screenshots
————- pt-pt
————- en-en
——— misc
————- in app purchases
————- press kits
The windows app ecosystem runs over an architectural pattern named Model View ViewModel (MVVM), to describe it in a few words we could say that the View represents your app user interface, on Windows Apps this means your xaml and some, view related, code behind (e.g. animations). The ViewModel is where your “showable“ data is placed and where your behaviors (e.g. button clicks) are implemented, and finally the Model is everything else that your app needs to do, that is not directly related to what your user is seeing or clicking (e.g. getting data from a service).
On our apps we added a new component that we call “Controller”, they simply are an extra layer to divide some of the ViewModel responsibilities, but we will talk about our components on a future post.
Every app that we have starts with the following platform specific projects:
App.[Platform] – the View from MVVM contains all the user interface and related resources.
App.Configurator – the project where we configure our injector with all platform specific services. (We rely on dependency injection to instantiate almost all our objects)
App.Services – a project for platform specific code (only created when necessary).
And the following PCL projects:
App.Common – where app specific services are declared, usually it contains the interfaces for In App Purchases (iap), navigation service, app specific services, etc.
App.Configurator – where we add configure the injector with portable services.
App.Controllers – where all the controllers are defined and implemented.
App.Controllers.Data – data classes used by the controllers and ViewModels.
App.Localisation – where all the string resources are stored (resx files).
App.Storage – where the app storage services are implemented and defined.
App.ViewModels – where the MVVM ViewModels are implemented.
Our MVVM Model is an undefined collection of other PCL projects, for instance CloudMesh model consists of 13 projects (at this moment), one for the service contracts, another for service data classes and the other 11 are for each of the cloud services we support.
Since each project has a strict set of responsibilities it makes knowing where things are, and where to put them, easy to find and having this division also helps to avoid circular references.
This model also has some disadvantages, the most critical in my opinion is: as the project number grows the build time gets slower, this is a huge issue especially when you are between debug sessions, long build times can make you lose focus and be less productive [FIND LINK FOR THIS].
I will go no further on the Project Structure since my next post will explain how this all comes together.
The golden rule on folder organization is simple, organize it the way you can access what you want in the quickest and easiest way possible, while maintaining some kind of structure. Having a folder like the Production one, which has all the store assets and descriptions organized, is an easy way to reduce errors on publishing and it also boosts the app submission time, especially when your apps support multiple languages. Try to save your app deliverables, although we always beta test our apps (and updates) remember that there can always be a critical bug that goes live to the public, so saving your previous distributables is always a safe guard against this, as it allows you to just downgrade the app. Another good practice is creating a branch/tag (depending on your version control system) for each app update, this way instead of having only the XAP you also have the source..
On project (and folder) organization remember that failing is knowledge, it’s just one more way you know it won’t work, we have spent the last 3 years working on Windows apps and we adapt (add or remove) something on every app. It’s also important to have a solid architecture but even more important to know where it fails, where it could be better and don’t ever be afraid to change or refactor. On the next post we will start to talk about our architecture and how we handle the apps lifecycle.