13 Comments
Apr 21, 2023Liked by Kent Beck

To make things more complicated, I know from experience that some developers (typically those trained in math) tend to to structure things like a proof, with "atoms" first, building up to larger entities.

Expand full comment

While reading this, I realized I unknowingly followed a mixed pattern, where I would use cohesion and sorting both.

Like, first group the variables by related meaning, then sort these groups alphabetically.

Much like

```

filters,

setFilters,

result,

setResult,

title,

setTitle,

```

Expand full comment

At least I have seen many .Net projects where developers with near OCD have taken great care to define collapsible regions for constructors, properties, public methods and private methods. While it looks nice and tidy, I see it as a big anti-pattern to arrange methods by protection. In terms of readability it can almost be worse than random order, because you are guaranteed that the sub elements are placed very far from the invocation, and the ideal reading order

Expand full comment
author

I'd love to have one of those re-ordered as an example.

Expand full comment

Does this depend on language? I ask because I’m JS, for example, “consumed” methods precede “consumer” methods (because IIRC methods are evaluated top-down when the file is loaded) as opposed to Ruby, for example, that will typically have the inverse.

Expand full comment

This is true for lisps, but in JavaScript it is just convention (with exception if you declare functions as let/const bindings).

Expand full comment

One of good examples IMO is hls.js library - https://github.com/video-dev/hls.js/blob/master/src/hls.ts

Notice how they grouped together methods of Hls class by their logical context:

on()

once()

removeAllListeners()

off()

attachMedia()

detachMedia()

startLoad()

stopLoad()

Class itself is pretty big (>800LOC) and it can be hard to find what you need without that cohesive grouping.

Expand full comment

I like (within the file) "calls should always go down" and "...should be as close as reasonable."

So the "main" or "entry point" function is always at the top and widely reused functions are near the bottom end.

Expand full comment
founding

One of example last I know is

validate1()

validate2()

use1()

use2()

Was transformed into

validate1()

use1()

validate2()

use()

In some rare case the first one might be useful if the use1 is really slow and we have command line tool which takes hours to execute. Sometimes, it is sad to look into the results in an hour and realize there was a mistake in a command line argument.

Are you looking for real-world example with some domain information?

Expand full comment
author

The ideal example is 1) real open source code and 2) requires domain knowledge all readers share. 2) is impossible but worth optimizing for. Bonus points for an actual diff.

Expand full comment

I can think of two similar examples that come immediately to mind. For classes, generically, it's a good idea to keep the public methods at the top of the file, as they'll be the "entrypoints" into that logic. Same with react components, it's usually a good idea to put the "main" component at the top of the file, front and center. It's definitely a choice of style, and doesn't have any behavioral impact (most of the time?) but can help the next person to read that module. Is that in the spirit of this advice?

Expand full comment
author

Yes. You're reading some code. You get towards the end of the file. Aha! You think, "Well why didn't they say that up front?"

The tidying is to reorder the elements in the order you wish you could have read them. That's what I'd like examples of.

Expand full comment

Exposing the public API is a valid reason to do that, but depending on programming language, I would rather use an interface for this purpose. It also makes your code easier to test.

Expand full comment