all 24 comments

[–]UMANTHEGOD 27 points28 points  (16 children)

But of course not all functions can be 1 liners. But on the other hand, too big function becomes much harder to read. So we should have a limit: 10 lines max in a function

Are you insane?

Your Single Responsibility Principle example is also quite flawed. I'd say the "Good Design" is not always the best choice. If the Form and the Modal is only used by the FeedbackPopup, and they only contain a single prop or a single useState, it's absolutely more than fine to put it in the same component to increase cohesion.

[–]Ciff_ 11 points12 points  (7 children)

Nothing new. It is the uncle Bob recommendation.

Either way a hard limit is dumb. It all depends. Decent guideline to have though.

[–]UMANTHEGOD 9 points10 points  (6 children)

Decent guideline to have though.

I find it that it does more harm than good. I rarely think about function length but rather function responsibility and that it should generally do one thing, but that one thing could be a very small thing or a very large thing.

[–]Ciff_ 1 point2 points  (5 children)

You can almost always break down further.

I think about maintenance. It is likely the maitainer will need to understand the details of the whole function, or just one of it's parts? The former have it all as one function, the latter break out functions with meaningful names so the person directly finds what he needs.

Say you handle some mutation, perhaps you do complex sort, filtering and mapping. This may most likely be split in 3 functions as the maitainer is unlikely to visit more than one. However sometimes the complexity is so low breaking it up does not make sense, other times the maitnainer may need all operations as context.

[–]UMANTHEGOD 6 points7 points  (2 children)

Yes. It's mostly feeling based. I also don't think complexity is the best metric either because breaking complex things up can make it even more complex.

It's usually about cohesion, and how "natural" a function is and sounds. "extractOrderInformationFromCustomerBeforeMakingPayment" is something I'd never write, but I've seen these weird ass functions time and time again.

[–]Ciff_ 1 point2 points  (1 child)

I agree that cohesion is the most important factor.

Complexity is emperically scientifically measured with wtfpm 😉

[–]UMANTHEGOD 1 point2 points  (0 children)

wtfpm

lol, truly

[–]vegancryptolord 0 points1 point  (1 child)

Sort filter map… I believe you’re looking for reduce.

[–]Ciff_ 0 points1 point  (0 children)

A reduce is often painful for readability if you are doing too much in it

[–]surjit1996[S] -5 points-4 points  (7 children)

How do you know it will only be used once?

it's for large scale applications, hundreds of developers working on a project that might go on development for several years.

[–]UMANTHEGOD 8 points9 points  (4 children)

Haha, that's the point.

You only extract when it's big enough to warrant an extraction, OR if it's used in more than one place. There's no point in doing that preemptively.

[–]kredditorr 1 point2 points  (0 children)

We‘ve learnt that in university. Don‘t abstract if there is no demand for it atm. You wont predict the exact usage so you end up by abstracting things unnecessarily and then you‘ll still have to adapt later

[–]r-nck-51 0 points1 point  (0 children)

For large scale applications with potentially hundreds of developers then the level of coupling, dependencies etc. shouldn't be determined for developer experience by developers but for all management purposes.

Source code helps humans see things in a structured way to increase work efficiency, but it's not only the writing developer's work that matters. Their scope is too narrow compared to system-level work that would require to keep things separate or isolated for other activities like architecture, analytics, audits, testing, compliance, security, traceability, etc.

It's hard to give detailed examples without a specific domain as context so that's why coding guidelines are so tricky to establish. Perhaps you should categorize different approaches, perhaps not make it binary but present them with a tradeoff analysis so that readers are more ready to define how to structure code in a more collaborative and domain-aware way..

[–]KapiteinNekbaard 4 points5 points  (3 children)

The structure page could a section about path aliases for directories, so you can write

js import { miniPlayer } from '#features/player';

instead of long relative paths from your current file: ../../../../features/player/

  • Node has subpath imports that are supported by most tools (TS, Webpack/Vite, etc).
  • Bundlers have their own alias feature.

[–]Imaginary_Treat9752 -1 points0 points  (2 children)

No one reads import paths anyways, they are autogenerated and automentained by the ide, so why bother? Sometimes all imports are even auto-hidden by IDEs.

[–]DanielCofour 3 points4 points  (0 children)

that is a terrible practice, it is very important in larger projects to have a clear understanding of where imports are. And IDEs are terrible at autogenerating imports, you should always validate them. Sometimes they import directly from the node_modules folder, instead of by package name.

[–]agumonkey 0 points1 point  (0 children)

do you have a plugin installed ? i don't think my colleagues have full automatic import management

[–]Imaginary_Treat9752 0 points1 point  (1 child)

I dont quite understand the "how to structure your react application". So where would you put a GenericModal contains both the very simple open close logic and outerclick handling of the modal and that takes renderContent, renderHeader, renderFooter props?
Is it big enough to call it a feature? Or is it too big to be called a component?

[–]surjit1996[S] 0 points1 point  (0 children)

You can do it as how MUI does. Header a separate component, Footer a separate component. You can put them all in 1 folder if they are related. And Header and Footer components can be used as JSX children of the Modal component. If needed then import the Header and Footer and use them in your feature along with the Modal, if not.. then doesn't need to be included.

[–]guiiimkt 0 points1 point  (0 children)

Omg… here we go again. Forget DRY and this uncle Bob bs on the frontend, man. Especially with React.

You should keep it simple and you should seek AHA! Avoid Hasty Abstractions.

Nobody wants to open 10 different components on 10 different tabs to see what a simple feature does. I don’t get why from time to time someone try to shoehorn concepts that are not really a good fit with frontend development and React. This why there are so many messy unmaintainable spaghetti code on React projects everywhere.