static members vs module for type in F#?

Your example is pretty simple, and so either approach here is probably fine. But imagine adding a dozen more functions that take a Season parameter. Now the type definition will look extremely cluttered. Plus, these functions may need to make use of some shared values and functions that can be declared as private inside the Season module.


Ultimately that's a domain modelling judgement call and there's no one definite correct answer here. What matters is how each choice affects readability and maintainability of the code.

I tend to favor static members for functionality that is highly "cohesive" with the type, more so than any particular piece of business logic code. Think Parse functions or smart constructors/factory methods. The general approach being that if I were to refactor the code by moving the type somewhere else, those would be the functions I'd definitely want to move together with it. Having them as static members also helps discoverability through intellisense, as you only need to know the name of the type to find them.

On the other hand, I'd use a module to house business logic that represents some abstract process, and if the function in question is somehow specific to that business logic and unlikely to be useful outside of it, then I'd go with a function in a module even if it's still somewhat type specific. For instance, a very purpose-specific parser that's only useful as part of this one workflow for legacy reasons would be a let-bound function rather than a static member, because other clients that use that type generally shouldn't even know about that function.

In your case, I'd go with the static member Next if it makes sense for it to be used in multiple different modules in your context - if being able to cycle through Seasons is a fundamental quality that defines what a Season is.

Otherwise if you just have a single module, let's say WeatherPatterns, that adjusts rainfall based on season changes, and that's the only part of your code where you care about cycling through Seasons, then I'd put it as a function in that module.

Tags:

F#