Reputation: 121
I have a project where I'm implementing an API that has about 300 methods and I want to separate them out so they're organized by the API category.
I'm trying to lay out my classes so that I have a parent class that has settings, and organize child classes inside of the parent that have access to those settings. I found a horribly convoluted way to do this that probably breaks every rule on the planet. Is there a more standardized way of going about this than what I've come up with?
I want to be able to create an instance of the parent class like:
var foo = new Foo(new FooSettings("Hello"));
and be able to access the functions in the child classes like:
foo.Bar1.WriteTag();
foo.Settings.Tag = "Woot";
foo.Bar2.WriteTag();
with Bar1 and Bar2 having access to the settings I gave when I created the instance of Foo. My current class layout is:
public class Foo
{
public FooSettings Settings;
public FooMethods.Bar1 Bar1 { get; }
public FooMethods.Bar2 Bar2 { get; }
public Foo(FooSettings settings)
{
Settings = settings;
Bar1 = new FooMethods.Bar1(ref Settings);
Bar2 = new FooMethods.Bar2(ref Settings);
}
}
public class FooSettings
{
public string Tag { get; set; }
public FooSettings(string tag)
{
Tag = tag;
}
}
public class FooMethods
{
public class Bar1
{
private FooSettings Settings { get; }
public Bar1(ref FooSettings settings)
{
Settings = settings;
}
public void WriteTag()
{
Console.WriteLine("Bar1 " + Settings.Tag);
}
}
public class Bar2
{
private FooSettings Settings { get; }
public Bar2(ref FooSettings settings)
{
Settings = settings;
}
public void WriteTag()
{
Console.WriteLine("Bar2 " + Settings.Tag);
}
}
}
Upvotes: 0
Views: 258
Reputation: 453
I can suggest you following changes .
You can have a base class for FooMethods , something like FooMethodsBaseClass which will be parent class for Bar1 and Bar2 .
You can move all your common codes, methods to base class and Bar1 and Bar2 can access those .
This way you can segregate the code . And in future, if you get requirement in which you have to implement in both in Bar1 and Bar2 you can add it in single place, in base class. Thus you can avoid duplicates .
As you can see WriteTag i made it as virtual . And overridden by child classes
Also passing as ref is not needed
Further more, you can have interface for FooMethodsBaseClass. This will actually help you in writing unit tests
Base Interface :
public interface IFooMethodsBaseClass
{
void WriteTag();
}
Base class:
public class FooMethodsBaseClass:IFooMethodsBaseClass
{
protected IFooSettings Settings { get; }
public FooMethodsBaseClass(IFooSettings settings)
{
Settings = settings;
}
public virtual void WriteTag()
{
}
}
Bar1 class
public class Bar1: FooMethodsBaseClass
{
public Bar1(IFooSettings fooSettings):base(fooSettings)
{
}
public override void WriteTag()
{
Console.WriteLine("Bar1 " + Settings.Tag);
}
}
Bar2 Class
public class Bar2: FooMethodsBaseClass
{
public Bar2(IFooSettings fooSettings):base(fooSettings)
{
}
public override void WriteTag()
{
Console.WriteLine("Bar2 " + Settings.Tag);
}
}
Foo and Foo Settings . Foo settings can be derived from interface as well. Since you are creating Foo by passing FooSettings , by introducing interface based injection you can write unit tests without any dependency by mocking
public class Foo
{
public IFooSettings Settings;
public IFooMethodsBaseClass Bar1 { get; }
public IFooMethodsBaseClass Bar2 { get; }
public Foo(IFooSettings settings)
{
Settings = settings;
Bar1 = new Bar1(Settings);
Bar2 = new Bar2(Settings);
}
}
public class FooSettings: IFooSettings
{
public string Tag { get; set; }
public FooSettings(string tag)
{
Tag = tag;
}
}
public interface IFooSettings
{
string Tag { get; set; }
}
Finally you can create Foo instance like this
IFooSettings fs = new FooSettings("1");
Foo foo = new Foo(fs);
Upvotes: 2
Reputation: 106920
Ok, so this actually seems pretty fine. A few tweaks I would make myself:
ref
qualifier in the BarX
constructors.BarX
classes could be lazily instantiated when someone first accesses Foo.BarX
. When using such huge APIs, the typical use case will probably just use a few methods, so most BarX
s will never be needed.Foo.Settings
readonly, either through a property or just with a readonly
qualifier.Foo
instance to the BarX
instead of the settings. BarX
can access the settings (and more if needed) through that.Upvotes: 1
Reputation: 89
May be to make the settings a static field?
public class Foo
{
public static FooSettings Settings;
public FooMethods.Bar1 Bar1 { get; private set; }
public FooMethods.Bar2 Bar2 { get; private set; }
public Foo(FooSettings settings)
{
Settings = settings;
Bar1 = new FooMethods.Bar1();
Bar2 = new FooMethods.Bar2();
}
}
public class FooSettings
{
public string Tag { get; set; }
public FooSettings(string tag)
{
Tag = tag;
}
}
public class FooMethods
{
public class Bar1
{
public void WriteTag()
{
Console.WriteLine("Bar1 " + Foo.Settings.Tag);
}
}
public class Bar2
{
public void WriteTag()
{
Console.WriteLine("Bar2 " + Foo.Settings.Tag);
}
}
}
And methods bar1 and bar2 can be implemented by the one class. Or its just for example?
Upvotes: 0