Chaining class inheritance with overriding methods - c#

As part of a big framework (so i cant post a MCVE unfortunately) i am trying to inherit a couple of times to hide necessary initialization from the user of the class so the structure is
// internal base class
public class InternalBase
{
// declared internal to avoid subclassing by user - visibility
// is handled in AssemblyInfo.cs so library can subclass
internal InternalBase()
{
}
public virtual void startup()
{
// perform necessary initialization
}
}
// public base class the users should inherit from
public class PublicBase : InternalBase
{
public override void startup()
{
// call base class to perform required init
base.startup();
// perform extra steps like check if init was performed correctly
}
}
// user class trying to use the provided functionaly
public class Test : PublicBase
{
public override void startup()
{
// this is put here by convention/template to ensure execution of
// required init - if this could be avoided, even better
base.startup();
// users are allowed to put their own init here
// perform user init code
}
}
Now as soon as i want to step into base.startup() in the Test class, the system behaves strange. Breakpoints in the other methods are not hit. An exception is thrown from somewhere completely different, log output suggests that the program continued a bit. When the exception (type is from the framework) is thrown, there is no callstack.
Should this work in principle, how could i provide such functionality or debug what i have?

Related

Unit Testing a method containing Environment.Exit() call within it

I have a public method say,
public void ErrorEncounter()
{
//Global Error Counter
gblErrorCount++;
//Process tremination
Environment.Exit();
}
This method terminates whenever it is called. However, it will update the Global Error Count which i'm suppose to test. Is there any way to perform Unit Testing on this method?
I'm Using NUnit Framework for Unit Testing.
This method is designed to be difficult to test!
Most obviously, because it terminates the application when called. But also because it changes a global (I assume static) variable. Both of these things prevent writing a good unit test that calls the method.
Three ways around this:
1. Eliminate the method
2. Don't test the method
3. Modify the method
Option 1. If this method only called exit, then you could simply drop it and call Exit directly. However, that would make some other method difficult to test, so this isn't really a great option.
Option 2. Sometimes a method is so simple that you can avoid testing it. Whether this is such a method depends on how gblErrorCount is used elsewhere. It would appear, however, that incrementing the count has no effect, since the process immediately exits.
Option 3. Modify the method and those methods that call it. One approach would be to use an event handling mechanism and terminate the app in the event handler. You could make this easier to test by injecting a different event handler when running tests.
IOW, this is basically a pretty untestable method. Hopefully, you are in control of the system under test and can change it.
This question contains answers that show how Environment.Exit() can be tested.
Constructor Dependency Injection
One option is to convert it into a dependency by injecting it through an interface :
interface ITerminator
{
void Exit();
}
class RealTerminator
{
void Exit()=>Environment.Exit();
}
public class MyErrorChecker
{
ITerminator _terminator;
public class MyErrorChecker(ITerminator terminator)
{
_terminator=terminator;
}
public void ErrorEncounter()
{
//Global Error Counter
gblErrorCount++;
//Process tremination
_terminator.Exit();
}
}
The test project will implement a fake terminator class that sets a flag if Exit is called:
class FakeTerminator:ITerminator
{
public bool Called{get;private set;}
public void Exit()
{
Called=true;
}
}
Mocking
Another option is to mock it by extracting the call to a virtual method that can be replaced in a mock class :
public void ErrorEncounter()
{
//Global Error Counter
gblErrorCount++;
//Process tremination
ForceExit();
}
internal virtual void ForceExit()
{
Environment.Exit();
}
The test project could create a mock error checker class:
class MockErrorChecker:MyErrorChecker
{
public bool Called{get;private set;}
public override void ForceExit()
{
Called=true;
}
}
Function injection
This option isn't included in the linked question. Pass an exit Action as a parameter to ErrorEncounter whose default will be to call Environment.Exit() :
public void ErrorEncounter(Action exitFn=null)
{
var doExit=exitFn ?? (()=>Environment.Exit());
//Global Error Counter
gblErrorCount++;
//Process tremination
doExit();
}
The test could pass its own function that sets a flag:
[Test]
public void Test_Exit_Is_Called
{
bool called;
void fakeExit() { called=true; }
thatClass.ErrorEncounter(fakeExit);
Assert.True(called);
}

Allways call base.Method in Override without mentioning it for simple Scripts

I am trying to implement C# as a scripting language for my game engine. Everything works fine, only one major problem occurred in my design.
I have the class BaseEntity. And another class BossEntity that derives from BaseEntity. Then I want to be able to create a new entity via script. So I create a class in my script let's say Boss1, that derives from BossEntity.
BaseEntity has an virtual Update Method. BossEntity overrides it and calls also base.Update(). All fine in the design.
But now to my problem. In my script I also want to be able to override the Update Method. So I go ahead and override it again. All works as supposed, the BossEntity override gets lost, as I now override the BaseEntity Update again.
But for simplicity I do not want to have to call in my script base.Update() to have the same behavior as in BossEntity. That's a thing that can be forgotten, which would be for me as for a scripting language bad design.
When scripting you just add functionality not remove some in my opinion.
So my general question is, is there any way to accomplish a call to base.Update() without even calling it extra in my script?
I assume no, or maybe just with a trick, but you never know.
As far as I know, there is no way to automatically invoke the base class's virtual method when an overridden one is invoked. You must explicitly call it.
One of the things you can do is break the parent method up a bit more. Instead of having all of the code in a single overridable method like this:
public class Foo
{
public virtual void Update()
{
// Do stuff
}
}
public class Bar : Foo
{
public override void Update()
{
// Replaces the parents implementation of the
// Update method due to not calling base.Load();
}
}
Instead, you can use the Template Method Pattern to break it up in to multiple parts, so that the user can override the part that is meant explicitly for them.
public class Foo
{
public void Update()
{
this.OnUpdating();
this.PerformUpdate();
this.OnUpdated();
}
public virtual void PerformUpdate()
{
// Leave this empty. Let the subclass override it and
// do their own thing. Your parent code will still
// get called when Update() is called.
}
public void OnUpdating()
{
// Invoke code that you want to guarantee is always
// executed PRIOR the overridden PerformUpdate() method
// is finished.
}
public void OnUpdated()
{
// Invoke code that you want to guarantee is always
// executed AFTER the overridden PerformUpdate() method
// is finished.
}
}
public class Bar : Foo
{
public override void PerformUpdate()
{
// Do custom stuff, don't have to call base.PerformUpdate()
// because it already does it's code in OnUpdating()
// and OnUpdated().
}
}
Hope this makes sense. This is what I do in my game engine. I then document that a call to base.PerformUpdate() is not needed. Another option is to make the PerformUpdate() method abstract, forcing children to implement it. That makes it a bit more clearer that there is no need to invoke base.PerformUpdate().
public class Foo
{
public void Update()
{
this.OnUpdating();
this.PerformUpdate();
this.OnUpdated();
}
// Child class is required to implement this method.
// Only downside is you will no longer be able to instance
// the base class. If that is acceptable, then this is really
// the preferred way IMO for what you are wanting to do.
public abstract void PerformUpdate();
public void OnUpdating()
{
// Invoke code that you want to guarantee is always
// executed PRIOR the overridden PerformUpdate() method is finished.
}
public void OnUpdated()
{
// Invoke code that you want to guarantee is always
// executed AFTER the overridden PerformUpdate() method is finished.
}
}
In the end, this approach lets your base class handle its update code safely, by forcing children to implement their own update method that you do not depend on. Your base class can run through its update stuff before and after the child-class has run through its updates.
This basically lets you do this in your game code:
Bar myFoo = new Bar();
myFoo.Update();
And you can rest assured that your base class update methods get called, and the child update code will get called as well.

Implement Derived Class as Base on Constructor Exception?

I'm working with code to implement a hardware test system, which involves communication with several benchtop instruments. When I instantiate an instance of one of these instruments, the constructor attempts to open the communication session with the instrument. If that fails, I can throw all kinds of errors, but what I'd like to do is to have the instrument object default to a virtual or simulation mode where no actual communication is done but I can still run my code.
Right now I have all instruments of one type inheriting from a base class. I've added virtual methods to the base class which perform these debugging functions, but I'm stuck on a clean way to modify the derived object at creation time to implement the base classes methods when the communication session fails.
The ideal solution would be to have the constructor (technically the new keyword) return an instance of the base class instead of the derived class, but I've done a fair amount of searching and that doesn't appear to be possible.
I could add a property to the derived class to use as a boolean flag where every method in the derived class tests against that flag and invokes the base class method if true, but I'm hoping to find a more elegant solution that doesn't require a few hundred if statements and a serious flogging of base.Stuff() calls.
I have a few dozen methods and a handful of instruments inheriting in this way so a solution that doesn't require an explicit change to every one of those overriding methods would go a long, long way.
public abstract class BaseInstrument
{
public string Address;
protected MessageBasedSession MbSession;
public virtual string Identify()
{
return "Debugging mode, fake identity";
}
}
public class SpecificInstrument : BaseInstrument
{
public SpecificInstrument(string address)
{
Address = address;
try
{
MbSession = (MessageBasedSession)ResourceManager.GetLocalManager().Open(Address);
}
catch
{
// Return an object modified in such a way that it invokes base class virtual methods
// instead of method overrides.
// Constructor has no return value (that comes from the new keyword) so I can't
// just return an instance of the base class...
}
}
public override string Identify()
{
return ActualInstrumentRead();
}
// ...
}
public class Program
{
public static void Main()
{
SpecificInstrument instr = new SpecificInstrument(ipAddress);
Console.WriteLine(instr.Identify()); // Would like to print the debug case if eg. my LAN is down
}
}
I feel like I might be missing an obvious solution to this but I've been scratching my head for hours.
You can't return a BaseInstrument from a SpecificInstrument constructor.
One alternative would be to put this logic where you create this instrument:
BaseInstrument instrument;
try {
instrument = new SpecificInstrument();
}
catch {
instrument = new BaseInstrument();
}

Losing reference to an object When a Subclass tries to use that object

this is weird to me, it's got to be something obvious but when using Selenium who knows...I haven't used Selenium until now.
But here is just basic code I think and I think it's just a syntax/OOP issue but not sure what.
Lets say I have a base class that has a driver property and a method where I'm getting the problem happening later on:
public Abstract BaseTest
{
protected IWebTestDriver TestDriver {get; set;}
...more code
protected void WaitForGridToRender(double seconds)
{
TestDriver.Wait(TimeSpan.FromSeconds(seconds));
}
}
I then have a test class called MyTests.cs that inherits BaseTest and in it an NUnit test:
[TestFixture]
public class MyTests : BaseTest
{
[Test]
public void SomeTab_WhenClicked_ShowsSomething()
{
SomeLandingPage someLandingPage = new SomeLandingPage(TestDriver);
mainLandingPage.NavigateToTheMainPage();
... rest of code
}
.. other test methods
}
And I have a 3rd class that serves as a "PageObject" that allows me to just reuse certain elements on the page, get at some things (more DRY) than have these same common methods repeated throughout my test methods:
public class MyPageObject : BaseWebTest
{
public void NavigateToTheMainPage()
{
// wait for the user to log in
WaitForGridToRender(5);
}
}
Now here's where my problem is and how things are being called:
1) The Base class is first initialized...meaning that TestDriver's instance is created and set to the TestDriver property so we can use it in subclasses
2) Eventually some code in another class that I did not mention here is called from the Base Class which just sends some calls to opens up FireFox, does some stuff...nothing special here
3) Eventually control goes to my test method and eventually hits the SomeTab_WhenClicked_ShowsSomething() method which then calls the MyPageObject.NavigateToTheMainPage() method.
The NavigateToTheMainPage() tries to call the BaseTest method called WaitForGridToRender and control eventually gets there.
Now the problem is, up till when WaitForGridToRender is called from within MyPageObject, that BaseTest.TestDriver instance has been there and accessible to both my test class and my PageObject class.
But when I finally debug and get to this line in WaitForGridToRender:
TestDriver.Wait(seconds);
Now for some reason, I get a null ref on TestDriver...the reference instance for that property is gone!
No idea why which is why I'm posting this cause I'm stuck as to why this might happen.
1) The Base class is first initialized...meaning that TestDriver's instance is created and set to the TestDriver property so we can use it in subclasses
This code
protected IWebTestDriver TestDriver {get; set;}
declares a protected property of type IWebTestDriver named TestDriver.
Unless you're setting TestDriver to something in a constructor or method not shown here, the backing variable for TestDriver contains a null reference.

should new behavior be introduced via composition or some other means?

I chose to expose some new behavior using composition vs. injecting a new object into my consumers code OR making the consumer provide their own implementation of this new behavior. Did I make a bad design decision?
I had new requirements that said that I needed to implement some special behavior in only certain circumstances. I chose to define a new interface, implement the new interface in a concrete class that was solely responsible for carrying out the behavior. Finally, in the concrete class that the consumer has a reference to, I implemented the new interface and delegate down to the class that does the work.
Here are the assumptions that I was working with...
I haven an interface, named IFileManager that allows implementors to manage various types of files
I have a factory that returns a concrete implementation of IFileManager
I have 3 implementations of IFileManager, these are (LocalFileManager, DfsFileManager, CloudFileManager)
I have a new requirements that says that I need to manage permissions for only the files being managed by the CloudFileManager, so the behavior for managing permissions is unique to the CloudFileManager
Here is the test that led me to the code that I wrote...
[TestFixture]
public class UserFilesRepositoryTest
{
public interface ITestDouble : IFileManager, IAclManager { }
[Test]
public void CreateResume_AddsPermission()
{
factory.Stub(it => it.GetManager("cloudManager")).Return(testDouble);
repository.CreateResume();
testDouble.AssertWasCalled(it => it.AddPermission());
}
[SetUp]
public void Setup()
{
testDouble = MockRepository.GenerateStub<ITestDouble>();
factory = MockRepository.GenerateStub<IFileManagerFactory>();
repository = new UserFileRepository(factory);
}
private IFileManagerFactory factory;
private UserFileRepository repository;
private ITestDouble testDouble;
}
Here is the shell of my design (this is just the basic outline not the whole shibang)...
public class UserFileRepository
{
// this is the consumer of my code...
public void CreateResume()
{
var fileManager = factory.GetManager("cloudManager");
fileManager.AddFile();
// some would argue that I should inject a concrete implementation
// of IAclManager into the repository, I am not sure that I agree...
var permissionManager = fileManager as IAclManager;
if (permissionManager != null)
permissionManager.AddPermission();
else
throw new InvalidOperationException();
}
public UserFileRepository(IFileManagerFactory factory)
{
this.factory = factory;
}
private IFileManagerFactory factory;
}
public interface IFileManagerFactory
{
IFileManager GetManager(string managerName);
}
public class FileManagerFactory : IFileManagerFactory
{
public IFileManager GetManager(string managerName)
{
IFileManager fileManager = null;
switch (managerName) {
case "cloudManager":
fileManager = new CloudFileManager();
break;
// other managers would be created here...
}
return fileManager;
}
}
public interface IFileManager
{
void AddFile();
void DeleteFile();
}
public interface IAclManager
{
void AddPermission();
void RemovePermission();
}
/// <summary>
/// this class has "special" behavior
/// </summary>
public class CloudFileManager : IFileManager, IAclManager
{
public void AddFile() {
// implementation elided...
}
public void DeleteFile(){
// implementation elided...
}
public void AddPermission(){
// delegates to the real implementation
aclManager.AddPermission();
}
public void RemovePermission() {
// delegates to the real implementation
aclManager.RemovePermission();
}
public CloudFileManager(){
aclManager = new CloudAclManager();
}
private IAclManager aclManager;
}
public class LocalFileManager : IFileManager
{
public void AddFile() { }
public void DeleteFile() { }
}
public class DfsFileManager : IFileManager
{
public void AddFile() { }
public void DeleteFile() { }
}
/// <summary>
/// this class exists to manage permissions
/// for files in the cloud...
/// </summary>
public class CloudAclManager : IAclManager
{
public void AddPermission() {
// real implementation elided...
}
public void RemovePermission() {
// real implementation elided...
}
}
Your approach to add your new behavior only saved you an initialization in the grand scheme of things because you to implemented CloudAclManager as separate from CloudFileManager anyways. I disagree with some things with how this integrates with your existing design (which isn't bad)...
What's Wrong With This?
You separated your file managers and made use of IFileManager, but you didn't do the same with IAclManager. While you have a factory to create various file managers, you automatically made CloudAclManager the IAclManager of CloudFileManager. So then, what's the point of having IAclManager?
To make matters worse, you
initialize a new CloudAclManager
inside of CloudFileManager every time you try to get its ACL
manager - you just gave factory
responsibilities to your
CloudFileManager.
You have CloudFileManager implement IAclManager on top of having it as a property. You just moved the rule that permissions are unique to CloudFileManager into your model layer rather than your business rule layer. This also results in supporting the unnecessary
potential of circular referencing between self and property.
Even if you wanted
CloudFileManager to delegate the
permission functionality to
CloudAclManager, why mislead other
classes into thinking that
CloudFileManager handles its own
permission sets? You just made your
model class look like a facade.
Ok, So What Should I Do Instead?
First, you named your class CloudFileManager, and rightly so because its only responsibility is to manage files for a cloud. Now that permission sets must also be managed for a cloud, is it really right for a CloudFileManager to take on these new responsibilities? The answer is no.
This is not to say that you can't have code to manage files and code to manage permissions in the same class. However, it would then make more sense for the class to be named something more general like CloudFileSystemManager as its responsibilities would not be limited to just files or permissions.
Unfortunately, if you rename your class it would have a negative effect on those currently using your class. So how about still using composition, but not changing CloudFileManager?
My suggestion would be to do the following:
1. Keep your IAclManager and create IFileSystemManager
public interface IFileSystemManager {
public IAclManager AclManager { get; }
public IFileManager FileManager { get; }
}
or
public interface IFileSystemManager : IAclManager, IFileManager {
}
2. Create CloudFileSystemManager
public class CloudFileSystemManager : IFileSystemManager {
// implement IFileSystemManager
//
// How each manager is set is up to you (i.e IoC, DI, simple setters,
// constructor parameter, etc.).
//
// Either way you can just delegate to the actual IAclManager/IFileManager
// implementations.
}
Why?
This will allow you to use your new behavior with minimal impact to your current code base / functionality without affecting those who are using your original code. File management and permission management can also coincide (i.e. check permissions before attempting an actual file action). It's also extensible if you need any other permission set manager or any other type of managers for that matter.
EDIT - Including asker's clarification questions
If I create IFileSystemManager : IFileManager, IAclManager, would the repository still use the FileManagerFactory and return an instance of CloudFileSystemManager?
No, a FileManagerFactory should not return a FileSystemManager. Your shell would have to update to use the new interfaces/classes. Perhaps something like the following:
private IAclManagerFactory m_aclMgrFactory;
private IFileManagerFactory m_fileMgrFactory;
public UserFileRepository(IAclManagerFactory aclMgrFactory, IFileManagerFactory fileMgrFactory) {
this.m_aclMgrFactory = aclMgrFactory;
this.m_fileMgrFactory = fileMgrFactory;
}
public void CreateResume() {
// I understand that the determination of "cloudManager"
// is non-trivial, but that part doesn't change. For
// your example, say environment = "cloudManager"
var environment = GetEnvMgr( ... );
var fileManager = m_fileMgrFactory.GetManager(environment);
fileManager.AddFile();
// do permission stuff - see below
}
As for invoking permission stuff to be done, you have a couple options:
// can use another way of determining that a "cloud" environment
// requires permission stuff to be done
if(environment == "cloudManager") {
var permissionManager = m_aclMgrFactory.GetManager(environment);
permissionManager.AddPermission();
}
or
// assumes that if no factory exists for the environment that
// no permission stuff needs to be done
var permissionManager = m_aclMgrFactory.GetManager(environment);
if (permissionManager != null) {
permissionManager.AddPermission();
}
I think that composition is exactly the right means to to this kind of trick. But I think you should keep it more simple (KISS) and just make an IAclManager property in the IFileManager and set it to null by default and set the SecurityManager implementation for the cloud service there.
This has different upsides:
You can check if permissions need to be checked by nullchecking the securityManager property. This way, if there doesn't need to be permissionsManaging done (as with localfile system), you don't have exceptions popping up. Like this:
if (fileManager.permissionsManager != null)
fileManager.permissionsManager.addPermission();
When you then carry out the task (to add or delete a file), you can check again if there's a permissionsManager and if the permission is given, if not throw exception (as you'll want to throw the exception when a permission to do an action is missing, not if a permission is missing in general if you're not going to add or delete files).
You can later on implement more IAclManagers for the other IFileManagers when your customer changes the requirements next time the same way as you would now.
Oh, and then you won't have such a confusing hierarchy when somebody else looks at the code ;-)
In general it looks good, but I do have a few suggestions. It seems that your CreateResume() method implementation demands a IFileManager that is also an IAclManager (or else it throws an exception).
If that is the case, you may want to consider adding an overload to your GetManager() method in which you can specify the interface that you require, and the factory can have the code that throws an exception if it doesn't find the right file manager. To accompolish this you can add another interface that is empty but implements both IAclManager and IFileManager:
public interface IAclFileManager : IFileManager, IAclManager {}
And then add the following method to the factory:
public T GetManager<T>(string name){ /* implementation */}
GetManager will throw an exception if the manager with the name given doesn't implement T (you can also check if it derives from or is of type T also).
All that being said, if AddPermissions doesn't take any parameters (not sure if you just did this for the post), why not just call AddPermissions() from CloudFileManager.AddFile() method and have it completely encapsulated from the user (removing the need for the new IAclManager interface)?
In any event, doesn't seem like a good idea to call AddFile in the CreateResume() method and only then throw the exception (since you now you have now created a file without the correct permissions which could be a security issue and also the consumer got an exception so he may assume that AddFile didn't succeed, as opposed to AddPermission).
Good luck!

Categories