Sunday, December 22, 2013

Const vs Readonly Static / Named and Optional Arguments (.NET)




What is common in constants and named parameters?

1. Const vs Readonly Static 
What is better to use DebitorNumberConst or DebitorNumberStatic?

public class SomeClass{

   public const string DebitorNumberConst = "0000123";
   
   public readonly static string DebitorNumberStatic = "0000123";
}

The difference is that usage
// use constant
Console.Writeline(SomeClass.DebitorNumberConst);
// use static
Console.Writeline(SomeClass.DebitorNumberStatic);
will be compiled to
// use constant
Console.Writeline("0000123");
// use static
Console.Writeline(SomeClass.DebitorNumberStatic);

Constant is just burned into DLL, while static variable is a reference to string. And so what? This is very bad sign if public constant is referenced from another library. In all referenced libraries constant will be burned too. And to update program in case of changing the constant now we need recompile all libraries that has reference to the constant. And users should download all this libraries for the case of an update.

Rule of thumb: Mostly use Static Readonly fields,  and Constants for private or internal fields.

2. Named and Optional Arguments 
In .NET 4 there appeared so called named and default arguments
public void Method(string first = "Default Value", int second = "-1"){...}
And now there are several variants to call the method:
Method(); // first = "Default Value", second = "-1"
Method(second: 5); // first = "Default Value", second = "5"
...
The problem is the same: calling named argument Method(second: 5) is burned inside DLL. If someone  will rename second -> newArg and do not recompile referenced DLLs there will be exception.

Old libraries historically has methods with lots of parameters that are not usually called (WinAPI, COM), for example, previous converter in MS Office:
range.ConvertToTable(ref separator, ref missing, ref missing,
    ref missing, ref missing, ref missing, ref missing,
    ref missing, ref missing, ref missing, ref missing,
    ref missing, ref missing, ref missing, ref missing,
    ref missing);
And now with new version with optional parameters we can write
range.ConvertToTable(Separator: ",");

And this is the real reason why named and optional parameters were introduced in .NET!

Rule of thumb: Do not use named and optional parameters if there is no need in support for old libraries with endless parameters; or if you sure that recompiling all libraries for small change will not hurt you clients/products.

On the other hand named parameters can be very useful for reading:

MakeMyDay(true, true, 5);

What does it really mean? :)
With name arguments it can be clarified:

MakeMyDay(isFunny: true, isCoding: true, partyHours: 5);

Sunday, December 15, 2013

IQueryable drawbacks (Repository pattern, OData)


Developers, developers, developers have new crazy idea "to publish data in IQueryable interface".

I For example, to provide IQueryable with WCF Data Service

public class MyWcfDataService : DataService<MyEfModel>
{
   [WebGet(ResponseFormat = WebMessageFormat.Json)]
   public IQueryable<GetMyListEF> GetMyList()
   {
       using (MyEfModel context = this.CurrentDataSource)
       {
           return context.GetMyListEF().ToList().AsQueryable();
       }
   }
}
(example from one of the hundreds common posts in the internet)

At first, what if context.GetMyListEF() will return millions of rows? All of them will be send to the client. Is client expect such thing?

Second point will be a bad nature of the IQueryable in real life. Currently nobody can provide full implementation of this interface. Even Entity Framework with modern sql providers does not have ideal implementation of the interface. There lots of exceptions of impossibility to convert to T-SQL code. Or with success we have bad performance (the reason stackoverflow.com choose Micro ORM dapper).

If some provide IQueryable<T> interface then clients expect full implementation of it. Not partial, FULL!


II Next example is widely using our lovely interface in Repository pattern, usually it looks like

public class MyRepository<T> : IRepository<T>
{
   public IQueryable<T> GetModels()
   {
       // implementation
   }
}

- What is the purpose of abstracting Repository?
- To make it possible exchange in future with another implementation
- Can you make NoSql storage or File storage using in future instead of MS SQL?
- No! Querable providers are very complex to create for such storages.


III Same problem with OData, that is pushing by Microsoft.
With OData users can query data by passing parameters in URI, for example,
http://services.odata.org/OData/OData.svc/Category(1)/Products?$top=2&$orderby=name

The idea is great, but, but, but
"Users like cheating only if it is a focus!"

If you take Sharepoint services with OData you will find the same problem. The service just cannot provide all possible ways of using it. Users will be restricted to the platform in their heads, instead of be lucky with interface features.


P.S. Better use what users expect to get from your services (IEnumerable<T> in most cases).

Resources:
IQueryable is Tight Coupling by Mark Seemann