Why no static interfaces?

G

Guest

In C#, an interface cannot mark any method as static. i'm told the ILASM
supports it but i've never tested that

Two questions. First, why? OK, i've heard the reason about interfaces being
allocated on the stack but that's not a real reason. Which is OK because this
isn't a real question, it's just a complaint dressed up to look like a reason

Second question. If a language doesn't support a fairly obvious feature, one
has to wonder if perhaps what one is trying to do is stupid. As in, if my
code benefits from a static interface member maybe i've created a bad design.
So i'll describe what i'm doing and why i want a static method and anyone
curious enough to read it all can tell me what i should be doing instead

We're using a pretty typical request/response architecture. One party fills
out a request, the other party processes it. It's the software equivalent of
any time you've ever had to fill out a work order or fill up a shopping cart,
with you spending some time building a comprehensive, atomic request and when
you're all done someone (school, carpenter, checkout guy, etc.) processes it
all in a single, atomic, stateless transaction. You've seen it a billion
times in transaction processors, Web Services, other services (e.g., calls to
credit scoring companies or credit card companies), booking airline tickets,
processing home loans, etc.

So here's an example of how we're using it. A person sits down with an
ASP.NET page and wants to edit a bunch of data about a person. They type in
an ID or a name or something and hit Search. In this example, the UI builds a
SearchRequest and passes it to the UserManager. UserManager does whatever it
does and returns the data. SearchManager is done now - he is stateless
(relative to you) and works only on atomic operations. The user and the
ASP.NET page then change all the data, using a bunch of objects and whatnot
to do so. The user finishes and presses the Save button. When this happens,
all the changes are packed up into a ChangeRequest and sent, once again, to
the UserManager. The UserManager does whatever it does, calling however many
data sources and downstream systems it needs to call, and returns a status
(in our case, a status object, but that's not important here)

So our system has lots of objects but the actual persisting of data is
handled by stateless, atomic transaction managers (RequestProcessors)

We do not allow the UI to talk directly to the manager(s). Instead, they
have to go through a factory of sorts which checks the user's credentials and
returns an interface tailored to the user's security rights and business
process. Behind that interface is one of the manager objects. Some of the
manager objects implement multiple interfaces, but you don't know that, all
you know is that you have an interface tailored to your task. And if we
switch which manager implements your interface or which interfaces a manager
implements, you don't know and don't get affected

So our objects might look something like this:

public UserFactory {
IUserView UserViewManager;
IUserUpdate UserUpdateManager;
}

public IUserUpdate {
Update(UserChangeRequest changeRequest);
Validate(UserChangeRequest changeRequest);
}

internal UserManager : UserUpdateManager {
public Update(UserChangeRequest changeRequest);
public Validate(UserChangeRequest changeRequest);
}

User.aspx.cs {
UserChangeRequest changeRequest = BuildChangeRequest();
ValidationResult result =
UserFactory.UserUpdateManager.Update(changeRequest);
}

OK, hopefully it's made sense so far. Here's where we get to the static
stuff. The manager classes are stateless and atomic. There is no reason that
they should ever be explicitly instantiated. Maybe if internally it was
caching stuff, but for the most part everything it does can (and i think
should) be static

However, none of the methods on the manager can be static because - and only
because - it uses interfaces. If the user called the manager directly (and
assuming they knew which one to call and we didn't change it on them and we
made all their methods public rather than selectively hiding them based on
roles), all the methods could be static. But because we use interfaces, none
of the methods can be static because a method defined in an interface cannot
be defined as static

i've heard the argument that an interface is just a contract and shouldn't
have to know implementation details. Which would be fine if the object
implementing the interface were allowed to add the static keyword to the
method. After all, it has absolutely no impact on the interface or the
contract it represents. But you can't do that meaning that interfaces aren't
just a contract, it's an implementation specification too, in this case
telling me i am not allowed to use static methods. i can (and have to) add
the keyword "public" when implementing the interface methods, i don't see why
i shouldn't be allowed to add "static" as well

Anyway, the question was, since i have a real (if small) benefit to using
interfaces with static methods and since that's not allowed, is there
something horribly wrong with my design? Is there something obvious i should
be doing different?

The one thing that leaps to mind is replacing the interfaces with facades.
That gives me a little better protection against change than the interfaces
since i can split delegation (right now all methods in an interface must be
implemented by the Manager). Another is that i dump the interfaces altogether
and make the manager objects facades (if need be). In either case, i suppose
i wouldn't need the factory since a facade factory seems kind of silly (a
facade using a factory, however...). Using interfaces is less work than
either, however, and is not exactly uncommon where factories are concerned

Ideas?
 
G

Gonzalo Rodriguez

Hi, I am sorry if I didn't understand the idea but I think that the static
method is also called class method, so in your example you want to use
samething like this:

....
public UserFactory {
IUserView UserViewManager;
IUserUpdate UserUpdateManager;
}
...
...
User.aspx.cs {
UserChangeRequest changeRequest = BuildChangeRequest();

// Calling a static method defined in the interfase
ValidationResult result =
UserFactory.IUserUpdateManager.Update(changeRequest);

// this is your original sentence
// ValidationResult result =
// UserFactory.UserUpdateManager.Update(changeRequest);

}

I think that the CLR has no way to know which is the class that implements
the IUserUpdateManager static method, so you need a class (such as it is
implemented in the factory method design pattern you used).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top