What’s in this file anyways?

Maria Neumayer
A problem like Maria
4 min readSep 13, 2017

Java has strict rules when it comes to files:

  • A file can contain one public, top level class
  • The file and class name need to match
  • The package must match the filepath it’s in

In Kotlin these rule don’t apply. The package can be different to the folder structure, you can keep multiple classes in one file, or give the class a completely different name. In fact a file doesn’t need to contain a class at all!

In my last post I talked about data classes. As they’re so simple you end up with many classes of a single line. It almost seems a waste of a file for this.

What can be combined?

One option is to combine models from the same feature into one file. As the package and folder structure don’t have to match you could even avoid creating a folder with a single file in it and keep it in the parent folder.

Above you can see an example — there’s a Music file which contains three classes: Artist, Album and Song. The classes are all top level classes and are in fact in a separate package: music. However there is no music folder inside model. There’s a warning on the package: this is because the file structure does not match. This shows that you should be careful with this.

Having the file in a different package can be confusing — I recommend following some rules if you do so:

  • The file name and the additional package should match
  • The same rule should apply to all files in a package — don’t mix and match
  • Don’t put the file in a completely different folder — you should expect where to find it

Having related models in one file has the advantage of seeing an overview of how the data looks like. Did you ever have to click through various models to see what they all contain and how they relate to each other? Seeing them all in one place simplifies that a lot. It is especially useful when defining models or refactoring.

However models are just one use case for this. One place where I particularly like using this is when defining your Model, View and Presenter. It made me stop to think what a screen needs to do and define everything in one go before implementing anything. Of course this is possible with separate files too, but it’s much easier to see the whole flow, or something you missed, if everything is in one place.

What are the drawbacks?

One danger is to go overboard — just as you don’t want to have a huge class you don’t want to have a huge file. If your app becomes more complex and you have to add lots more classes you might have to move the classes into separate or different files.

Simply looking at the list of files can give you a good overview of your project. If a file contains multiple classes per file this is no longer possible. Luckily the IDE highlights files with multiple classes differently to the ones with only one, so you will be able to differentiate them. You will have to open the file, though to see the classes inside.

Another drawback is version control behaviour. If you have a single class per file it’s very clear when a class was added, removed, moved or modified. If you keep multiple classes per file this is no longer obvious. Say you add a class to an existing file — the commit summary will only show that the file was modified. You have to look at the actual diff to see what happened. You can also run into conflicts if multiple people add or remove classes in the same file.

If you’re used to opening files using cmd+shift+o (ctrl+shift+n on windows) the file you’re looking for will not show up — only classes will be matched this way. You can however still open them via cmd+o (or ctrl+n) or double shift.

So should I add multiple classes per file?

It absolutely depends on your preferences and use cases. Discuss with your team and find what works for you. Personally I have found having multiple classes per file is really useful to see the bigger picture. Many people prefer having separate files per class because of the drawbacks mentioned above and to have a clear structure. So far I haven’t been bitten by any of the drawbacks, but time will tell.

If you do decide to make use of it I recommend setting up some guidelines on when to combine classes in a file. This way you will always know where to put a new class, or where to find an existing one. This is especially important when the package name and the folder structure don’t match.

Personally I like it, but I’m careful not to go overboard and haven’t dared not matching the file structure yet.

--

--

Maria Neumayer
A problem like Maria

European living in London. Principal Engineer at @SkyscannerEng. Tweeting at @marianeum.