Sometimes, the human mind acts in mysterious ways

What follows is quite embarrassing actually. Yesterday, I was reviewing my own code and optimizing it a bit, looking for ways to make it even more generic, adding more constructors for ease of use, you know the whole 9 yards. In the O/R mapping layer which is targeted by the generated code of LLBLGen Pro, the application I've been working on for the last 5 months, I use a dynamic query engine (DQE). This DQE is specific for each database vendor so you have a special DQE for SqlServer, one for Access etc. The DQE constructs query objects which contain a command object, the parameters and all other necessary objects and data to get the query executed. All methods are static.

"Oh!", my mind sighted. "It is a generic piece of code, and to enforce a common interface of methods, we should define such an interface!". I wrote the SqlServer DQE code, which I was looking at, five weeks ago if not more, so the suggestion of my mind wasn't that bad indeed, but I was immediately wondering why I hadn't done it already. I defined the interface but as I soon found out, static members can't be part of an interface. My mind was outraged. "Why is this!", it fumed. "How am I suppose to enforce a given interface onto developers of DQE's, if I can't define such an interface in the first place!".

I had to agree with my mind this time. It was kind of odd, the only way to enforce an interface on developers was by defining that interface and now I couldn't. My mind was still calling the C# language designers all kinds of names and not in the mood for any reasoning so I decided to hop into a thread in the C# newsgroup which was about that same subject: static methods in interfaces and why you couldn't define them in interfaces.

The C# newsgroup has some 'regulars' and one of them is Jon Skeet, who also knows a lot about Java. He simply said "But the only way you can call these methods is by reflection anyway!". I thought... wait a minute. "MIND! Come here!", I cried. With its tale between its legs and an ashamed look in its three green eyes, my mind shambled towards me. "Why didn't you think of that and stopped me before I made a fool of myself on usenet?" It didn't answer. All it could produce were soft mumbled sounds.

Yeah, why didn't I think of that? How are you suppose to call a static method on an interface if you use that interface, say IFoo, to make your code be able to handle multiple implementations? You can't. It's illogical to call IFoo.Method(), because which implementation of IFoo do you mean?

It's a weird thing, the human mind. It makes you stare at material you have to work with for hours in a row without noticing the reason why you keep on wondering: "Why isn't this possible?".

10 Comments

  • Good story Frans! If it makes you feel better, I have also wanted to gather a couple of static functions under a contract and realized that it wasn't possible. I also felt somewhat "ashamed" afterwards, but what the heck, it's not the end of the world.


    :-)





    So, what solution did you choose? Skipping the interface or skipping static?





    Best Regards,


    Jimmy


    ###

  • lol, this really sounds Familiar to me....

  • Frans, you seriously disappointed me ;) No clue what methodology you use, but eXtreme Programming (XP) would have trapped that issue probably in the first iteration. Start prototyping dude!

  • :)


    I skipped the interface. The static methods are really handy, since they're one shot calls, so having an object for just 1 call is not that handy. :)

  • Paul hehe I'm not gonna bite! am NOT! :D :)

  • Hehe, wasn’t my intention… just a little teaser ;)

  • Your implementation SCREAMS Factory Pattern. It's what I use in GenX.NET when I deal with my OutputProviders without needing to know which provider I am using. I'm going to be writing a Factory Pattern tutorial sometime early next week, after I RTM GenX.NET 3.0. Until then, don't scrap your code.... you're just missing one more piece to the puzzle.





    Any BTW, you didn't make a fool out of yourself. It can be done.

  • Also, I know this method would be perfect because GenX.NET uses it for the exact same reason... specific implementations for specific databases. Believe me, understanding this method will take your coding to a whole new level.

  • Robert, I do use a lot of factories, I have the GoF book. :) In my DAO objects (using the DAO pattern) I simply want to call IActionQuery query = DynamicQueryEngine.CreateInsertQuery(//...);





    Which one is based on the using directive at the top. This is generated code, so I only have to change 1 line to make it work with Oracle f.e. and the generator generates Oracle code. I understand that when I create the DAO in the DAO factory I can also create the right DQE object and pass it to the DAO, but that's not that efficient because these DAO objects are not living very long. A static method is then more appropriate. Admitted, it can be done using a factory, but a static method in this case is more efficient I think. It's not a big deal, the templates used for the code are closely related to the DQE and the database driver used, so it's a complete package, but I was just wondering if I could create an interface for this, but I couldn't. :)

  • Robert: I don't have a central cache system where I can store generic objects, so I can't cache these kind of objects like the DQE. If I could, I definitely would have used the factory route. But now I can't. Image that when I load 2000 customer objects in memory. Then I have 2000 times created the DQE. That's pretty amazingly inefficient :)





    But I appreciate your thoughts. You definitely understand what's required for good OO software :)

Comments have been disabled for this content.