Should there be hard limits on program part sizes?

NOTE HXA7241 2010-11-24T19:27Z

There is cause to, based on complexity, but a better solution seems to be to adopt a different structuring – one with different scaling behaviour

We accept strict rules about goto: various languages constrain it or disclude it entirely. Should we be as strict with the sizes of functions, modules, and even programs? – not merely have best-practice guidelines but enforce limits with language rules? No-one likes a monster function. So should it be syntactically impossible, for example, to write a function of more than 30 lines? or have a class with more than 10 fields?

Software is about bringing some structure, or formalisation, to human logical activity, and sprawling functions, and other parts, look negligent.

Limiting the complexity of local state

Structured programming is informative here: the gist of it is to make complexity proportional to program length (Dijkstra: EWD249 page25 para5). This deserves further pondering, but it immediately gives a perspective on what size-limiting would be doing.

The purpose of strict size limits would be to make complexity nearer constant within each structure/part.

These are two different kinds of complexity, but the intent is the same: to make them more understandable. Structured programming is addressing control-flow complexity and its mapping to program structure, size-limiting is addressing local state complexity.

Over-large functions (in their data and operations), modules (in their parts), and programs (in their modules) share the same problem: excess state and excess interconnection of it. The problem is not size per se, it is the uncontrolled internal structure. Each additional part adds not merely itself, but more complexity to the whole. A long function has many variables and arbitrary (that is, unpredictable to the reader) relationships of them and their operations. Similarly with a large module and its members, or a large program and its modules and classes.

Size limits keep this reasonably bounded. They do not replace all arbitrariness with standard forms – they cannot: there must be some room for arbitrariness of structure, otherwise programs could not be different. But it ought to be limited to something reasonably easy to understand.

Avoiding complexity by using other structurings

Functional languages rather avoid the function length problem: operations are not in simple sequences, but more in trees. You cannot add length without adding depth, and also immutability reduces interrelations, and those together isolate subsequent branches.

Functional languages still have some arbitrarily extendable parts: case/switch, pattern matching, function parameters. But they are different to imperative kinds of extension: because the complexity is only in the basic ‘list’-form of the structure – you can understand it just by recognising it is a ‘list’: each element doesn't add any more internal relationship complexity. The complexity is constant for the structure.

Within classes/modules, and between them in whole programs, functional languages seem not so restrained. These higher-level parts are might able to refer to each other, and so enable arbitrary complexity. Following the viewpoint so far, it would seem preferable instead to keep to the same basic functional form of aggregation: lists (and hence trees) of independent non-interrelating items.

Do these various kinds of lists still warrant size limits? Perhaps, but the need is much smaller – excess length might add inconvenience in viewing, but not really complexity.

Conclusion

So, roughly, the answer is yes, but preferably indirectly. We can avoid the problems of long procedures (and other things) – unbounded non-constant complexity – by using alternative structurings, like functional languages.