Using interfaces is a very easy way to remove dependencies, but what happens when one of your classes needs a method not defined by the interface? If you're using constructor injection or a factory, how do you access that extra method without casting? Is this possible?
Here is an example of a factory with this problem. Am I trying to do something impossible? Thanks for your help.
interface IFoo {
int X { get; set; }
int Y { get; set; }
}
public class A : IFoo {
int X { get; set; }
int Y { get; set; }
}
public class B : IFoo {
int X { get; set; }
int Y { get; set; }
int Z { get; set; }
}
public static class FooFactory {
public static IFoo GetFoo(string AorB) {
IFoo result = null;
switch (AorB) {
case "A":
result = new A();
break;
case "B":
result = new B();
break;
}
return result;
}
}
public class FooContainer {
private IFoo foo;
public FooContainer(IFoo foo) {
this.foo = foo;
}
/* What methods would you define here. I'm new to IoC. */
}
public class Main(...) {
int x,y,z;
IFoo fooA = FooFactory.GetFoo("A");
x = foo.X;
y = foo.Y;
IFoo fooB = FooFactory.GetFoo("B");
x = foo.X;
y = foo.Y;
z = foo.Z; /* Does not compile */
z = ((B)foo).Z; /* Compiles, but adds unwanted dependency */
}
You do indeed need to cast. This is normal, and sometimes necessary. It is usually a sign that something is wrong though.
The ideal is that if a method/routine takes/returns an interface, then your logic only cares about the members exposed by that interface. If inside that method you find yourself checking the exact type so that you can cast to that type and call different members depending on the type, then something probably be wrong.
Let's say you have an IContact interface, and some of your entities that implement this are your classes Customer, Purchaser, and Contractor. If you have a SendChristmasCard method that takes IContact, it should only care about the IContact members. If you have logic inside this method that is doing a select Case on the obj.GetType().ToString to find out if it's a Customer or not, then:
That functionality should probably be over in the Customer-centric side of your code base, taking a Customer object as a parameter. (In your example, there would be separate logic for acting upon class A and class B.)
IContact should define common members that your SendChristmasCard method would call, and be completely ignorant of the logic that goes on inside the particular object. Each class that implements IContact would implement these member differently. (In your example, class A would also implement property B, but it wouldn't do anything with it.)
In the case where a method returns an interface and you use the object, the above still applies but in my experience it can, now and then, be best to put up with the casting. The complication you add by "fixing" the situation might make it more complicated. I would say that the further up and non-standard the logic is, just take the simple way out. SendChristmasCard is obviously not core functionality; and if an IContact factory method is only handy method that gives you All the contacts, then maybe just use that, pass it to SendChristmassCard(IContact Contact), and inside there check for the type to say "it was great buying from you this year" or "it was great selling to you this year" etc. But if this is core logic in your system, you really need to look for a better way.
Check out the Decorator Pattern though, which can help in situations like this.
When you encounter the need to downcast an object, it is usually a sign that the API could be better.
Downcasting an abstract type is a violation of the Liskov Substitution Principle. It can usually best be addressed by changing the style of the interface in question. Instead of exposing a lot of properties and queries (in CQS terminology), reverse the focus towards a more command-oriented approach. This is the Hollywood Principle.
Instead of having IFoo expose the X and Y properties, you may be able to redefine its behavior towards a set of commands:
public interface IFoo
{
void DoStuff();
void DoSomethingElse(string bar);
void DoIt(DateTime now);
}
Concrete implementations can then encapsulate whatever data they would like (such as X, Y or Z properties) without the consumer needing to know about them.
When the interface grows to become too big, it's time to apply the Interface Segregation Principle or the Single Responsibility Principle.
If you're trying to access a method that isn't available to the interface, then don't use the Factory. You're obviously hard coding a dependency...so just go with it (but only if it's really necessary).
No need to over-complicate things.
Trying to cast back to an Object type rather than the interface is going to introduce a dependency...but it's going to hide it rather than obviously expose the dependency. If somebody changes the Factory in the future and your call returns a different Object type, your code is now going to break in a non-obvious way.
Related
I have 4 different SQL databases that hold similar data; they’re all based off the same model. They differ according to version of the data, where they're being used, etc.
Db1Context
Db2Context
Db3Context
Db4Context
Upon initialization, I need to make sure each of the databases have a single parent record, so I run a method that looks something like this:
Sub EnsureATableExists()
Dim theDb = New Db1Context
Dim parentTable = theDb.parentTables.Where(Function(x) x.somedata = "somedata").FirstOrDefault()
If parentTable Is Nothing Then
parentTable = CreateTable()
theDb.parentTables.Add(parentTable)
theDb.SaveChanges()
End If
End Sub
But I currently have 4 of these methods which offends my sense of DRY. But I don’t how to write this method for reuse because the declaration of a DbContext is unique and I can’t really parametrize the DbContext to hand in.
I assume there is some common technique for coding this and would appreciate being taught.
Additional code added per comment below:
This is my current context. It is repeated 3 more times with the different names like listed above and respective connection strings.
I converted my vb.net to C# and believe I'll be able to convert any examples provided back into vb.net.
public class Db1Context : DbContext
{
public Db1Context() : base("Db1Connection")
{
}
public Db1Context (string connectionString) : base(connectionString)
{
}
public DbSet<Table1> Table1s { get; set; }
public DbSet<Table2> Table2s { get; set; }
}
How would I define a class to be inherited where I can define a new connection string, and what would the new Db1-Db4 contexts look like as they inherit?
I am attempting to create Web API controller in F# which returns objects from Entity Framework. SharpObject and SharpContext are my object and DbContext respectively defined in a c# project.
/// Retrieves values.
[<RoutePrefix("api2/values")>]
type ValuesController() =
inherit ApiController()
let values = [| "value1"; "value2" |]
/// Gets all values.
[<Route("")>]
member x.Get() : IEnumerable<SharpObject> =
use context = new SharpContext()
context.SharpObjects.ToList() :> IEnumerable<SharpObject>
Here is SharpObject with the SerializableAttribute.
[Serializable]
public class SharpObject
{
[Key]
public virtual int Id { get; set; }
public virtual string Description { get; set; }
}
The error that I am getting is this:
The type System.Data.Entity.DynamicProxies.SharpObject_3A697B5C46C0BF76858FEAFC93BFED36DD8D4CA2CEACBB178D2D3C38BB2D2052 was not expected. Use the XmlInclude or SoapInclude attribute to specify types that are not known statically.
When I de-compile this using ILSpy, it looks like this:
[Route("")]
public IEnumerable<SharpObject> Get()
{
SharpContext context = new SharpContext();
IEnumerable<SharpObject> result;
try
{
result = (IEnumerable<SharpObject>)context.SharpObjects.ToList<SharpObject>();
}
finally
{
IDisposable disposable = context as IDisposable;
if (disposable != null)
{
disposable.Dispose();
}
}
return result;
}
What is the best way to get my list to show through in f#?
This happens because the object that you get from EF is not, in fact, of type SharpObject, but rather of that scarily named type, which inherits from SharpObject. This type is called "proxy" and is dynamically generated by EF in order to provide certain services (such as lazy loading, see below).
Because your action is declared as returning IEnumerable<SharpObject>, the default WebAPI's XML serializer expects to find object of that type, and so rightly complains upon finding an object of different type.
One temporary, bandaid-style fix that you can try is to remove the virtual keywords from your entity (why do you have them there, anyway?). It is the presence of the virtual keywords that causes EF to generate the proxy type. Absent virtual, no proxy will be generated, thus making the XML serializer happy.
This, however, will not work once you extend your model to include navigation properties with lazy loading. Those properties, you must make virtual, otherwise lazy loading won't work.
So the correct fix is not to use the same type for both DB-facing DTO and client-facing DTO. Use different types.
Using the same type for these two purposes may seem "convenient" at first, but this road quickly leads to numerous problems. One of small technical problems you have already discovered. But even absent those, conceptually, you almost never, ever want to just serve up your DB records directly to the untrusted user. Some of possible consequences include security holes, badly factored UI code, badly factored database structure, performance problems, and so on.
Bad idea. Don't do it.
P.S. This doesn't actually have anything to do with F#.
I have a StructureMap config that looks something like:
cfg.For<ICacheOrder>().Use<CacheOrder>().Ctor<int>().Is(context => LoginHelper.LoginID);
cfg.For<ICacheProduct>().Use<CacheProduct>().Ctor<int>().Is(context => LoginHelper.LoginID);
cfg.For<ISQLOrder>().Use<SQLOrder>().Ctor<int>().Is(context => LoginHelper.LoginID);
cfg.For<ISQLProduct>().Use<SQLProduct>().Ctor<int>().Is(context => LoginHelper.LoginID);
Via constructor injection, a chain of objects can be created, with some needing an int LoginID that is determined at the time of creation. The static LoginHelper determines the LoginID.
Presently in my config, LoginHelper is called for every created object. Is there a way, perhaps via StructureMap's IContext, for LoginID to be "remembered" and only determined once within a chain of creation?
I know that I could refactor and create an ILogin interface/concrete that StructureMap could construct and cache - but I'd prefer my various layers to be concerned only with a simple int LoginID.
Although it's okay to inject primitive configuration values in your services, when you repetitively inject that same primitive into multiple services, you are missing an abstraction.
This is clearly the case with your configuration; you are missing an abstraction.
The solution is to let those services depend on an abstraction rather than a primitive value. For instance:
public interface ICurrentUser
{
int LoginID { get; }
}
And you can create a rather simple implementation as follows:
public class CurrentUserImpl : ICurrentUser
{
public CurrentUserImpl()
{
this.LoginID = LoginHelper.LoginID;
}
public int LoginID { get; private set; }
}
This means that you will have to change the constructors of CacheOrder, CacheProduct, SQLOrder and SQLProduct, but when you do this, your configuration gets much more maintainable:
cfg.For<ICacheOrder>().Use<CacheOrder>();
cfg.For<ICacheProduct>().Use<CacheProduct>();
cfg.For<ISQLOrder>().Use<SQLOrder>();
cfg.For<ISQLProduct>().Use<SQLProduct>();
The problem of "remembering a param literal" now goes away immediately, because we can now register the ICurrentUser as follows:
cfg.For<ICurrentUser>().Use<CurrentUserImpl>();
The default lifecycle in Structure Map is per request (per object graph) so the same instance is injected into all objects in a single object graph.
Another option is to register it using the HttpContext lifecycle, but this of course only works when running an ASP.NET web application.
Total Guice noob here, have read a few articles and seen the intro video, that's about it.
Here's my simplified old code that I'm trying to "guicifiy". Can't quite figure out how to, since (as far as I understand), I can only #inject-annotate one of the two constructors? How can a calling class create the one or the other instance? Or will I have to refactor this somehow?
public class MyDialog extends JDialog {
public MyDialog( JFrame parent, <other parameters...> ) {
super( parent );
}
public MyDialog( JDialog parent, <other parameters...>) {
super( parent );
}
}
You can only inject into the one ctor.
Depending on how this class is being used, you could:
Inject a factory into the client code with two "new" methods.
Roll all the arguments into one ctor and pass null when not required.
How can a calling class create the one or the other instance?
This suggests that the calling classes will want multiple instances of MyDialog? Then you need to use a hand-rolled factory (Assisted Inject can handle this for you if you only had one ctor). I don't know the details of what you are up to and I'm likely repeating what you already know but as a blanked statement I'd suggest also extracting an interface from MyDialog and have the factory return them. This way you can fake MyDialog in tests.
Constructor injection is very clean. mlk is right, saying that you can inject into one constructor only.
What you can do is use method injection:
public class Smt {
private int a;
private Cereal cereal;
private Personality personality;
private ignition;
public Smt() {
this.a = 5;
}
public Smt(int a) {
this.a = a;
}
#Inject
public void setup(#CiniMini Cereal cereal, #Rastafarian Personality personality,
Ignition ignition) {
this.cereal = cereal;
this.personality = personality;
this.ignition = ignition;
}
}
What Guice will do is call your class' setup class method and provide all the injections. Then you do the same thing as in the constructor--assign the objects to your class' attributes.
I agree with the previous comments.
Just an additional hint: constructor injection is supposed to provide all dependencies a class needs. As mlk says, one approach could be to annotate the constructor with most arguments and then refactor the other one to call the former by passing null values where needed.
Additionally, Guice 3.0 supports the so called Constructor Bindings which allow the programmer to specify which constructor to use. See here for more details.
I've got a Fitnesse RowFixture that returns a list of business objects. The object has a field which is a float representing a percentage between 0 and 1. The consumer of the business object will be a web page or report that comes from a designer, so the formatting of the percentage will be up to the designer rather than the business object.
It would be nicer if the page could emulate the designer when converting the number to a percentage, i.e. instead of displaying 0.5, it should display 50%. But I'd rather not pollute the business object with the display code. Is there a way to specify a format string in the RowFixture?
You certainly don't want to modify your Business Logic just to make your tests look better. Good news however, there is a way to accomplish this that is not difficult, but not as easy as passing in a format specifier.
Try to think of your Fit Fixture as a service boundary between FitNesse and your application code. You want to define a contract that doesn't necessarily have to change if the implementation details of your SUT (System Under Test) change.
Lets look at a simplified version of your Business Object:
public class BusinessObject
{
public float Percent { get; private set; }
}
Becuase of the way that a RowFixture works we need to define a simple object that will work as the contract. Ordinarily we would use an interface, but that isn't going to serve our purpose here so a simple DTO (Data Transfer Object) will suffice.
Something Like This:
public class ReturnRowDTO
{
public String Percent { get; set; }
}
Now we can define a RowFixture that will return a list of our custom DTO objects. We also need to create a way to convert BusinessObjects to ReturnRowDTOs. We end up with a Fixture that looks something like this.
public class ExampleRowFixture: fit.RowFixture
{
private ISomeService _someService;
public override object[] Query()
{
BusinessObject[] list = _someService.GetBusinessObjects();
return Array.ConvertAll(list, new Converter<BusinessObject, ReturnRowDTO>(ConvertBusinessObjectToDTO));
}
public override Type GetTargetClass()
{
return typeof (ReturnRowDTO);
}
public ReturnRowDTO ConvertBusinessObjectToDTO(BusinessObject businessObject)
{
return new ReturnRowDTO() {Percent = businessObject.Percent.ToString("%")};
}
}
You can now change your underlying BusinessObjects around without breaking your actual Fit Tests. Hope this helps.
I'm not sure what the "polution" is. Either the requirement is that your Business Object returns a value expressed as a percentage, in which case your business object should offer that -OR- you are testing the true value of the response as float, which you have now.
Trying to get fitnesse to massage the value for readability seems a bit odd.