0

I'm working on some MonoTouch code that I derived from one of the samples (this is not a MonoTouch specific question) and the sample code declares a private class inside another class. I've not seen private classes used much in c# and I'm at a loss as to when it might make sense. I can see how a class that is only referenced within another class could be declared private but isn't this going to cause more grief than it's worth? Doesn't this break a number of the SOLID principles?

  • Single Responsibility - broken?
  • Open/Closed - broken?
  • Liskoff Substitution - maybe ok?
  • Interface Segregation - broken?
  • Dependency Inversion - broken?

Right now I'm finding it confusing just trying to navigate the source because of the private class definition. I guess this could be mitigated somewhat by declaring a partial class to contain the private class and separating them into separate files that way but is this really a good approach?

David Clarke
  • 12,888
  • 9
  • 86
  • 116
  • Standard answer, it depends. Clearly this is very dependent on what the embedded class is being used to implement. If the embedded class can change independently of the enclosing class then isn't that a violation of SRP? – David Clarke Sep 19 '12 at 09:18
  • 1
    The embedded class does not (can not) have any responsibility to the outside world. It's part of a micro-cosmos where it has its own (presumably single) responsibility. – H H Sep 19 '12 at 09:49
  • @HenkHolterman: That's exactly what i was thinking, it *cannot*, at least *should not* (if you want to follow principles), have any responsibility outside it's enclosing type. I think that's somebody would decide to place it there and make it private in the first place. – atiyar Sep 19 '12 at 10:19

4 Answers4

3

Usually, nested types (either class or struct, including enumerations) are used for some kind of contextual data and/or behavior, which doesn't have any sense without its context.

E.g., you could make nested types for some interop API, when you don't want to provide access to that API from external code, or you're using some kind of helper data container, which provides functionality, useful only for surrounding class.

So, even making these types internal can bring confusion to other developers (especially, where a single project is being edited by several people).

I don't see, how SOLID is broken here - nesting the type is just a limiting of type scope. It is not an extending of functionality of the surrounding class.

David Clarke
  • 12,888
  • 9
  • 86
  • 116
Dennis
  • 37,026
  • 10
  • 82
  • 150
  • Thanks Dennis. I'm getting the impression the code I'm looking at is using the *private* class inappropriately. Just because the embedded class is only used by the enclosing class is not sufficient justification for embedding it. – David Clarke Sep 19 '12 at 18:45
2

I've used private classes in situations where an API says "you must implement and provide to us an implementation of this interface when we ask you for it" and there is no other use or consumer of that class other than the use of the API interface.

In this situation, the interface provides public or cross-functional access so there is no need for access to the implementation.

dthorpe
  • 35,318
  • 5
  • 75
  • 119
  • Ok, I can see that has some merit. How do you test your private class? – David Clarke Sep 19 '12 at 09:25
  • I write unit tests that ask for the interface, and exercise the interface. – dthorpe Sep 19 '12 at 17:10
  • Right, that makes sense. IIUC, the *public* enclosing type is a type of facade? Do you have a *public* method implementing the interface that then uses a method on the *private* class to implement the functionality? Can you provide an example? That isn't the usage I'm seeing in the sample I'm working with. In the sample code, the *private* class is used to embed a type that is used by the enclosing type. – David Clarke Sep 19 '12 at 18:24
1

Why would the SRP be broken? You separate a responsibility that is only accessed inside a class into a nested class.

Most other principles do not apply to private members or private nested classes.

Dmitry S.
  • 8,373
  • 2
  • 39
  • 49
  • Why do other principles suddenly not apply to private nested classes? Surely a private class is by definition strongly coupled to the enclosing class which is one of the issues the SRP is trying to address. – David Clarke Sep 19 '12 at 09:21
  • Private classes are not something that would be used directly or extended by a user. A private method would also be tightly coupled to a class but that is by design and is not supposed to be an extension point or a reusable algorithm. – Dmitry S. Sep 19 '12 at 14:38
  • A user in what context? I'm not building a library or framework. I'm the producer and consumer of the code within my application so why not then make all my classes private? And I'm not convinced coupling is relevant to methods. Public or private, a method is *coupled* to a class and a method cannot exist outside a class. – David Clarke Sep 19 '12 at 18:35
  • There are such things as static methods without a state. But seriously, a private nested class probably cannot exist by itself either because it has an intimate knowledge of the outer class private members. The question whether to encapsulate the logic into a method or a class is up to you. – Dmitry S. Sep 19 '12 at 21:04
  • 1
    A tricker question would be a nested public class. It could be a builder class that builds the outer class in multiple steps (method calls) and requires a knowledge of the private variables. In this case it helps not to violate SRP because otherwise the outer class would be responsible to build itself. In .NET you might use a builder class in the same assembly and internal methods/properties on the "outer" class but the coupling will still be there. In Java code like "DialogBox.createBuilder().build()" is somewhat common and uses a nested class. – Dmitry S. Sep 19 '12 at 21:08
1

I'm not sure but I think Single Resposibilty can be broken by nested classes, since a class can now have more resasons to change. The definition is not very clear at Single Resposibilty... Anyway I think ms does also use nested classes in .net, so maybe c# is missing some features in terms of encapsulation here. I think nested classes can be fixed with not doing nested classes and writing a analyzer. Nested classes are often used to get access to private members of the wrapping class.

Ini
  • 548
  • 7
  • 19