13 ms·
Should you split that file?
- jeffbee 3y agoSome of this may be potentially true for TypeScript programmers. I have no idea, since I never used it. However, sensible division of code into small files can have enormous benefits in C++. Throwing everything into giant files makes it annoying to write and run unit tests, or to reuse part of the code in a new translation unit. There is a noticeable difference between working in a code base where the tests link and run in milliseconds, compared to ones where it takes a long time to compile and link them.
- tadfisher 3y agoOne of the best improvements in Kotlin (over Java) is the ability to have multiple top-level classes, functions, and static variables in one file. I hate jumping between 10 files when reviewing code. You technically can do this in plain Java, but it comes with many caveats and probably won't work with a default build setup. And no, nested classes are not the same thing.
- beeboobaa 3y ago> And no, nested classes are not the same thing. They actually are if they're public static. Quite literally so, nested static classes are the exact same as "normal" classes but named `OuterName$InnerName.class`
- occz 3y agoIt might be for the compiler, but the nesting implies hierarchy for the reader, which may or may not be desirable.
- beeboobaa 3y agoSame goes for putting them in the same file.
- dtech 3y agoThey are not the same at all. One practical reason is that in Kotlin (and other languages supporting this) you can always move the class to a dedicated file if it or the file becomes to unwieldy. With a nested class all the imports would need to change, which is a no go unless you can refactor all code using it in 1 go.
- beeboobaa 3y agoThis only matters if you are building a library intended to be consumed by other projects, and you are intending to release before deciding on a public API, and for some reason put multiple classes in a single file. Pretty specific case of a bad practice. Otherwise, just use your IDE's refactor capabilities.
- deleted 3y ago[deleted]
- nightpool 3y agoThe overall advice here (add comments to your code to delineate different 'sections" of a file) is ultimately a bad hack to deal with the fact that your codebase is not structured well into function / modules / classes with a single responsibility and the right level of composition. Refactor your codebase to put the related code together, and then this "problem" will disappear and your code will be much easier to change in the future
- leghifla 3y ago"Refactor your codebase to put the related code together" Of course it is a goal, but not always possible. You sometimes have two (or more) conflicting "relations" in the codebase. E.g.: you are dealing with taxes in various countries. Do you group by country or by kind of taxes (on sales, profits, earnings, energy, real estate...) ? The right answer really depends on how your team is organized and how you are making changes.
- froggit 3y ago> E.g.: you are dealing with taxes in various countries. Do you group by country or by kind of taxes (on sales, profits, earnings, energy, real estate...) ? Seems like you would be dealing with one of 2 reasonably well defined problems in this case. How to group would follow logically. It's either: 1) "If i will be dealing with one specific type of tax at a time and how it is applied in different countries. (i.e. What are the sales taxes in UK, France, and Germany? )" Group by tax. OR 2) "If i will be looking at one country at a time and their assorted taxes. (i.e. What are the taxes in the UK for income, sales and value added?)" Group by country. Else "i have failed to properly define the problem." that's gonna be the problem.
- Bjartr 3y agoHow about when supporting both use cases? A multinational company might need the former for people making decisions across the whole company, and a country specific department doesn't need anything but what's relevant to that country. You could make two tools, but now you're duplicating implementation. Factor out a shared library/service/modularization-approach-de-jour? Good idea, but we're back to the question of how to structure things. You don't always get to enforce that "OR"
- dvt 3y agoThis is a much larger discussion, and it's not as easy as adding headings, subheadings, etc. to your comments. There has been a clear cultural shift against writing comments and properly documenting code. This is probably due to several factors, including unreasonable deadlines, bad architecture, job security, or meaningless output factors (e.g. lines of code). This is why open-source code tends to be some of the best architected and documented code out there: it's pretty much the definition of "by committee" (in the best sense of that term) and meant to be inviting to anyone to contribute. So of course you want it to look nice. At BigCo, these factors don't really come into play (even though it would probably be better for the company if they did). There's also a lot of differences between writing software and building robots. Systems engineers build and refine requirements documents, pages upon pages of "this tiny part should be built like this, should have these constraints, etc." with traceability, discussion, and clear deliverables. Software, on the other hand, is unfortunately mostly just "patch a few things together and get the login form working."
- berlinquin 3y agoHave been using a version of this recently: with C++ in Visual Studio you can add `#pragma region X` that will let you expand/collapse regions of code in the same file. Can be useful for top-level organization.
- smusamashah 3y agoC# natively supports `#region <name>` and `#endregion`. IntelliJ supports the same using comments like `//#region <name>`.
- cglong 3y agoTypeScript IDEs also typically support this via `// #region <name>` and `// #endregion`.
- earthboundkid 3y agoAre y’all reading files top to bottom? This is weird to me. I pretty much just follow execution using jump to definition, and I rarely read something top to bottom in a way that having sections would be helpful.
- darth_avocado 3y agoHaha, me too! I was concerned for a second. Though, I do organize my files bottom to top with the innermost part of the execution at the top.
- MuffinFlavored 3y agomaybe it’s a C thing where (without header definitions) you have to put main at bottom and anything it needs above it (same for functions that reference other functions/structs that aren’t main) to make the compiler happy?
- gipp 3y agoI honestly wish more people would try to organize their files to be read top-to-bottom, it makes it much faster to grok something new. But of course there are lots of other factors constraining the way a file can/should be ordered, depending on language
- cellularmitosis 3y agoYes, the "inverted pyramid" concept from journalism. Most important details up top, implementation details down below. In our (Swift) codebase, this typically translates into "publicly-consumable interface up top, private and internal functions down below".
- okwubodu 3y agoWithin individual files I tend to create a mental index of names and purposes from top to bottom before tracing, which usually helps avoid redundant jumping or branching so deep it becomes difficult to keep track.
- deleted 3y ago[deleted]
- mrkeen 3y agoWhere-clauses help break up long modules. somefunc = ... where subfunc1 = ... subfunc2 = ... otherfunc = ... where subfunc1 = ... where subfuncA = ... subfunc2 = ... Then the reader can instantly tell top-level concerns from implementation details, and the amount of jumping-around is reduced since those subfunctions are limited in scope.
- chrismorgan 3y agoI’ve been playing around with using extra indentation for these sorts of purposes in the last couple of years, mostly at the sub-function level but also in the larger file situation described in the article. I’ve found it to work so well that it has even been significantly influencing the design of the lightweight markup language I’ve been using for my own purposes for the last year or two and further designing as I go. The minor rough point is that text editors probably don’t support mixing line folding techniques, so you probably won’t be able to fold sections and functions, which it would sometimes be nice to be able to do. Maybe at some point I’ll get round to making a hybrid fold expression for Vim to mix multiple fold methods, though honestly I find Vim’s folding pretty janky (my Rust foldexpr works fine when you load code, but start editing it and the fold tree rapidly falls apart in painful ways and it’s absolutely Vim’s fault) and would probably prefer to shift the entire thing to FFI for more flexibility. Some languages/IDE ecosystems support other ways of doing this sectioning, like Visual Studio’s “regions”, which gets around the folding problem since it’s all in the language rather than being a mixture of language syntax and independently-chosen convention.
- marcrosoft 3y agoIn typed languages like go I don’t need to look at module imports linked to files for navigating. With the vim shortcut ‘gd’ I can immediately jump to the definition making this entire discussion about where to put things almost irrelevant. I would still try to organize for reading.
- inChargeOfIT 3y agoI find if you subscribe to the "Write libraries not software" mantra where your libraries/packages/classes are focused and adhere to the single responsibility principal, code organization kinda sorts itself out. But I agree with the author that organizing and commenting long files like this makes it easier to grok what's going on. But if you are clicking around a project and scrolling with your mouse, instead of taking advantage of your IDE's ability to use keystrokes to find and open files, jump to references/definitions, find and replace text, etc., you are handicapping yourself. It's worth the investment to learn.
- tikhonj 3y agoI try to organize most of my code as libraries too, but I still find having sections and subsections super useful. I sort of took that for granted because most of my code was in Haskell, and the Haskell documentation tool supports sections/subsections/etc natively, so I just used those to organize my larger modules.
- inChargeOfIT 3y agoI totally agree. And some long/complex files are simply unavoidable (shell/build scripts, config files, etc).
- nucleardog 3y ago> But if you are clicking around a project and scrolling with your mouse, instead of taking advantage of your IDE's ability to use keystrokes to find and open files, jump to references/definitions, find and replace text, etc., you are handicapping yourself. It's worth the investment to learn. Really? I've observed the opposite. The developers that I work with that make heavy use of things like fuzzy file matching, go to definition, etc tend to have a _much_ harder time understanding the codebase. My theory as to why this is the case is that they're never building or taking advantage of any higher level context. Having to browser through the directory structure (assuming it roughly mirrors the code structure), having to look through classes, etc forces you to actually build some awareness of the greater context of that method you're looking at. Using "go to definition", you may find yourself in a method, then later you hit "go to definition" and find yourself in another method, and unless you've made a conscious effort to observe so, you may very likely have never noticed they're even in the same class and presumably related. Using "go to definition" you might end up in a "process" method. Knowing that's in the "Image" class in the "ImageResizer" module would probably add a lot of clarity to what that's doing before you even get started looking at code. When I need to onboard in a new codebase, I very much _don't_ use those tools until I have a solid grasp on the big picture.
- polyrand 3y agoI kind of agree with the post. For me, this technique almost starts overlapping with literate programming[0]. One trick I use[1] is adding certain characters before the section name. e.g: ¡¡ settings This makes searching and jumping between sections a lot easier. [0]: https://en.wikipedia.org/wiki/Literate_programming https://en.wikipedia.org/wiki/Literate_programming [1]: https://ricardoanderegg.com/posts/write-apps-in-single-file/ https://ricardoanderegg.com/posts/write-apps-in-single-file/
- tikhonj 3y agoThe Emacs version of this is using ^L (the ASCII form feed character), which lets you jump around using Emacs's built in page navigation commands. I've used this occasionally in Emacs Lisp code and it's pretty nice, but I've never done it in other languages because I suspect that non-Emacs-users won't be able to handle it :P The Emacs Wiki has a whole page on this: https://www.emacswiki.org/emacs/PageBreaks https://www.emacswiki.org/emacs/PageBreaks
- emmanueloga_ 3y agoThings humans are bad at: organizing files, topological sorting, ontologies. Things computers are good at: organizing files, topological sorting, ontologies. The point is I wish we could just ask the computer to sort things out for us, show different views, etc. this would require a software system able to work with more granular code units, maybe something like [1]. I still have some ptsd from huge refactoring where a big part of the hassle was to manually create directories, move files around, fix imports, build files, cyclic dependency errors, sigh… I suspect a good solution would be to have a language agnostic dsl to describe a program’s data flow, then use it to generate the boilerplate of functions involved. Then you could ask the system to show you only the pieces of the code strictly related to a certain feature, hopefully never again have to deal with file structure manually. 1: https://www.unison-lang.org/ https://www.unison-lang.org/
- MetaWhirledPeas 3y ago> The point is I wish we could just ask the computer to sort things out for us, show different views, etc. I agree. I'm usually opinionated about a related subject: code formatting. But I'm not too opinionated in one case, where we're using Prettier. The project is autoformatted and expects everyone else to do the same. It's so refreshing to let the computer take over sometimes, even if the end result isn't exactly what I would have typed out myself. If a piece of software could so something similar with the folders, files, and code that would be pretty great. Maybe. It seems like a much harder problem to solve than simple formatting, without introducing a bunch of bugs. But you seem to be suggesting a different way of viewing the code, which I guess might be the way. But still underneath you'd have the spaghetti code, just sitting there not being dealt with, like a complicated Microsoft Word document.
- deleted 3y ago[deleted]
- norman784 3y agoI was about to comment also that unison is an interesting approach, we need more tooling support before it can be possible, ideally there need to be a protocol that the new kind of editors can be built on top, similar to how LSP enabled editors to support different programming languages without a proprietary implementation. I'm wondering if the unison devs already have plans on working on a protocol like that.
- hoten 3y agoHere's a good rule to use, only applies in the extreme. When your cpp file is so large that you begin losing debug info in upstream tools like Sentry, you should probably split it. Related, when your functions are so large that they fail to compile under higher debug modes for emscripten (too many locals!), you should probably split it. (send help)
- wruza 3y agoWas doing that for ages. I have snippets com and com2 for first and second level full-width headers. Third level is just a comment surrounded by empty or “//“ lines. “;” cycles through headers. Never understood that “more import lines than lines of code” style too.
- amadeuspagel 3y agoMaybe plaintext is not the perfect way to organize code.
- jameshart 3y agoUnderappreciated aspects of the C# compilation model: 1: file agnostic. While files provide a scope for imports, in general the compiler can’t tell the difference between the same set of classes split across multiple files or crammed into the same file. 2: unordered - files don’t import one another, or get processed in particular sequence. The compiler takes a set of files and turns that into a set of type definitions. 2: partial types, which lets you even split a class definition between multiple files 3: regions, to let you bracket of sections within a file and organize things how you want. No ‘one class per file’ rules. No ‘references at the top of the file to every other file you need’. You can reorganize code freely, adding or combining files at will.
- bbkane 3y agoI think, by using a directory as "the module unit", Go gets similar benefits while being simpler.
- pipe01 3y agoIf only cyclical references were possible
- aragonite 3y agoThat sounds like something I really wish were available for JS development. Used to have a setup where, during development, I write all my .js files as "script files" rather than modules, all placed inside a folder, and the "build-step" is simply concatenating all .js files in that folder. All the functions in each script file are globally visible from all the other script files and there's no need to import/export anything. No one should publish code in that form, but during development it was incredibly freeing and helps me concentrate on the actual programming tasks at hand rather than getting sidetracked by trying to figure out the right way to organize the code into modules, something that (imo) I'm in a much better position to do when the programming tasks have largely been solved. It's like writing a book. The natural process is to first create substantive content in fragments and then gradually for a chapter or section structure to naturally emerge from these fragmentary bits of content. Focusing too much on 'modules' during early development is imo akin to being preoccupied with spending time deciding what chapters and sections you want your book to have before even having a substantial base of content. Unfortunately the current tooling for JS doesn't really support this workflow as well as I'd like.
- kraftman 3y agoThis is kind of related, but I've always wondered what a 2D or 3D IDE would look like, if we could drop the limitations of files and working top to bottom, and instead be able to group code more spatially (and i guess still have it then outpt to files for storage.) Does anything like this that isnt a GUI drag and drop editor?
- bbkane 3y agohttps://www.unison-lang.org/ https://www.unison-lang.org/ stores code in SQLite (last I checked) and looks super interesting. In a related idea, I wonder what organizing code imports by one or more "tags" instead of import paths would be like. Probably too confusing after a while (tag systems tend to get that way), but fun to daydream about
- marwis 3y agoJetBrains got you covered: https://www.jetbrains.com/mps/ https://www.jetbrains.com/mps/
- swizzler 3y agoThere is code bubbles. Early demo: https://www.youtube.com/watch?v=PsPX0nElJ0k https://www.youtube.com/watch?v=PsPX0nElJ0k current site (eclipse plugin for java projects?): https://cs.brown.edu/~spr/codebubbles/index.html https://cs.brown.edu/~spr/codebubbles/index.html. Maybe also inspired Visual Studio debugger exploration. I haven't used it (but have wanted to)
- kraftman 3y agoThis is exactly what I meant, thanks!
- SnooSux 3y agoI like tools like vim and tmux for being able to quickly and easily split windows and show multiple terminals. If I could extend things out further than just my monitor that would be really cool. Or stack windows on top of each other so I could scroll through windows in a specific spot.
- 3y ago
- vemv 3y agoIn practice, the chances that N programmers with follow the pretty comment convention of a given file approach zero, as time passes. Splitting into files is an approach that is easier to lint against (e.g. max 500 lines - a best-effort mechanism to foster SRP). And it's not really problematic after mastering a few key aspects: jump to definition, and more interestingly Peek Definition. It's also important to not traverse files top-to-bottom (which yes, is very tempting). Optimal code traversal is tree-like, you jump from definition to definition, skipping over the irrelevant, and gathering necessary info on demand. The file/line location of a function becomes irrelevant.
- solarkraft 3y ago> It's also important to not traverse files top-to-bottom (which yes, is very tempting). Optimal code traversal is tree-like, you jump from definition to definition, skipping over the irrelevant, and gathering necessary info on demand. A (successful!) ex-colleague of mine read thousands of lines long files top to bottom. I don't know how, but somehow this worked for them.
- vemv 3y agoYeah I mean, it can be done, it can be helpful but is it efficient? You could as well try memorizing the entire $framework API, which most people would agree that isn't the best use of one's energies.
- ilrwbwrkhv 3y agoThe rails world is filled with stuff like this: class Something def execute first_method end private def first_method second_method + 1 end def second_method 2 end end This should have been just one method instead of thousands of tiny one line methods. I blame Uncle Bob and that whole group for brainwashing the Ruby community.
- eternityforest 3y agoWhy do we not have rich text code yet? Headings could be large. We could embed diagrams with graphvis or mermaid. We could hyperlink and have tables of contents or even embedded runnable forms like a Jupyter notebook. Comment anchors and similar are close though. https://marketplace.visualstudio.com/items?itemName=ExodiusStudios.comment-anchors https://marketplace.visualstudio.com/items?itemName=ExodiusS...