With each new version of .net framework Microsoft tries to add some new elements to the language, which in theory should improve the possibilities of language and comfort of the software developer. In .net 4.0 new keyword – [mark]dynamic[/mark] – has been introduced. This type enables the operations that will be resolved at run time. It means that we can use any name with dynamic object and compiler will not show any error during compilation – even if there is no method with used signature. The error will occur when the running application will not find used method.
Let’s back to code review… I thought that I have seen many weird things in code. But it seems that creativeness of software developers does not know limits. Last time I have found the following code.
There is nothing special on beginning. Code provides read only property, which was defined in interface:
interface IReadOnlyFoo { int SomeValue { get; } }
There was also a method using this object which implements this interface as an argument:
public void DoSomething(IReadOnlyFoo obj) { ... }
Till now everything looks normal. In most cases I would not look into DoSomething method. I would just use it. But last time I have that felling – it was saying: You should check this! Something is wrong! And I looked deeper to this method and I have found following code:
public void DoSomething(IReadOnlyFoo obj) { ((dynamic)obj).SomeValue = 10; }
Hmmmm… Surprise! In language with strong type control, I say that value of property will not be changed according to the method signature and in the same time I try to get to the object by using very sophisticated and brutal constructions that can guaranty only one thing – the compiler will not threat this construction as an error. What is more important, together with those construction we should be aware about great risk. It is high possible that when we will do some refactoring in IReadOnlyFoo interface we will cause serious error that will be revealed by user who will use our application.
I wonder what we can do with such situation. Maybe Microsoft could add to new version of language mechanism that allows defining list of key words that should not be used in project. And then each usage of one word from list should be approved by other team members.
Please let me know if you have better solution for this issue?
W idealnym przypadku taki kod powinien zostać wychwycony podczas code review przez innego/innych programistów. Prawie na pewno ten kod nie musiał powstać, a wartość ’10’ być może udałoby się ustawić gdzieś wyżej podczas tworzenia obiektu IReadOnlyFoo, a jeśli jego konstrukcja lub metody (prywatne) na to nie pozwalają to jest coś nie tak w samym design skoro widać że istnieje potrzeba wykonania takiej operacji. Ale skoro nie było czasu na code review także pewnie i programistę czas naglił, że takie coś stworzyć raczył 🙂 Co do proponowanych zmian to nie jest to kwestia zmian w samym języku (specyfikacji), ewentualnie kompilatora czy innych narzędzi. Np w jednej z przyszłych wersji C# lub RoslynCTP (obecnie nie ma jeszcze obsługi dynamic ale być ten konkretny przypadek da się zrobić inaczej) będzie można napisać coś co wyrzuci warning w takim przypadku (error chyba się nie da), a jeśli sam warning nie odstrasza wystarczająco to build process powinien zablokować taki commit. Nie wiem czy jakieś istniejące narzędzia do statycznej analizy kodu już czegoś podobnego nie umożliwiają. Co do samych dynamic to oprócz celów do jakich zostały stworzone są nader często wykorzystywane właśnie przy różnego typu obejściach i wcale nie musi to być złe. Np ostatnio w projekcie w przypadku dość dużego zasobu zaszłego kodu, w którym performance nie jest priorytetem a reflection jest na porządku dziennym zdecydowałem się na użycie dynamic w parametrze metody. Inaczej musiałbym zryć architekturę kilkoma dodatkowymi interfejsami wprowadzonymi tylko w tym celu. Ale nawet i tego nie mogłem zrobić bo na tyle to mąciło design że wprowadzało circular reference. Użycie dynamic w tym przypadku dodatkowo zabezpieczone zostało kilkoma unit testami. Natomiast workarround z Twojego przypadku na który się natknąłeś jest rzeczywiście przegięciem:)
jakby nie było dynamic, to pewnie kreatywny programista wykorzystał by reflection. A samo dynamic jest z powodzeniem wykorzystywane w ASP do np. ViewBag.
Jest jeszcze jedna opcja -- rzutowanie. Może być ono zrobione na inną klasę lub interfejs. Taka konstrukcja też będzie dziwna, ale przynajmniej będzie zapewniona kontrola typów.
The code you have provided shows that:
1. Code was not tested
2. Code was not covered with unit tests
3. There was no code review by a more experienced person
Dynamic keyword is a powerful tool but you have to know how and when to use it.
The example you provided isn’t caused by the presence of that keyword.
You can write many stupid things that will break only at run-time even with old-school .NET
Language isn’t a problem here. People are the problem.
The people – I completely agree that this is the main reason of this issue.
All three reasons that you have pointed are true for the project from which is this example.
I think that most important solution for finding that strange constructions is code review. And in many times there is no budget for such activities…