> what matters is the formal structure of the code
Yes, and splitting code into well named files is a starting point for giving it proper structure.
The same goes for the size of your functions. Here some (like "ProcessEvent") consist of nearly 500 lines... that's roughly 10 screens. Textbook spaghetti code.
Overly long code files are difficult to maintain and introduce various practical problems, eg. greater likelihood of merge conflicts. That's why they're considered a red flag in software engineering. Professional literature on software development elaborates more on the subject if you don't want to take my word for it
This is one of those "software engineering best practices" that sounds nice but has no basis in reality. What matters is the formal structure of your program: types, composition, state, capabilities. Where your code is located on the filesystem is incidental complexity.
> This is one of those "software engineering best practices" that sounds nice but has no basis in reality
Are you a programmer? What languages?
> Where your code is located on the filesystem is incidental complexity.
Incidental complexity is still complexity to deal with.
It isn't easy for me as a developer to find such and such routine if you've thrown everything into a big bucket named "main".
You also omitted the fact that I didn't only refer to files. I mentioned the size of functions, too. Now functions ARE logical units of code, and if you need to scroll ten screens and names are as vague as "ProcessEvent" (which is not broken down into subroutines), this doesn't speak very well about the overall design.
Thanks for the links - but it's hard not to notice that they both refer to FP languages, however (Erlang and Scala).
I wouldn't step out to judge the quality of an Erlang codebase, because that's not a paradigm I'm well familiar with.
Go, however, doesn't belong to that family. I see no reason why SRP and other oldschool principles wouldn't apply here. I'd be happy if someone told me (that's why I asked at the beginning - "or is that the language"?).
The other commenter (@mod) implied that since the project is experimental, it's done quick and dirty but that's because it's prototyping.
Note that I've never said the author of the project is a sloppy programmer, I only wondered at the code being so messy.
Considering a major goal of the project / approach is precisely to deprecate the the hierarchical and file-based approach to programming, it doesn't really surprise me to find all the code in a single file.
Perhaps the better storage layer would be function definitions living in a database. That Conception uses an unindexed flat file as the 'code database' also isn't surprising given the stage of development.
I get paid to program c, c++, java, python, and r (not necessarily in that order, with other languages as needed) and there's nothing inherently wrong with a 500 line method if that's what the problem calls for.
It's grounds for getting the stink-eye in code review, but to reject it out of hand is pure ideology.
"there's nothing inherently wrong with a 500 line method if that's what the problem calls for"
Yeah, "if", but that's rarely the case :) Care to show me an open-source example of a function 500 lines long where you don't think one could find proper seams to split the code along? Ideally in https://github.com/shurcooL/Conception-go/blob/master/main.g...
I'll bite. We were just talking about spaghetti code in the context of the Toyota ETCS. In that case, static analysis was used to measure the cyclomatic complexity of the code and even then some comments claimed that wasn't enough to immediately qualify as 'spaghetti code'. https://news.ycombinator.com/item?id=8905718
Spaghetti code refers to the complexity of tracing cause/effect through a set of routines increasing to the point where you can no longer safely add functionality or fix bugs without too high a risk of regressions. It has to do with the difficulty of understanding the purpose, intent, actions, and side-effects of each function.
As is often the case, splitting a function too much simply based on a LOC guideline can result in spaghetti code just as easily as it may guard against it. Functions should be atomic, re-usable, repeatable, clearly defined, and well encapsulated.
I don't see lines of code as a direct factor in judging a function implementation, as long as those lines are spent moving the feature forward and not violating "DRY".
> Functions should be atomic, re-usable, repeatable, clearly defined, and well encapsulated.
And when they're very long, it's a warning flag indicating that they may NOT be atomic, re-usable, repeatable, clearly defined nor well encapsulated.
Also bear in mind that code is not carved in stone, but subject to constant change in every project that isn't deprecated, let alone in one under active development. This is why we judge its design not only by what qualities have been achieved up to this point - but also by whether the design serves to prevent them from deteriorating.
A long function that's reusable at the moment is at much greater risk of becoming unreusable than a concise one.
Readability is of great importance, too, since code is meant to be read by humans.
Poor readability and messiness is acknowledged as an issue at the moment, since it is (to quote https://github.com/shurcooL/Conception-go/issues/3) "hurting readability of the project for other people". What else is poor code readability if not (to quote your words now) "difficulty of understanding the purpose, intent, actions, and side-effects"??
> I don't see lines of code as a direct factor in judging a function implementation, as long as those lines are spent moving the feature forward and not violating "DRY".
Well, in this case we have to agree to disagree I guess :)
The thing about spaghetti code is it's like spaghetti: if you try to follow one strand (of execution or pasta) you get mixed up with all other strands.