In Visual Studio, using a c# project, instead of placing a class that contains multiple methods and properties in a single file would there be any downsides to using multiple files with the partial keyword and nested file linking?
For example, if I have a class called Customer that has some properties and two methods: GetOrders and GetAddress. Instead of creating one file called Customer.cs and placing all the code for the properties and two methods in that file I would create a Customer.cs and place only the properties in that file. I would mark the class as partial. I would then create each method in a new file called Customer_GetOrders.cs and Customer_GetAddress.cs, each containing a Customer class marked as partial and only the code for that method. In Visual Studio I would nest the Customer_GetOrders.cs and Customer_GetAddress.cs files under the Customer.cs file.
The upsides I can see are less code in a file to look at so instead of scrolling up and down in a big file you would only see the code dealing with the method you are working on. Also if you are using source control merges would be easier since you would only have to deal with the code in each method. And since methods are bound by physical files you could easily see the change history of a method by looking at the change history of the file.
The downsides I can see are having a lot of small files but I don't think that would be so bad. Are there any other downsides with this line of thought?
Thanks,
Frank
The upsides I can see are less code in a file to look at so instead of scrolling up and down in a big file you would only see the code dealing with the method you are working on. Also if you are using source control merges would be easier since you would only have to deal with the code in each method. And since methods are bound by physical files you could easily see the change history of a method by looking at the change history of the file.
All of these upsides, in my opinion, are only "upsides" if the class is too big. If your class adheres to the Single Responsibility Principle, the file should never be "too big" to manage.
Also, most IDEs (such as Visual Studio) already provide a huge amount of functionality to navigate the files quickly (such as the pulldowns that jump directly to members).
The downsides I can see are having a lot of small files but I don't think that would be so bad. Are there any other downsides with this line of thought?
You're splitting your types up across multiple files, which makes it far less maintainable and more difficult to follow, as the data used by the type is no longer near the methods that use it.
You also add extra maintenance cost to refactoring, as method renames, for example, now would require additional work (file renames) which would break your "history" of that method within that file.
Overall, I'd find this a bad practice. Partial classes are great if you have generated code, and want to be able to add other logic to a generated code file, but otherwise, they tend to be something I'd personally avoid.
It is a Code Smell to me: a class sufficiently large that something is gained in understanding by partitioning into multiple parts is an indication that it has too many responsibilities. It's probably a poorly thought out abstraction that should be partitioned into multiple classes.
For example, if I have a class called Customer that has some properties and two methods: GetOrders and GetAddress. Instead of creating one file called Customer.cs and placing all the code for the properties and two methods in that file I would create a Customer.cs and place only the properties in that file. I would mark the class as partial. I would then create each method in a new file called Customer_GetOrders.cs and Customer_GetAddress.cs, each containing a Customer class marked as partial and only the code for that method. In Visual Studio I would nest the Customer_GetOrders.cs and Customer_GetAddress.cs files under the Customer.cs file.
From a modelling perspective, GetAddress() and GetOrders() shouldn't be methods, at least, not on the Customer object. A Customer probably has 1 or more Address properties and single, collection-like property, Orders, that represents the customer's order history.
I think your abstraction is missing some classes. Perhaps you need an OrderFactory, that given a Customer (and possibly other criteria), knows how to find 1 or more of the customer's orders.
There is actually a big problem with visual studio. The more files that you have the longer it takes to compile and even load a solution. Give it a go sometime with lots of text files, imagine 7 or 8 extra files per class a standard solution would explode in size in no time and .
From a .net compiler perspective there is nothing wrong with this.
The only other problem is maintainability ie code navigation knowing what goes where.
Related
So for example I have this Web Api controller class AdministratorController and it contains a lot of tasks:
Create
Delete
Edit Password
Update
Get
Get all
Etc...
Now I have all these Tasks in 1 file AdministratorController.cs. But with all comments and annotations the file is pretty long.
Is it a good method to split this controller up into partial class pieces to make developers that search for a specific function get quicker to their destination? Or is this abusing the partial keyword
So for example I have a folder structure of:
--Controllers
⠀|-- Administrators
⠀⠀⠀⠀|-----AdministratorCreateController.cs
⠀⠀⠀⠀|-----AdministratorDeleteController.cs
⠀⠀⠀⠀|-----AdministratorEditPasswordController.cs
Obviously, this is a opinionated answer. Technically speaking, yes you can. It will compile.
I think you are right to split this into multiple files if it gets to long.
You could have partial classes. Or you could just have multiple classes. No one forces you to put all those methods into a single controller.
Personally, I'd opt for the multiple classes for practical reasons. You probably do dependency injection and you probably do it via constructor injection, because this is the default. With partial classes, which just means one big class but multiple files, you now need to edit your current file, plus the file that the constructor resides in to add a new service. It also means all the methods will need the DeleteDataService injected, although only the Delete method uses it. If you had one controller per method, you'd have the constructor in the same file and the other classes are not dependent on it.
But if for example you do injection via [FromService] attribute in your method then there is little difference between your two choices.
Structuring them in different files if keeping them in one file is too long is good. So good, that I don't think it would be too bad, even if you picked the "wrong" method to do it. So pick the one that seems most practical to you.
It depends on what you mean by "readable." To the extent that we must read a class, whatever we have to read doesn't become less by being placed in separate files. There's just as much to read either way. It could even be a nuisance looking through parts of a class across separate files looking for a particular member.
Partial classes might make us feel like we're separating code when we're really just making bigger classes. If we think we're making anything simpler with partial classes then they could even make our code harder to understand by encouraging us to add more to a single class while separating it into different files.
I'm not railing against partial classes. This stuff only exists if there is a use for it, and I don't mean to imply that anyone who uses them is abusing them. One example is autogenerated classes, like when we add a service reference (do we still do that?) We might make some modifications to the class, but then they get lost if we update the service reference and redo the auto-generation. If we put our custom code in a partial class then we can generate part while leaving the rest intact.
I often come across the pattern that I have a main class and several smaller helper classes or structs.
I'd like to keep the names of thoses structs as clean as possible. So when I have a class that's called CarFinder that heavily makes use of some special Key object that is only (or mainly) used internally, I'd like to call that object Key instead of CarFinderKey.
Everything to remove all the extra fuzz that distracts me from when I try to understand the class while reading it.
Of course I don't want to pollute the rest of the code with a small helper class that is called Key - it most likely will clash and confuse.
In a perfect world I would have liked to have a keyword like internal to this namespace, but as that does not exist that leaves me the following options that I can think of:
Use internal and put the class in a different project.
Advantage: Perfect encapsulation.
Disadvantage: A lot of organisational overhead and unnecessary complicated dependencies.
Note: I'm not talking about really large self contained systems that undoubtedly deserve their own assembly.
Put it in a different child namespace, like CarFinding.Internal
Advantage: Easy to implement.
Disadvantage: Still can pollute when the namespace is accidently imported.
Put the helper class as a child class within CarFinder.
Advantage Doesn't pollute internally and can even be promoted as a public helper struct that is exposed to the outer world with CarFinder.Key
Disadvantage Have to put the helper class within the same file, or encapsulate it in an external file with public partial class around it. The first one makes a file unneccesary long, the second just feels really ugly.
Anyway call it CarFinderKey
Advantage Easy to implement.
Disadvantage Adds in my opinion too much fuzz to CarFinder. Still unncessary pollutes the naming, just with a name that is not likely to clash.
What is the recommended guideline?
Personally, I don't mind the extra "fuzz" caused by CarFinderKey, and here is why: Once worked on a very large project where we tried to use namespaces to disambiguate names.
So as you expand your system, you can very easily end up with 10 tabs open in your code editor, all named "Key.cs". That was seriously not fun.
It's opinion based. Anyway, I would:
try to make it a private nested class of CarFinder, which usually fails because the Key needs to be passed over to CarManager, you know what I mean. Public nested classes are discouraged.
I would put it into a sub-namespace called Core, a common name for internal stuff. For me, Core is "namespace internal" by naming convention.
The larger the project, the longer names you need. CarFinderKey is still a valid option.
I would never create additional assemblies just for this. It just doesn't feel right.
I had the same dilemma many times, and personally use (3) and a variation of (4).
(3): I have no problem with neither putting the nested class/struct within the same file (if it is small and really tied with the parent class), nor using a separate file within partial ParentClass declaration - the only drawback is that it gets one more level of indentation, but I can live with that. I also have no problem with violating FxCop rules or other recommendations - after all, they are just recommendations, not mandatory. But many people do have problems with all or some of these, so let move on.
(4): You already described the cons. What I'm going to share is how I do overcome them. Again, it's personal and one might or might not like it, but here it is.
First, let say we use a separate file for the key class and name the class CarFinderKey.
Then, inside the code file for the CarFinder class, we put the following line at the end of (or anywhere inside) the using section:
using Key = CarFinderKey;
This way, only inside the CarFinder class code file, anywhere CarFinderKey is needed, we can just refer to it simply as Key, what was the goal. At the same time we keep all the advantages and no clashes. Intellisence works w/o any problem. In VS2015, the lightbulb would even suggest to "simplify the name" for you anywhere it finds CarFinderKey inside that file.
Your decision should depend on your design. Is your Key class really a key only for CarFinders, or could it also be used to find motorcycles or houses or whatever.
One of the first rules the famous Gang of Four stipulated was "Design for change". If you really think that in the very near future your key could also be used to find houses or motorcycle, then it would not be a good idea to make your key class thus private that other could not use it.
Since you are speaking about private helper classes, I assume your key is only useful for CarFinders.
If that is the case and your design dictates that the Key is only useful for CarFinders, or maybe even: if it is designed such that it even isn't useful outside CarFinders the Key class ought to be part of the CarFinders class. Compare this to a simple integer that you would use in the CarFinders class, you would declare it private inside the CarFinders class wouldn't you?
Leaves you with the problem of one big file or a partial definition. From design point of view there is no difference. For the compiler there is also no difference. The only difference is for humans who have to read it. If you think that users of your class seldom have to read the definition of your key class, then it is better to define it in a separate file. However, if you regularly need to read the key class while reading the CarFinder class you should make access to the key class as easy as possible. If your development environment is fairly file oriented instead of class oriented, then I think that in that case the disadvantage of a large file is less than the disadvantage of having to switch between files.
I would put the class and their "helpers" in their own namespace MyNamespace.CarFinding,
so that you have :
MyNamespace.CarFinding.CarFinder
MyNamespace.CarFinding.Key
and I will just put this namespace in a sub-folder of the project.
This will not block the internal helper class to be used elsewhere in the project, but from the parent namespace you could reference your helper as CarFinding.Key
This warning message is popped up when my mouse is over my class name, I can understand that the file name should be named exactly as the class name (or vice-versa) (which is defined in the cs file). That will be OK and of course good to follow but what if I intend to define more 1 class in a cs file? Or I shouldn't do like that?
I don't like any warning message, it seems to mean that I'm doing thing abnormally and in a non-standard way.
As comments point out it is not comment put by C# compiler (or Visual Studio).
There is no restrictions in C# on number of classes per file or if class/namespace should match file/folder name (unlike Java or ActionScript).
It is considered good practice to have one class per file (not counting nested classes) and somewhat match folder names to namespaces. This makes code easier to search and easier to find files corresponding to particular classes.
As for length of classes again there is no technical restriction, but long classes generally mean too many responsibilities in one class and as result not recommended. Generally there is no reason not to have many small classes in individual files.
You need to come up with style that works for you/people you work with and try to stay with it. Most code analysis/style checking tools (like ReSharper) are very flexible in style checking, so you often can adjust rules to your liking.
The first class in the file should be named same as the filename. If you need other classes that are only used by this class you can put them below this top level class and you will not get any warnings.
I have a large number of classes which all use the same interface. This is the first time this code will have unit tests so I'm trying to think of the best way to generate all of these tests, or the structure of the classes at least.
I know T4 Templates are used in EF to generate multiple files based on the model. Is there a way I can specify in the T4 Template that I want it to look at all of the classes which implement an interface and generate a unit test class for each. Alternatively, if it's easier, all of the classes are within the same folder so if I could just point it at that folder it would probably be fine.
Once that is done I can fill in the details of each unit test class with the specfics. I'd obviously have to remove the T4 file so it doesn't overwrite the code I've added to the classes, maybe there is a way to do that too?
Take a look a this blog post:
http://t4-editor.tangible-engineering.com/blog/how-to-generate-multiple-output-files-from-a-single-t4-template.html
It should enable you to generate multiple outputs with a single .tt file. I use it in (almost) the same way you do, I generate a huge class of methods (3000 lines) based on an xml file and then I generate another file containing unit tests for those methods. Ironically, the unit tests pointed out several bugs in my big generated class, even though the unit tests were generated also.
A T4 template always generates only one piece of output, be it one output file for the design time template or one string for the runtime template. The template itself will therefore not be able to generate you multiple files. Nonetheless, with a little code, you can use a single runtime template multiple times, to create multiple pieces of output as you like.
I suggest to create a simple utility, separate from the main project, which will contain the T4 runtime template and the code which will, for example, inspect a given assembly or bunch of given source files and generate the appropriate test skeleton using the T4 runtime template and save it to a file for each of the classes of interest. I guess it depends on the number of classes in question, if it is worth it to spend a little time to create such a tool.
If it's not clear enough, just let me know and I will try to provide an example.
I'm doing something similar in a new project, where I want to use a T4 template to generate some code that pertains to all the classes that inherit from a particular class. (Basically write a factory generator class to create a new instance of each derived class given only a string containing the class name, and also to collect a list of the public properties in each class without using reflection at runtime. That way, other developers can just add the new class to the project without worrying about tying it into our framework.)
I'm also keeping the source classes in a common subfolder.
While I'm only starting to design how the template works, the template will run before the code is compiled, so my process will be to:
For each source code file in the subfolder:
Load the file into memory.
Use regular expressions to verify the class in the file inherits from the desired base class.
Use regular expressions to extract the data I need.
Write the output class using the data I've gathered (class names, public property names)
This is something where Roslyn may be useful in analyzing the code in order to extract class and property names, but I'm not going to get too fancy just yet. My approach will limit us to one class per file, and will only work with the one language we're writing in, but that's convention over configuration that we can live with.
You may find this MSDN article useful, as well as Oleg Sych's blog and toolkit. Oleg's T4 Toolbox includes a template for generating multiple output files from a single T4 template.
Is it good practise to have multiple class definitions in one file? or is it preferable to have one class per file?
I prefer one class per file. You'll never have to search for the correct filename because it is always the class name.
One class per file.
That way you can avoid having to merge edits when two people have to edit the same file because one is working on class A and the other is working on class B. While this should be automatic in any source control system, it's an extra step that can be missed which would cause problems.
Far better to have a process that didn't allow this sort of error to occur in the first place.
I do not see any issue with multiple classes in the same file, as long as the classes are related to each other.
If you have resharper, you can always use the navigation tools to find any class.
It is generally best practice to have one file per class.
Some folk, not me, like to have more than more one if they are related and very very small in size. Others might do this in a prototyping stage. I say start and stay with one per file as does Scott McConnell in his discourse on Class Quality in his seminal book Code Complete
To quote, "Put one class in one file. A file isn't just a bucket that holds some code. If your language allows it, a file should hold a collection of routines that supports one and only one purpose. A file reinforces the idea that a collection of routines are in the same class."
I think it's preferable to have one class per file and to organize them in folders having the same hierarchy as their namespaces.
Most programmers would consider one class per file to be a best practice.
Usually - no.
Following practice "one class per file" simplifies browsing of solution.
Additionally if you have a big team of developers and source control tool that uses pessimistic approach (exclusive locks) - your developers will have hard time while working on the same file.
I guess it is down to preference as you said.
I think you'll find most online examples/ most code is one class per file for easy management.
I sometimes put 2 classes in a file - only if i'm using the second class as an entity and it's only being used in the first class.
I guess you ask because you've noticed already that it's considered best practice. Given the obvious benefits (and some less obvious ones mentioned here), why would you want to do it differently? Are there any benefits at all in multiple classes per file? I can't think of any.
Usually it is the best solution to have one class per file (with the file named exactly like the contained class).
I only differ from that if
There are lots of small enumerations ->I collect these into a single file e.g. Enums.cs
There are lots (20+) of generated classes/interfaces that directly relate to each other ->Into one file E.g. Interfaces.cs
There is stuff that is no direct functional part of the application and in close semantic consistance (e.g. everything you need for interop. Thats usually a few structures, enums, constants and a single class) -> That goes into a single file named after the interop class.
Private inner classes -> Stay with their parent class instead of partial classes
I would say no, i know devexpress hates it aswell ( It has some detection bad practives).
But i do have it sometimes, when its a very small class thats basicly only used by the "main" class in the file. Personaly i think it comes down a bit to taste, there is a balance between having 10k lines long .cs files or having to many .cs in your project.
I think in terms of it being a "best practise" approach then probably yes. However, really it depends on the project. I tend to group related code into separate units for example:
MyApplication.Interfaces
MyApplication.Utils
MyApplication.Controllers
I really think a class only ever deserves it's own unit if it becomes huge. However, if it does get to this stage, you should start to consider moving some code into helper classes to separate the logic.
I would have to agree with most on this. One class per file is ideal. It makes it easier to see what's available in a project without having to rely on intellisense to discover types that are available in a given assembly.
I think the only time I ever fudge on the one class per file rule is when I'm defining a custom EventArgs class and it's related to an event that's fired from another class. Then typically I would define those in along with a delegate for the event in the same file. I don't know that it's a good practice one way or another or just out of sheer lazyness??
If you work on a very large project, too many files can slow down your build times significantly (at least with C++). I don't think that rigid adherence to a rule is necessarily the way to go.
One Class Per File is my Preferred approach, it helps me get rid of any confusion later on... I tend to use a lot of partial classes though...
As long as I dont break the 1000 line barrier, I'll stuff in as many related classes that makes sense.
Sometimes an abstraction may only be one overridden method.