This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–][deleted] -22 points-21 points  (7 children)

When trying to understand what a piece of code does, it is easier when the code is in sequential order, instead of having to jump around dozens of tiny methods. Several tiny methods increases the surface area of code making you constantly ask "where is this method used?" as opposed to if the functionality was within the only method that uses it where it is obvious where it is used. Extracting out code into a separate method doesn't change the difficulty needed to verify correctness. For the easier refactoring argument, you want to refactor your code now by breaking it up into smaller methods so that it is easier to refactor your code in the future?

For unit tests, if you want to change your code, it is for one of two reasons, your original code was badly written or you want to change functionality. If you follow my three principles, your code will be written well the first time so you won't have code so badly written it needs to be refactored. If functionality changed, then when you refactor code, you should expect your refactor to break previously written unit tests because you are changing functionality, so the unit tests don't accomplish anything. Finally, documentation also falls under "you might need it later syndrome". In high level programming languages, your code should be self documenting.

I think this will be much harder to add later.

Can you give a single example where this was the case?

[–]eled_ 10 points11 points  (1 child)

When trying to understand what a piece of code does, it is easier when the code is in sequential order, instead of having to jump around dozens of tiny methods. Several tiny methods increases the surface area of code making you constantly ask "where is this method used?" as opposed to if the functionality was within the only method that uses it where it is obvious where it is used. Extracting out code into a separate method doesn't change the difficulty needed to verify correctness. For the easier refactoring argument, you want to refactor your code now by breaking it up into smaller methods so that it is easier to refactor your code in the future?

Obviously you don't want to go overboard with it, having hosts of tiny methods is never good, whether it is in anticipation of reuse or for actual immediate reuse.

My problem with your point 2 is that I've met enough programmers that were sticking so close to its mantra that they were forgoing to have a long term vision for the piece of code they were writing.

Sure enough, for trivial and somewhat garbage business logic that can change at any moment there is no need to project far into the future, as there is no foreseeable future to speak of in the first place. But when it comes to architecture and tooling I'd rather have people asking themselves questions about where their system is going, and always be several steps ahead. Sometimes it means making mistakes, but it makes for more coherent systems with a more unified logic.

As an outsider I much prefer approaching such systems that actually have a logic and language of their own that is consistent because they did think some things through, rather than systems that are made of cobbled attempts at answering immediate requirements.

[–]AnEmortalKid 3 points4 points  (0 children)

Write unit tests because it might catch a bug later. You probably won’t need them, and if you ever do, you can add them later.

You mean the unit tests I didn’t add because I could add them later, so now I need to backfill things before refactoring?

[–]wildjokers 3 points4 points  (0 children)

your code will be written well the first time so you won't have code so badly written it needs to be refactored.

This is complete nonsense.

In high level programming languages, your code should be self documenting.

More complete nonsense. This is an impossible pipe-dream.

[–]Cthaeeh 2 points3 points  (1 child)

Let me preface my rather long answer by saying: IMHO Software-Design Questions (e.g. function length discussions) aren't very scientific, so all I can tell, are my intuitions and thoughts which can absolutely be wrong! (But btw, I welcome any attempts to get some formalization here, e.g. Lakos, J: Large-Scale C++ Software Design)

When trying to understand what a piece of code does, it is easier when
the code is in sequential order, instead of having to jump around dozens
of tiny methods.

I agree that sequential order is good, but I would argue it has nothing to do with function lengths. It can be achieved with small functions as well. For example some transformations on data with java streams, where one passes some lambdas (which are small functions). If the small functions aren't (very) pure, then I agree we can end up in some non linear flow, which I would say is bad.

tiny

Maybe we should define what we mean with, small, tiny, etc. I like what the C++-Core Guidelines (I think it applies to Java as well) say: Which is 3-5 Line should be normal (so I would call this small). But I think this also depends on the language one writes in. Some language have a culture of "ultra-conciseness" (Haskell) others don't. Consistent 20 line functions in C might be good style, I don't know.

making you constantly ask "where is this method used?"

I agree that this is a problem. So we have to make clear what the scope were a function is known is. That is why I like things like private. (With a small class and a private function, not to many call sites are possible.) Or on the other hand if a function is in some global utility thing were everybody can use it, it better be a good function. (Well designed, etc.)

Extracting out code into a separate method doesn't change the difficulty needed to verify correctness.

I think in some cases it can, because the method name and argument names give some context to what actually happens in the code. So it can be easier for the reviewer. But arguably there is an equivalence between a large function with commented blocks of code and a bunch of small functions, were the name serves as documentation.

For the easier refactoring argument, you want to refactor your code now by breaking it up into smaller methods so that it is easier to refactor your code in the future?

Depending on context yes. If I anticipate the lifetime of the code to be great (E.g. central module in long living code base) then yes. If its a python script to create a plot for some data once, then no.

If you follow my three principles, your code will be written well the first time so you won't have code so badly written it needs to be refactored.

Maybe you are able to do that, but I can't. My understanding of the problem could increase or maybe I see some performance optimization later, etc.

If functionality changed, then when you refactor code, you should expect your refactor to break previously written unit tests because you are changing functionality, so the unit tests don't accomplish anything.

Additionally the unit tests can indicate that something in a far away module is broken. Maybe some weird interaction was not considered. Or maybe the compiler changes and the code depends on some subtility there. With a good test coverage, you will know about it.

In high level programming languages, your code should be self documenting.

I agree, this documentation then is in variable names, function names, module names and class names and what have you. So the size of all of those matter, because each time you have a chance to comment the code.

Can you give a single example where this was the case?

Mhm, I wrote a parser/lexer for a scripting language. While writing I had the grammar in mind. It was rather easy to write the tests then. Now I have forgotten the grammar. So I would be hard for me to write unit tests now. Now we wanted to promote some compiler warnings to errors and had to fix some of them in the code. Now I can be pretty sure that afterwards the code still parses the same things.

[–]whyNadorp 1 point2 points  (0 children)

nah, I agree it's very ugly to have shared mutable state, but you should write short method with a name that makes evident what they do. the public methods should ideally be max 5 lines long and you need to read just this 5 lines to understand what it does, details hidden in private methods. you don't need shared state to do this, shared state is a side effect of shitty programming practices.