In F#, you specify the order of files explicitly. Any code can only reference types, modules and functions that are higher up in the same file or in a file higher up in the file list. When starting with F#, this feels strange because most programming languages don’t rely on ordered files. Some call this feature even dumb.
The disadvantages are rather clear: you have to specify the order explicitly – which is additional work, isn’t it? Sometimes, getting the order right can be tricky because of the many dependencies – functions calling functions and using types – in our code.
Big ball of mud
In my many years of working with C++ and C#, managing dependencies between types (classes) was always challenging. It was easy for cyclic dependencies to sneak in. Cyclic dependencies between types and namespaces. The problem with these cycles is that they make refactoring and changing code unnecessarily hard. You want to change a little piece of your code with a quick change, but you can’t because a lot of code is inside the cycle of dependencies. You got a big ball of mud.
To keep the dependencies in check and therefore have a system that remains easy to change, extend and refactor, we introduced tools. Tools showing dependencies, especially cyclic dependencies. Structure101 is for example such a tool.
Strict ordering is great!
In F#, we don’t need such tools anymore. The compiler doesn’t allow cycles – it won’t compile*. So when the codebase grows, strict ordering helps to keep the code and its design simple. Even when reading code, you can always be sure that all code the current line depends on is above, and the functions with the biggest scope are at the end. This helps – at least me – reading and reviewing code. It’s not as much jumping around as in, for example, C#, where the dependency can be anywhere.**
* F# allows recursive type and function definitions through the
and keyword. But only locally.
** Of course one can use the navigation features of the IDE. But very often, it’s simpler just to scroll up a bit.
While manually ordering files is a bit tedious, overall it reduces the effort needed to implement and maintain the codebase, especially in bigger codebases. So after a while, strict ordering is one of the best features of F# for the software architect in me.