Mark Toman
Mark Toman

Reputation: 3239

Nested classes for a multiple-phase state

I would like to use nested classes for a "developing state":

public class WebSvcClient : IDisposable
{
    //
    // 10 private fields required by all methods
    ...

    public Profile Profile { get; private set; }
    public void Authenticate()
    {
        this.Profile = new Profile();
    }
    public class Profile
    {
        // public methods that do require authentication
        ...
    }

    // public methods that don't require authentication
    ...
}  

I can see several benefits:

But is it considered good practice?

Upvotes: 1

Views: 95

Answers (3)

oɔɯǝɹ
oɔɯǝɹ

Reputation: 7625

Consider using interfaces that represent state, and methods that can transition from one state to another:

public interface INew {
    // transition to initialized state
    IInitialized Init();
}

and

public interface IInitialized {
    // connect to get a connected object
    IConnected Connect(string connection);
}

and

public interface IConnected {
    // disconnect reverts back in state
    IInitialized Disconnect();

    // methods only available when connected
    bool GetValue(string name);
    void SetValue(string name, bool value);
}

Etc..

You can implement these interfaces on a common class, or use a different class for every state. You will need some kind of factory to create the initial instance.

This works well when you are in full control of the actual state (no unexpected disconnect etc..).

This way you are telling the users of your API what they need to do, in what order, to get access to the desired methods. You can use 'fluent' code to use this:

var newMachine = Factory.NewMachine();
var connected = newMachine
    .Init()
    .Connect(connectionString);

connected.GetValue("test");
...

connected.Disconnect();

Upvotes: 1

Henk Holterman
Henk Holterman

Reputation: 273264

I don't think there's any gain here.

  • Encapsulation, Profile makes sense only in the context of WebSvcClient

But using private fields in another class, even when it's nested, breaks encapsulation.

  • Single IDisposable unit

It causes more problems then it solves here. What if other code keeps a Profile around after the Service was disposed?

  • Lack of need for 3rd class just to pass the private fields to Profile

Ok, maybe. That class would have been messy anyway.

  • No pollution of namespace

That's not really an issue anyway.


As an alternative, use two interfaces, or at least one for the Profile part. Implement the relevant members explicit so that they are only available through an IProfile reference.
This can be circumvented with casting, but if that's a problem you should speak with your team. It would matter for a library, but it shouldn't for an Application.

Upvotes: 1

Onur Gazioğlu
Onur Gazioğlu

Reputation: 511

There are no benefits:

  • Encapsulation is about modifiers. Your nested class and its methods are public. If you don't reach to nested class from outside, you can use private class for pollution.
  • IDisposable unit is related to the implementer class only. The nested class won't be affected.
  • Pollution doesn't come from namespaces, it comes from bad designs, and bad naming practices. Keep in mind that you are not the only developer. The next developers must understand your code, so they should see the code easily by exploring file names. Or they have to check all code file by file.

Upvotes: 1

Related Questions