Hacker News new | comments | show | ask | jobs | submit login

What do you think of partial classes and methods in term of code quality?



I've always thought of "partial classes" as a language feature motivated by code generators not stomping on programmers' manually entered code. E.g. Winforms generates some declarations in one partial class while the programmer codes UI handlers in the other partial class.


When I first learned C#, I was having a hard time to navigate the code due to partial methods. So I have always wondered what C# developers think of having their methods spread out in different files.


Partial classes and partial methods exist specifically to support having code that is automatically generated paired with a human-managed source file.

While you could use the support for them to split human-managed code across separate source files, that would be a horrible practice that I've never encountered in the wild, even in .NET shops with otherwise-atrocious practices and code quality.


>While you could use the support for them to split human-managed code across separate source files, that would be a horrible practice

To continue that type of advice, some say "#region/#endregion" is another language feature that's intended for code generators so that the IDE can collapse specific lines of code and hide it from view. Programmers should not be hand-coding "#region" themselves. That said, there is debate on that: https://softwareengineering.stackexchange.com/questions/5308...


#region / #endregion, IME, largely serves to mitigate the visual offensiveness of poor (usually, completely neglected) design and (despite the potential utility in the case of code generation, and the utility it might have in the rare case where there is a good reason for a monster source file) I'd prefer it not to exist.


We use regions to standardize the layouts of our classes. Except for trivial classes, you will find the same regions in the same positions making it eas(ier) to find, for example, all methods implementing an interface, or all of the private helper methods.


Regions are just useless visual clutter most of the time. You can put the methods/fields in the same order without using the regions. In my experience regions are a very bad practice used only to mask bad design that produced gigantic classes. The only place where I think they may be helpful is when you are writing a library and your class must be huge because you are implementing for example a Trie or some other collection or some other object pretty complicated that doesn't make sense to divide in smaller classes. And even in that case I would first try really really hard to split it in smaller entities rather than just having a thousands lines class with some regions around.


Not sure where to go from there. You've precluded the possibility that regions and good design should exist at the same time in the same file.

Where does the absolutism in the tech industry come from? We are a bunch of individuals who have individual experience and then try to form a view of the world that satisfies our experiences. What about the experiences you haven't had or conceived of? We are constantly rewriting the rules in our head to fit the new experiences we have every day to make sure we are right all of the time. Surely, our current world views are not complete or we would have no room to grow.

Still, I'll take your comment under advisement in case my classes are big, poorly designed non-Tries.


Since it's buried at the bottom of the stackexchange: #region/endregion is useful for visually grouping Unit Tests per method under test. They're also occasionally useful to group interface implementations.


You could just use nested classes for that, with the added benefit that the test framework will reflect that organization in its UX.


The suggestion is appreciated. Thank you.

I have a minor doubt that I won't like the additional level of nesting incurred, but I'll attempt it regardless.


Partial classes are also useful in the case that you want a nested class to have its own file.


I think I may have manually created partial classes for huge classes to make them more manageable. Think for example expression tree visitors or collections of extension methods. Sure, I could just have created several classes like FooExtensions and BarExtension, but having a partial class Extensions seems ever so slightly better to me. But I generally agree, there are not many good use cases besides code generation and if you are tempted to do it, then you probably have a problem that has a different and better solution.


I think just about every time I've seen it it's either been exactly what the OP described or an attempt at refactoring a class whose scope had grown far too large.


It's a tool to use.

Like others have said, it makes working with generated code easier.


That's where every Visual Studio dev will see them used, because it's been a VS pattern since the beginning. But I create them manually often enough. Overall I use them sparingly, but there are cases where you definitely want a set of things in one class for code-organization, but still want to think of them as different modules for human-organization.


I did that once where I had a complicated class with a docile public API that controlled a not so docile long running threaded 'machine' of sorts. Having them in two files made thinking about stuff easier.


If you want to think of them as different modules then most likely they should be completely separated entities. Why on earth you would want something completely different to live in the same class? It is just screaming that it wants to be a separate class. Namespaces are the correct tool for code organisations, certainly not partial classes.


It's very interesting that you were able to see my use cases and come to this conclusion...


Regardless of the use case this is what the official documentation says about namespaces:

The namespace keyword is used to declare a scope that contains a set of related objects. You can use a namespace to organize code elements and to create globally unique types.

And about partial classes:

There are several situations when splitting a class definition is desirable: When working on large projects, spreading a class over separate files enables multiple programmers to work on it at the same time. When working with automatically generated source, code can be added to the class without having to recreate the source file. Visual Studio uses this approach when it creates Windows Forms, Web service wrapper code, and so on. You can create code that uses these classes without having to modify the file created by Visual Studio.

As you can see partial classes are not the right tool to organise code.


How would you propose to split a struct that has a single data member? Say, a struct where the only data is one unsigned short?

Also, "regardless of the use case" ? I barely know how to respond to that. Have a little imagination.


Thank you. It has just occurred to me I can use this feature at work!

lol


Not the OP but here are my 2 cents: partial classes should only be used when you have a mix of generated and hand written code. Any other usage should be forbidden. It requires some education but it is useful for this usecase.


If, like me, you're old enough to have used MFC (where the code generators generated source for classes that you had to augment, and randomly picked lines to replace or overwrite in those classes whenever it felt doing so (1), you think they are a godsend.

(1) that's an exaggeration; MFC used comments to identify sections that it owned in the source, but in my (limited) experience, there typically were zillions of ways to make changes to your code, but if you didn't use the one Microsoft picked as _the_ way (and which they didn't push into your face in the IDE), you were in for heaps of problems.




Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | DMCA | Apply to YC | Contact

Search: