tags:

views:

1807

answers:

26

I follow this rule but some of my colleagues disagree with it and argue that if a class is smaller it can be left in the same file with other class(es).

Another argument I hear all the time is "Even Microsoft doesn't do this, so why should we?"

What's the general consensus on this? Are there cases where this should be avoided?

+34  A: 

I sometimes group more than one class within a file if they are tightly coupled and at least one of them is very small.

General 'best practice' is to have one file per class.

henchman
If you recognize that they're coupled, why aren't you decoupling them?
The Matt
@The Matt: It's called avoiding overengineering. If you have a few tightly coupled classes and decoupling them would add a lot of complexity compared to the amount of practical flexibility it provides, then what's the point?
dsimcha
Sometimes I have like basically "data" classes that are used only by this one class, so I usually put the data-class in the same file as the user because the datac-lass usually has little to no logic itself and it seems like a waste to create a new file for it.
Earlz
@The Matt: Sometimes there are helper classes that I would argue as coupling-acceptable. They reduce the complexity for part of another class but still facilitate a very specific purpose to that class.
j0rd4n
@jordan, earlz: i spoked about exactly these types of classes :-) sometimes it just doesn't make sense to decouple classes.
henchman
I do this at times myself... although I generally now create child classes under the main class to encapsulate this relationship. For instance, a List type object which contain SubNodes.
Nick
@TheMatt: Decouple this: http://msdn.microsoft.com/en-us/library/system.diagnostics.debuggervisualizerattribute.aspx Coupling between modules is bad, but collaboration between classes within a logical feature is unavoidable.
Ben Voigt
@dsimcha The point is that by decoupling you should be reducing the complexity. The 'complexity' you're referring to must be navigating physical files on disk because all we're talking about is the physical location of the class. So its unclear to me why separating two classes from the same physical file in anticipation of reuse is going to add complexity. Sounds more like laziness. By that reasoning, if more files is more complex and that's what you want to avoid, you should just shove all your code into a single file.
The Matt
I generally always keep strongly typed collection classes in the same file as the class the collection is composed of, especially if there's little extended logic to the collection class.
Chris
+1  A: 

I do this, but only when the classes are related in a child-parent fashion and the child classes are ONLY used by the parent.

CResults
Thanks, but why don't you separate it into another file? Just curious.
Joan Venge
@henchman has said it a lot more eloquently than I have, especially when the child object is very small. It is usally the case that the child class is properties only with maybe only a little logic
CResults
+4  A: 

In larger solutions I think it is very valuable to have one class per file and that the file is named the same thing as the class. It makes it much easier to locate the code you need to work in.

Chris Clark
I find this argument less valuable with tools like ReSharper. I Do CTRL+T and start typing the name of the type I'm looking for.
Mark
Yes, but do you want your application structure to be dependent on a third party tool?
magnus
@magnus: if the tool is ReSharper, it's cool.
John Saunders
@magnus I wasn't saying this isn't a reason not to do it, but a less compelling of an argument for someone to do it.
Mark
+54  A: 

One class per file also gives you a better idea of what each check in is changing without looking at the diffs of the file.

Mark
Great idea.....
Joan Venge
excellent reason
MedicineMan
More classes in the same file enhances the diff between related classes in only one operation.
Luca
Proper diff viewers let you view all diffs of one commit.
Dykam
I'm not entirely sure how this particular answer is THE answer to the question(s) of the original post. Sure it provides A reason to keep 1 class to a file (though Luca and Dykam make good points), but it doesn't reflect general consensus or provide cases when it should be avoided.
Robert Davis
+2  A: 

One case could be: when your classes jointly form a module / unit that serves some main classes like helper classes, other wise no.

have a look at ASP.NET MVC 2.0 project source code. It strictly follows this rule

Asad Butt
Thanks, that's by MS, right?
Joan Venge
+1  A: 

I only do this rarely. For example if there is an enumeration or struct that is closely related to the class yet too trivial to be separated on its own.

or a separate class to contain some extension methods for that main class.

puffpio
+4  A: 

The StyleCop tool for C# has standard rules that require no more than one top-level class in one namespace (plus any number of interfaces, delegates and enums in that namespace).

In cases of two or more classes where the second and subsequent classes are only ever used by the first, those could and should be inner classes, visible only to the consuming class.

Steve Gilham
When you say "no more than one top-level class in one namespace", you mean in one `namespace` block, right?
Daniel Pryden
The rules alluded to are SA1403: A C# document may only contain a single namespace.SA1402: A C# document may only contain a single class at the root level unless all of the classes are partial and are of the same type.
Steve Gilham
+5  A: 

In the vast majority of cases, I follow the one class per file rule. The only exception I regularly make is the definition of an enum that is tightly coupled to a specific class. In that one case, I will frequently include the enum's definition in that class' file.

Greg D
+35  A: 

I hate it when people think in absolutes and say you should never do this or that with something subjective and nit-picky like this, as if we all need to conform to someones stupid idea of right and wrong. Bottom line having more than one class per file is totally fine if it makes sense. By makes sense I mean things like:

  1. Makes the code easier to digest and maintain
  2. Makes the solution less annoying (scrolling through countless unnecessary files) and less slow
  3. The dev team is okay with it as a local coding practice

[Edit]

A really good example of why I may want multiple classes per file:

Say i've got a few dozen custom exception classes each one is a 4 liner, I could have a separate file for each one or I could group the exceptions and have a file per group. For me what seems the most rational/pragmatic approach is to group them, and just have a few files, because it's more efficient time/coding wise (I don't have to right click add class , rename, 50 times), it keeps the solution less cluttered and better performing.

James
+1,000. Understanding the rationale for best practices and thinking twice before violating them is great. Slavish adherence is evil.
dsimcha
+ 1! or in short: USE YOUR BRAIN(S), PEOPLE!
henchman
Sometimes just "making sense" or being okay with something doesn't allow for additional benefits gained by making the shift. At other times it does.
John K
Thats true, emphasizing the "other times it does". For this specific topic there are good reasons for doing one or the other on either side of the equation. In other words there is not a right or wrong answer here, and the dev writing the code ultimately needs to make the decision and not feel bad for his/her choice.
James
*A few dozen custom exception classes*? Isn't that the real source of the problem? I don't just mean to be nit-picky here: I think most of the time people want to combine classes into a single file, it's because they're needlessly creating too many types. (Having said that, perhaps there is an actual case where a few dozen custom exception classes make sense). Numerous small, no-op classes are normally a sign of a bigger problem.
Jeff Sternal
I agree with you for the most part. But exceptions are a special case. Because a properly architected system needs to have proper exception handling to deal with all the cases that yield legitimate errors, most of the best practice articles i've read emphasize the need to create specific exceptions (and some times you need a lot of them to cover the all the business rules on a large project) so that you don't end up catching system.exception which isn't proper exception handling at all.
James
I agree that you should not slavishly follow some guideline without a good reason, however I disagree with the fact that you should have more than one class in a file. For me the file should be named after the class and not contain more than one. Some languages (java being one) make a note of actually enforcing that the class is in a file with the file name matching the class name. For me it makes it easier for newcommers to navigate so for that reason I believe that the one class per file is the right thing to do
krystan honour
+1  A: 

The responses so far seem to revolve around people's exceptions to the rule, so here's mine: I keep classes and their metadata 'buddy' classes together when using the DataAnnotations package in .NET3.5sp1. Otherwise, they're always in seperate files. You know, most of the time. Except when they aren't.

Brant Bobby
+1  A: 

Sometime one class per file, but...

When multiple classes are stricly related, more than one classes in the same source file are, IMHO, BETTER than dedicating a short source file for each class. The source is more readable and compact (and using #region the same source can be be more structured than before).

Consider also that sometimes it's NECESSARY putting the same class in different files (using partial), since having a 20000+ source file is not handy even with the RAM I have available (but this is another question).

Luca
+2  A: 

Is that really a problem?:)
Really small classes, just like enums, can be put together with others. There's one rule to follow: put together only classes that have something in common.

As a digression - in one of my projects I have a file that has 150 classes inside. The file has 10000 lines of code. But it's auto generated so it's fully acceptable :)

StupidDeveloper
I have a same file with 120 classes and 750 subclasses with half a million lines, it is also autogenerated.the problem is:if i click on it, i must reboot because everything stops.
Behrooz
+2  A: 

On occasion I will leave a small class in with a larger class but only if they are very tightly related like an object and it's collection class or factory.

There is one problem with this though. Eventually the small class grows to the point at which it should be in its own file, if you move it to the new file you lose easy access to your revision history.

ie.

  • on monday I make a change to my classes x and y in file y.css
  • on tuesday I seperate class x in to its own file x.css because it has grow to large
  • on wednesday my boss wants to see what I changed in class x on monday so he looks at the history for x.css, only x.css doesn't show the history before tuesdays changes.
runrunraygun
+19  A: 
static bool GeneralRuleShouldBeFollowed(IGeneralRule rule, IUseCase useCase)
{
    return (rule.Overhead(useCase) 
            < My.PersonalThresholds.ConformismVsPracticality)
}
Jeremy Bell
Is there a rule like that in .NET? I also I would have just returned the statement result. :O
Joan Venge
+1 for style :-)
henchman
Hah, you got me Joan! Edited.
Jeremy Bell
no need for brackets I think you'll find :)
krystan honour
+1  A: 

One reason for putting multiple related classes in one file is so that the poor bastard who uses your API doesn't have to spend half a day typing import declaration boilerplate and the poor bastard who has to maintain the code doesn't have to spend half a day scrolling through import declaration boilerplate. My rule of thumb is that multiple classes belong in the same file if you would almost always use a large subset of them at the same time instead of just one at a time.

dsimcha
What do you mean by "import declaration boilerplate"? "Using statements"? But aren't the classes gonna be in the same namespace?
Joan Venge
@Joan: I mean having to import 15 different but related modules to accomplish something really simple. Maybe it doesn't apply specifically to C#. I don't really know C#, but in other languages it's a pretty annoying problem.
dsimcha
Thanks yeah that's why I was confused.
Joan Venge
+4  A: 

Really, this boils down to personal preference. Everybody will say "one class per file", but we all have our reasons for avoiding that in certain circumstances. I used to have a large project that had about 300 different enums. No way am I going to have 300 seperate files, one for each class, when some of the enums only were tri-state.

Also for people that can't find certain classes if they aren't all in files named after what they are, is there a reason you don't use Find looking in the entire solution? using find saves me valuable time scrolling through solution explorer.

Jason M
Re: find - when I'm looking for a type's definition, I don't want to see where it's used. Besides, find takes significantly longer than scrolling through an alphabetically sorted list of files I've probably already divided up (by namespace).
Jeff Sternal
I notice you've indicated you're working with something you've divided up by namespace. We're not all lucky enough to always work with projects we've been able to manage, unfortunately.
Jason M
+2  A: 

I like the idea of creating smaller classes and making sure that the class is doing only what it is suppose to do. If you have multiple classes which are contributing to solve a single problem then there is no harm to put them together in the same file.

I would not follow MS practices as they are not the BEST PRACTICES!

azamsharp
+1  A: 

I usually stick with one class per file. But I will make exceptions for groups of similar constructs that are used project-wide. For example:

  • An EventArgs.cs that contains any EventArgs subclasses, since they're usually only 5-10 lines of code each, but they typically are used by several different classes. Alternatively, I might put the EventArgs classes in the same file as the class that declares the events.
  • A Delegates.cs that contains Delegates that are used throughout the project, since they're usually only 1 line each. Again, the alternative is to put them in the same file with the class that exposes/consumes them.
  • An Enums.cs that contains enums used throughout the project. (If there's an enum that's used only by one class, I'll usually make it private to that class.)
Daniel Pryden
+6  A: 

Beyond hypothetical arguments and focusing instead on Windows .NET with Visual Studio IDE and growing software projects, it just makes sense in this context to have one class per file.


In general, for visual reference nothing beats one class per file. Really.

I don't know if Microsoft does or doesn't do the same, however they did create the partial keyword to split one class over multiple files (this is even more severe). It's often used to split the auto-generated designer code from your custom code in the same class (but sometimes is used to allow different developers to work on the class at the same time via different files). So Microsoft does see benefits of multiple files and everybody has multiple file organization thoughts in mind for sure with .NET.

For nested classes you have no choice but to use one file, or at least the first parts of the classes in them. One file is necessary and fine in this case:

class BicycleWheel {
    class WheelSpoke {
    }
}

Otherwise why would you keep multiple classes in one file? The argument "because they're small" or associated with each other doesn't hold much water because eventually your classes will be associated with other classes. Ultimately you can't easily infer in-file organization of objects based on their usage especially as software continues to grow.

Additionally if you use folders for namespaces then you'll never have a class filename clash. It's also convenient to locate a class by filename on the file system when not inside a development environment like Visual Studio (e.g. if you want to quickly edit a class with Notepad or something quick/light).

So many good reasons ....

John K
Thanks, what do you mean by "at least the first parts of them"? You mean you can also separate nested classes?
Joan Venge
That's a indirect reference to the `partial` keyword I mentioned.
John K
Thanks, your answer is really good.
Joan Venge
For the record nested classes can be `partial` http://msdn.microsoft.com/en-us/library/wa80x488(VS.80).aspx I looked this up out of curiosity.
John K
jdk, thanks for taking the time to post the link.
Joan Venge
This only goes to show that the default view should be logical (namespace/class) and not physical (files).
David Schmitt
+2  A: 

I find that grouping a class with it's standard factory class in the same file is very useful.

Robert Davis
+1  A: 

No matter how lightweight the content, I think one class / interface / etc per file is essential.

If I'm working on a big solution in Visual Studio I want to be able to see the files and not have to delve inside to see. Even with navigation tools like ReSharper, I want a 1:1 mapping.

If you find a lot of source files with little or no content in (maybe extending a class but adding nothing to it) then perhaps you should rethink your design.

Michael
+2  A: 

Another vote for one class per file with the file being named the same as the class. For me, it helps with long term maintainability. I can easily look through the repository and see what classes are part of a solution without having to open the project or any of the files.

Tim
+4  A: 

I would normally have one class per file but you would normally have to use your discretion to see if the file could contain related classes e.g. grouping your exceptions which can be re-used by yourself and other developers. In this case, the user only need one file to be included rather than multiple files.

So the point is: discretion should be used!!!

Akapetronics
True wisdom, no rule in programming is hard and fast.
ChaosPandion
+1  A: 

I follow it 99% of the time. It's good to follow standards, but I also believe flexibility has its place. Sometimes it just seems like a silly waste of time to break things apart. In those times, I get over myself and just write my code.

Mike Pateras
A: 

One code item per file, yes.

Everything else is a malpractice - and, quite frankly, a sign of RAD victimness.

As soon as one starts proper software development (IoC, design patterns, DDD, TDD, etc...) and leaves the "omg lets get this done, I have no idea how, but I get paid" playground, one will see that this rule really, really, matters.

Turing Complete
+1  A: 

I, too, believe there should be one type included in a single file.

There is one exception to this rule that must be mentioned : Having two classes that differ only by a generic argument such as :

RelayCommand     

and

RelayCommand<T>
Andrei Rinea