Creating an interface for my objects...

Creating an interface for my objects...

Old forum URL: forums.lhotka.net/forums/t/8398.aspx


ballistic posted on Thursday, January 21, 2010

I'm new to C#, but not CSLA.  I am working on a new MVC project and would like to do it the "right" way, which means I need to create interefaces.

I would like to create an interface that my objects would need to implement.  Creating the properties was not a problem, however, when I try to add the Data Portal methods, I keep getting errors.

For instance when I add the following to my interface:
void DataPortal_Insert()

Then try to implement in my concrete class:
protected override void DataPortal_Insert()

I get the error saying that the method cannot be protected.  I would like to keep it protected.  Is there any way to do this?

Or what is the best way to create interfaces for the Data Portal methods?

Thank you,

 - Andy

RockfordLhotka replied on Thursday, January 21, 2010

You can't really create an interface for the DataPortal_XYZ methods, as they are not public.

The reason they aren't public is that they can't be called by UI code. Typical test code takes the place of UI code, and so shouldn't be able to call those methods either.

The only way to call those methods is through the data portal. If you tried to call them directly, you wouldn't be in the same context as you would be when they were invoked via the data portal, which would make your test invalid to start with.

If you want to have a testable DAL, which is a fine idea, then you should use one of the external DAL techniques discussed in Chapter 18 and in both the Silverlight and Core video series. The video series both include code samples showing external DAL implementations.

But even with an external DAL implementation you don't want or need to invoke the DataPortal_XYZ methods. Instead, one of the models has the DP_XYZ methods invoke the DAL - and so you build tests that takes the place of the DP_XYZ methods when invoking the DAL - thus cleanly testing the DAL itself.

ballistic replied on Friday, January 22, 2010

Rocky,

That makes sense.

Basically, what I wanted to do was to for any class that implemented the interface to implement an Insert and Update. 

Since Insert and Update are never directly called (I cannot create a factory method that calls Insert or Update) and instead rely on Save() to determine which Data Portal method to call, I wanted to somehow force them to define both Insert and Update.

Forcing them to implement Get methods is not a problem, since I just define the static factory method in the interface.

RockfordLhotka replied on Friday, January 22, 2010

One good solution is to create a mock DAL. That allows you to create tests at the top level that do create/fetch/save operations to test create/fetch/insert/update/delete - all very fast and against known mock data.

I talk about this at a high level in Chapter 18, and explicitly (with examples) in the Core 3.8 video series.

ballistic replied on Friday, January 22, 2010

I am now working on defining the Get methods in the interface which my concrete methods will implement and am encountering a problem.

In my interface I want to define the get method:
public interface IMemberRegistration
    {
        IMemberRegistration GetRegistration(int id);
    }

And in the concrete class I have the definition:
    [Serializable]
    class MemberRegistration : BusinessBase<MemberRegistration>, IMemberRegistration
    {
        public static IMemberRegistration GetRegistration(int id)
        {
            return DataPortal.Fetch<MemberRegistration>(new SingleCriteria<MemberRegistration, int>(id));
        }
    }

However, since my GetRegistration is static, the compiler says it can't be used to implement the interface.  Is there any way to do this?

Also, I'm not really sure that my concrete class is calling the correct base class and implementation. Nor am I sure if the return type of the GetRegistration method is correct.

 - Andres

RockfordLhotka replied on Friday, January 22, 2010

No, you can't define static members in an interface, that's not allowed in C# (or VB).

If you really want to be able to test the factory methods through an interface you'll need to create a separate factory class to contain them as instance methods. That's perfectly fine, I just fine that it makes the overall object API less intuitive.

But testibility requires compromise - often increased complexity and more code - just make sure you get enough value from the testing to offset the increased costs.

ballistic replied on Monday, January 25, 2010

Rocky,

You are right, I will need to create a separate factory class which would implement the interface.  I have always liked being able to create the static factory methods within my business objects.  This new approach will require me to think more of where my methods are located.

This is the first time I do set up a project so it can be tested.  Sure hope the returns are worth the added complexity :)

Thanks for your help,

 - Andy

Copyright (c) Marimer LLC