Ayende @ Rahien

Hi!
My name is Oren Eini
Founder of Hibernating Rhinos LTD and RavenDB.
You can reach me by phone or email:

ayende@ayende.com

+972 52-548-6969

, @ Q c

Posts: 6,124 | Comments: 45,483

filter by tags archive

Ayende's Design Guidelines: Rule #1

time to read 1 min | 167 words

When creating a generic method, strongly prefer to supply an overload that is not generic, can accept the types manually, and is externally visible.

Reasoning: The generic version often looks significantly better than the non generic version, but it comes with a cost. It assumes that you know, up front, what the types are. When you are writing any type of generic code, this is almost always not the case and your generic method is useless in that scenario.

Example: myContainer.RegisterComponent<IService, ServiceImpl>(); is a good syntax to have, but the problem with that is that it cannot be used with this code:

foreach(Type type in GetComponentTypes())
{
    myContainer.RegisterComponent<type.GetInterfaces()[0], type>();
}

Since we cannot use the generic overload, we need to resort to trickery such as MakeGenericMethod and friends. This is costly at runtime, obscure and generally make life harder all around.


Comments

Symon Rottem

I completely agree - this is something I've run into a few times and providing an API without non-generic alternatives just generates friction for the consumer.

Christopher Bennage

I guess the context here is when you are publishing an API?

In a project where I control and consume the code base, it's YAGNI.

Ayende Rahien

Yes, this is for published API.

If you control the code, it doesn't really matter, since you can always change that.

Nevertheless, you need to carefully consider what you believe a published API is

Andrey Shchekin

Exactly. http://api.castleproject.org/html/MCastleMicroKernelDefaultKernelResolveServices1.htm immediatelly comes to mind.

Andrey Shchekin

Exactly. http://api.castleproject.org/html/MCastleMicroKernelDefaultKernelResolveServices1.htm immediatelly comes to mind.

Francois Tanguay

That's why I wished there was a way to promote a type object into a generic scope:

foreach(Type type in GetComponentTypes())

{

// New using scope keyword!

using<TInterface with type.GetInterfaces()[0], T with type>()

{ 

  myContainer.RegisterComponent<TInterface, T>(); 

}

}

Comment preview

Comments have been closed on this topic.

FUTURE POSTS

  1. RavenDB 3.5 whirl wind tour: I’ll find who is taking my I/O bandwidth and they SHALL pay - 7 hours from now
  2. The design of RavenDB 4.0: Physically segregating collections - about one day from now
  3. RavenDB 3.5 Whirlwind tour: I need to be free to explore my data - 2 days from now
  4. RavenDB 3.5 whirl wind tour: I'll have the 3+1 goodies to go, please - 5 days from now
  5. The design of RavenDB 4.0: Voron has a one track mind - 6 days from now

And 12 more posts are pending...

There are posts all the way to May 30, 2016

RECENT SERIES

  1. RavenDB 3.5 whirl wind tour (14):
    02 May 2016 - You want all the data, you can’t handle all the data
  2. The design of RavenDB 4.0 (13):
    03 May 2016 - Making Lucene reliable
  3. Tasks for the new comer (2):
    15 Apr 2016 - Quartz.NET with RavenDB
  4. Code through the looking glass (5):
    18 Mar 2016 - And a linear search to rule them
  5. Find the bug (8):
    29 Feb 2016 - When you can't rely on your own identity
View all series

Syndication

Main feed Feed Stats
Comments feed   Comments Feed Stats