This is the first time I am writing a C++ code using SOLID principles. Therefore I do not know if the following sample code implements the principles correctly. My questions follow the code.
I highly appreciate all responses. Thanks!
Here is the sample:
class ICustomer
{
public:
virtual char* GetName() = 0;
virtual char* GetSurname() = 0;
virtual char* GetAddress() = 0;
};
class CCustomer : public ICustomer
{
public:
virtual char* GetName()
{
return "Name1";
}
virtual char* GetSurname()
{
return "Surname1";
}
virtual char* GetAddress()
{
return "Address1";
}
};
class IExporter
{
public:
virtual void Export() = 0;
};
class CExportToExcel : public IExporter
{
public:
virtual void Export()
{
ICustomer* pCustomer = new CCustomer;
printf("%s, %s, %s\n", pCustomer->GetName(), pCustomer->GetSurname(), pCustomer->GetAddress());
}
};
class IShopOwner
{
public:
virtual void Execute() = 0;
};
class CShopOwner : public IShopOwner
{
public:
virtual void Execute()
{
IExporter* pExp = new CExportToExcel;
pExp->Export();
}
};
void main()
{
IShopOwner* pOwner = new CShopOwner;
pOwner->Execute();
}
Questions:
Is it a valid SOLID implementation? If no, how it should be.
In the sample ICustomer has GetName(), GetSurname() and GetAddress(). I want an additional info GetPhoneNumber(). Where should I put that in? What changes will it incur?
In the sample there is CExportToExcel. Now I want an additional class CExportToHTML and use it. How should I do that?
The key feedback is to take the dependencies through the concrete class constructors, and take these dependencies as the interfaces not the concrete class, so .. In your object composition root you can decide which actual concrete implementation to pass on to create your objects, ie another product implementation of an interface or just a test mock class for testability purposes. it will also nicely fit with dependency injection pattern and frameworks.
as an example:
change your CShopOwner class to have a constructor that takes an IExporter object, keep that object as a property and use that inside your Execute method. When you are creating your CShopOwner object, on run time you can decide what exact concrete implementation of IExporter interface to pass it on ie. CExportToHTML.
This should cover your 1st and 3rd questions. About your second question. If GetPhoneNumber() would be relevant for all implementation s of ICustomer, puristically speaking you should create a new interface still, inheriting from ICustomer with one method - GetPhoneNumber() - and not change the ICustomer interface especially if it is already being used by client code because you are breaking the contract by changing it and may cause issues on the existing clients. On the other hand if you asses the situation and risk you could change the ICustomer interface directly and all consumers of it, if this is all your own code which will be much easier. we have all done it :)
Related
I have a class with a protected copy constructor:
class ThingList
{
public:
ThingList() {}
virtual ~ThingList() {}
std::vector<Thing> things;
protected:
ThingList(const ThingList ©) {}
};
I have another class the uses this one:
class AnotherThing
{
public:
AnotherThing()
{
}
virtual ~AnotherThing() {}
void DoListThing(const ThingList &list)
{
}
};
and a Mock version of this class:
class MockAnotherThing : public AnotherThing
{
public:
MOCK_METHOD1(DoListThing, void(const ThingList &list));
};
I want to call this method DoListThing with a real argument to supply a real list:
TEST(Thing, DoSomeThingList)
{
MockThing thing;
ThingList list;
MockAnotherThing anotherThing;
list.things.push_back(Thing());
EXPECT_CALL(anotherThing, DoListThing(list));
anotherThing.DoListThing(list);
}
I get an error compiling this:
1>..\mockit\googletest\googlemock\include\gmock\gmock-matchers.h(3746): error C2248: 'ThingList::ThingList': cannot access protected member declared in class 'ThingList'
Yet if I make a non-Mock call it works just fine:
ThingList list;
AnotherThing theRealThing;
theRealThing.DoListThing(list);
If in the Mock test I call with '_', it works:
TEST(Thing, DoSomeThingList)
{
MockThing thing;
ThingList list;
MockAnotherThing anotherThing;
list.things.push_back(Thing());
EXPECT_CALL(anotherThing, DoListThing(_));
anotherThing.DoListThing(list);
}
However, how can I pass a list in this case? If the list was returned by DoListThing, I could use Return but what do I for an argument that get modified like this?
I was unable to get past a protected copy constructor so my answer was to create a fake (dummy) version of a class and ignore Google Mock. This worked well enough for me to test the class in question. The example I provided here is a simplified version of the bigger package.
I'm currently diving into the world of Xamarain with the MvvmCross framework. In my current project I want to make use of a MVVM base ViewModel to be able to reuse some of my code in other ViewModels.
When trying to implement this I've ran into a problem when using the MvxViewModel which supports passing parameters between navigation.
public abstract class BaseViewModel<TParameter> : MvxViewModel, IMvxViewModel<TParameter> where TParameter : class
{
protected readonly IMvxNavigationService _navigationService;
public BaseViewModel(IMvxNavigationService navigationService)
{
_navigationService = navigationService;
}
public new abstract Task Initialize(TParameter parameter);
}
This way I'm able to use the BaseViewModel as following.
public class ExampleViewModel : BaseViewModel<ExampleParameters>
{
private ExampleParameters _parameter;
public ExampleViewModel(IMvxNavigationService navigationService) : base(navigationService)
{
}
public override Task Initialize(ExampleParameters parameter)
{
return Task.Run(() => { _parameter = parameter; });
}
}
In this situation I think this is a pretty good solution. The ExampleViewModel even tells me I need to implement the Initialize Task when I've forgotten.
Still this solution is not great in every situation. When I have ViewModel that doesn't require the passing of parameters I still need to specify a parameters object and implement the Initialize method.
public class ParameterlessViewModel : BaseViewModel<object>
{
public ParameterlessViewModel(IMvxNavigationService navigationService) : base(navigationService)
{
}
public override Task Initialize(object parameter)
{
return Task.Run(() => { });
}
}
When removing the abstract method from the BaseViewModel I wont need to implement the Initialize method but then I won't be forced to implement it when I'm creating a ViewModel that requires the passing of parameters.
The above solution is workable but I'm curious if anyone ran into this same problem and maybe has a better solution? One which is good in both situations without having to setup two BaseViewModel classes.
Kind regards,
Jop Middelkamp
The documentation for this states: https://www.mvvmcross.com/documentation/fundamentals/navigation
If you have a BaseViewModel you might not be able to inherit MvxViewModel<TParameter> or MvxViewModel<TParameter, TResult> because you already have the BaseViewModel as base class. In this case you can implement the following interface:
IMvxViewModel<TParameter>, IMvxViewModelResult<TResult> or IMvxViewModel<TParameter, TResult>
In case you use TResult you can just copy the source code into your viewmodel:
public override TaskCompletionSource<object> CloseCompletionSource { get; set; }
public override void ViewDestroy()
{
if (CloseCompletionSource != null && !CloseCompletionSource.Task.IsCompleted && !CloseCompletionSource.Task.IsFaulted)
CloseCompletionSource?.TrySetCanceled();
base.ViewDestroy();
}
Do we do the add the Interface IMvxViewModel in the base class or the device class, can you give a simple example
In this case you can implement the following interface:
IMvxViewModel<TParameter>, IMvxViewModelResult<TResult> or IMvxViewModel<TParameter, TResult>
I realize the question may be confusing and the word "better" may be problematic, but I could not think of a, well, better way to ask.
Let's say you are writing an application that has a single entry point, like Main, which also serves as the composition root for IoC:
From outside, run application
Main or equivalent
var container = new AwesomeContainer();
container.Install(new CompositionRootInstaller(startArgs));
container.Register( ... );
ApplicationMiddleware = container.Resolve<IMiddleware>();
ApplicationMiddleware.SignalStart();
Here, ApplicationMiddleware might be a ControllerFactory in a web application, for instance.
Now, of course we will have lots of other services located by the container at the appropriate time (per request, for instance).
Sometimes we will run into situations where we don't feel like it's so bad to just assign, say, a default value to a field. But, in my view, this breaks IoC a little bit.
So, is it a true statement that (regardless of the marginal value of doing so) it is always better to avoid calling constructors or factories that call constructors or otherwise get components without calling the container once we leave the entry point?
Example: WinForms program
Here is the setup. It is a contrived example but I'm trying to focus on the issue at hand...
static class Program
{
[STAThread]
static void Main(string[] args)
{
using (var root = new AppCompositionRoot())
{
}
}
}
class AppCompositionRoot : IDisposable
{
private IWindsorContainer _container;
public AppCompositionRoot(IWindsorContainer container = null)
{
_container = container ?? new WindsorContainer();
}
public void Run()
{
var formFactory = _container.Resolve<DefaultFormFactory>();
Application.Idle += delegate
{
formFactory.ApplicationIsIdle();
};
Application.Run();
}
public void Dispose()
{
_container?.Dispose();
}
}
public interface IFormFactory
{
System.Windows.Forms.Form Create();
}
public class DefaultFormFactory : IFormFactory
{
private readonly IWindsorContainer _container;
private Form _lastForm;
public DefaultFormFactory(IWindsorContainer container)
{
_container = container;
}
public Form Create()
{
return _container.Resolve<AppForm>();
}
public void ApplicationIsIdle()
{
_lastForm = _lastForm ?? Create();
_lastForm.Show();
}
}
public class AppForm : Form
{
private readonly string _big; // sensible default is "Welcome!"
private readonly string _little; // sensible default is a string varying by form, time of day, factory
private readonly IList<object> _watched; // sensible default is list empty.
public AppForm(string bigMessage, string littleMessage, IList<object> watched)
{
_big = bigMessage;
_little = littleMessage;
_watched = watched;
}
public void Initialize()
{
// do something with bigMesaage, littleMessage, etc.
}
}
So let's start with concrete AppForm. It needs two strings and a List<object>.
Let's say for all of them there is a natural default that makes sense like 95% of the time, as in something that would be a const string on the class.
Regardless my question is - to really do IoC in the ideal sense, wouldn't it be true that you should always see constructors like these (clean constructors) and any defaults should be injected as well?
Inversion of Control simply states that control (whatever that is) is inverted. It doesn't mean that you have to invert everything; you should invert that which you want to vary.
If you're writing a Hello world application, and you don't want to vary anything, you can create the string within the implementation:
Console.WriteLine("Hello, world!");
On the other hand, if you want to be able to vary the message, you can pass it in as a Primitive Dependency:
public class Helo
{
private readonly string message;
public Helo(string message)
{
this.message = message;
}
public void SayHello()
{
Console.WriteLine(this.message);
}
}
If it helps, Miško Hevery makes the distinction between newables and injectables. On a different note, in my book, I've attempted to make a distinction between stable and volatile dependencies.
You can new up values that you don't need to be able to control from the outside. If you need to control them from the outside (Inversion of Control, remember), then you need to inject them.
While trying to coerce Windsor into wrapping an implementation with a random number of decorators, i've stumbled upon the following:
i have 3 decorators and an implementation all using the same interface.
if you run this code, windsor resolves icommandhandler<stringcommand> as implementation, which, as far as i can tell, is expected behaviour, because the typed implementation can not be registered with the open typed decorators.
However, if you uncomment the line container.Register(Component.For<ICommandHandler<stringCommand>>().ImplementedBy<Decorator1<stringCommand>>());, all three decorators will be used to resolve implementation, which is the desired result (sort of : ).
class Program
{
static void Main(string[] args)
{
var container = new WindsorContainer();
container.Register(Component.For(typeof(ICommandHandler<>)).ImplementedBy(typeof(Decorator1<>)));
container.Register(Component.For(typeof(ICommandHandler<>)).ImplementedBy(typeof(Decorator2<>)));
container.Register(Component.For(typeof(ICommandHandler<>)).ImplementedBy(typeof(Decorator3<>)));
//uncomment the line below and watch the magic happen
//container.Register(Component.For<ICommandHandler<stringCommand>>().ImplementedBy<Decorator1<stringCommand>>());
container.Register(Component.For<ICommandHandler<stringCommand>>().ImplementedBy<implementation>());
var stringCommandHandler = container.Resolve<ICommandHandler<stringCommand>>();
var command = new stringCommand();
stringCommandHandler.Handle(command);
Console.WriteLine(command.s);
Console.ReadKey();
}
}
public interface ICommandHandler<T>
{
void Handle(T t);
}
public class stringCommand
{
public string s { get; set; }
}
public abstract class Decorator<T> : ICommandHandler<T>
{
public abstract void Handle(T t);
};
public class Decorator1<T> : Decorator<T>
where T : stringCommand
{
private ICommandHandler<T> _handler;
public Decorator1(ICommandHandler<T> handler)
{
_handler = handler;
}
public override void Handle(T t)
{
t.s += "Decorator1;";
_handler.Handle(t);
}
}
public class Decorator2<T> : Decorator<T>
where T : stringCommand
{
private ICommandHandler<T> _handler;
public Decorator2(ICommandHandler<T> handler)
{
_handler = handler;
}
public override void Handle(T t)
{
t.s += "Decorator2;";
_handler.Handle(t);
}
}
public class Decorator3<T> : Decorator<T>
where T : stringCommand
{
private ICommandHandler<T> _handler;
public Decorator3(ICommandHandler<T> handler)
{
_handler = handler;
}
public override void Handle(T t)
{
t.s += "Decorator3;";
_handler.Handle(t);
}
}
public class implementation : ICommandHandler<stringCommand>
{
public void Handle(stringCommand t)
{
t.s += "implementation;";
}
}
Why exactly is this happening, is this a feature of windsor that i am not aware of? Is there perhaps a different way to achieve the same effect? (without resorting to reflection)
When windsor tries to resolve a component it will first try to resolve the more specific interface. So when you register Component.For it will prefer to resolve this over an open generic type.
If the same interface is registered multiple times, it will use the first one specified.
So if you don't uncommment the line your application will resolve implementation since this is the most specific component.
If you do uncomment the line decorator1 will be resolved and indeed the magic starts. The decorator will now start looking for the first registered component that satisfies it's constructor, in this case that would be decorator1 again (you did notice that your output show decorator1 2 times ?). Which will the resolve the next registered component and so on till it comes to the actual implementation.
So the only thing I can think about is not registering decorator1 as an open generic but as a specific type.
Kind regards,
Marwijn.
Consider the following example:
public interface ITask
{
void Execute();
}
public class LoggingTaskRunner : ITask
{
private readonly ITask _taskToDecorate;
private readonly MessageBuffer _messageBuffer;
public LoggingTaskRunner(ITask taskToDecorate, MessageBuffer messageBuffer)
{
_taskToDecorate = taskToDecorate;
_messageBuffer = messageBuffer;
}
public void Execute()
{
_taskToDecorate.Execute();
Log(_messageBuffer);
}
private void Log(MessageBuffer messageBuffer)
{}
}
public class TaskRunner : ITask
{
public TaskRunner(MessageBuffer messageBuffer)
{
}
public void Execute()
{
}
}
public class MessageBuffer
{
}
public class Configuration
{
public void Configure()
{
IWindsorContainer container = null;
container.Register(
Component.For<MessageBuffer>()
.LifeStyle.Transient);
container.Register(
Component.For<ITask>()
.ImplementedBy<LoggingTaskRunner>()
.ServiceOverrides(ServiceOverride.ForKey("taskToDecorate").Eq("task.to.decorate")));
container.Register(
Component.For<ITask>()
.ImplementedBy<TaskRunner>()
.Named("task.to.decorate"));
}
}
How can I make Windsor instantiate the "shared" transient component so that both "Decorator" and "Decorated" gets the same instance?
Edit: since the design is being critiqued I am posting something closer to what is being done in the app. Maybe someone can suggest a better solution (if sharing the transient resource between a logger and the true task is considered a bad design)
Edit2: Castle3 has added support for this (http://docs.castleproject.org/Windsor.Whats-New-In-Windsor-3.ashx) by introducing the "Bound" lifestyle
'Transient' explicitly means 'non-shared', so what you are asking is conceptually the wrong thing to do. The correct solution is to register Shared as a Singleton instead of Transient:
container.Register(Component.For<Shared>());
(Singleton is the default lifetime in Windsor.)
However, I suspect that behind the stated question lies a much more complex problem. I'm guessing that you need Shared to be Transient because you need it with this lifestyle for a lot of other cases, but exactly when it comes to the relationship between Decorator and Decorated you need to share them.
I still think this sounds like a Design Smell, but there are at least two ways you can achieve this result.
The first option involves prematurely resolving Shared and explicitly supply the resolved instance to the configuration of the two IFoo registrations:
container.Register(Component.For<Shared>().LifeStyle.Transient);
var r = container.Resolve<Shared>();
container.Register(Component
.For<IFoo>()
.ImplementedBy<Decorator>()
.DependsOn(new { resource = r }));
container.Register(Component
.For<IFoo>()
.ImplementedBy<Decorated>()
.DependsOn(new { resource = r }));
The second option is to make a specialized, named registration for Shared that is used only by the IFoo registrations:
container.Register(Component.For<Shared>().LifeStyle.Transient);
container.Register(Component.For<Shared>().Named("shared"));
container.Register(Component
.For<IFoo>()
.ImplementedBy<Decorator>()
.ServiceOverrides(new { resource = "shared" }));
container.Register(Component
.For<IFoo>()
.ImplementedBy<Decorated>()
.ServiceOverrides(new { resource = "shared" }));