Dynamic Run-Time object creation: Keep intellisense? - c#

Recently I have been exploring using the fancy new dynamic keyword introduced in C# 4.0 (DynamicObject, ExpandoObject etc..)
Now I can identify several uses (and several pitfalls) for the new introduction, but for the purpose of my project, and for this question - I am looking into cleaning up my late-bound string-based indexed collections to make them more safe.
So, before dynamics I had:
Car car1 = CARWarehouse1["Honda"];
And WITH dynamics I can now do (where CARWarehouse1 now extends the DynamicObjects base)
Car car1 = CARWarehouse1.Honda
This is all well and good, and from a quick glance it looks like I have achieved what I wanted.. but have I?
Because lets face it, for either method at compile time should I have mistyped my referenced car type, the compiler won't have a problem, but I will run into issues at runtime.
Therefore, what I really need is compile time property checking, and Intellisense support. So - can I do it?
I know that there are libraries out there such as Moq that have this capability, and Resharper gives some sort of support within intellisense, but I'm looking for a more rounded solution.
Any ideas, big, small, easy or complex are welcome.

Nope, no such thing for dynamic types.
Basically the compiler just skips all checks on variables marked as dynamic because there is no way to check anything. Properties on dynamic objects may be created at runtime, so the code can't be checked at compile time for accuracy.

If compile time checks and intellisense are important, don't use dynamic. If the scope of the object is pretty small you could use anonymous types instead, but I don't get the impression that's applicable to your situation. I'd suggest you just define the types you need, and stick with dictionaries and hashtables for any properties that you can't predict when coding.

Related

Why we need Reflection at all?

I was studying Reflection, I got some of it but I am not getting everything related to this concept. Why do we need Reflection? What things we couldn't achieve that we need Reflection?
There are many, many scenarios that reflection enables, but I group them primarily into two buckets.
Reflection enables us to write code that analyzes other code.
Consider for example the most basic question about an assembly: what types are in it? Assemblies are self-describing and reflection is the mechanism by which that description is surfaced to other code.
Suppose for example you wanted to write a program which took an assembly and did a graphical display of the relationships between the various classes in that assembly, to help you understand that code. There are such tools. They're in Visual Studio. Someone wrote those tools. They did not appear by magic. Reflection is the mechanism designed into the .NET framework that enables you or me or anyone else to write tools that understand code.
Reflection enables us to move compile time bindings to runtime.
Suppose you have a static method Foo.Bar(). When you put a call to Foo.Bar() in your program, you know with 100% certainty that the method you think is going to be called is actually going to be called. We call static methods "static" because the binding from the name Bar to the code that gets called can be understood statically -- that is, without running the program.
Now consider a virtual method Blah() on a base class. When you call whatever.Blah() you don't know exactly which Blah() will be called at compile time, but you know that some method Blah() with no arguments will be called on some type that is the runtime type of whatever, and that type is equal to or derived from the type which declares Blah(). (In fact you know more: you know that it is equal to or derived from the compile time type of whatever.) Virtual binding is a form of dynamic binding, but it is not fully dynamic. There's no way for the user to decide that this call should be to a different method on a different type hierarchy.
Reflection enables us to make calls that are bound entirely at runtime, based entirely on user choices if we like. We pay a performance penalty, and we lose compile-time type safety, but we gain the flexibility to decide 100% at runtime what code we call. There are scenarios where that's a reasonable tradeoff.
Reflection is such a deep part of the .NET framework that you often don't know that you're doing it (see Attributes and LINQ for instance). And when you do know you're doing it, even if it feels wrong, it might be the only way to achieve a particular objective.
Apart from the two broad areas that Eric mentioned here are a few others. There are lots more, these are just some that come to mind immediately.
Serialization (and similar)
Whether you're using XML or JSON or rolling your own, serializing objects is much easier when you don't have to write specific code for each class to enable serialization. Reflection enables you to enumerate the properties in your object that have been flagged for (or not flagged against) serailization and write them to the output.
This isn't about saving state though. Reflection allows us to write generic methods that can produce business output too, like CSV or XLSX files from an arbitrary collection. I get a lot of mileage out of my ToCSV(...) and ToExcel(...) extensions for things like producing downloadable versions of data sets on my web-based reporting.
Accessing Hidden Data
Yes, I know, this is a dodgy one. And yeah, Eric is probably going to slap me for this, but...
There's a lot of code out there - I'm looking at you, ASP.NET - that hides interesting and useful stuff behind private or protected. Sometimes the only way to get them out is to use reflection. Sometimes it's not the only way, but it can be the simpler way.
Attributes
Every time you tag an Attribute onto one of your classes, methods, etc. you are implicitly providing data that is going to be accessed through reflection. Want to use those attributes yourself? Reflection is the only way you can get at them.
LINQ and Other Expressions
This is really important stuff these days. If you've ever used LINQ to SQL, Entity Frameworks, etc. then you've used Expression in some way. You write a simple little POCO to represent a row in your database table and everything else gets handled by reflection. When you write a predicate expression the system is using the reflection model to build structures that are then processed (visited) to build an SQL statement.
Expressions aren't just for LINQ either, you do some really interesting things yourself, once you know what you're doing. I have code to generate line parsers for CSV import that run pretty damn quickly when compiled to Func<string, TRecord>. These days I tend to use a mapper somebody else wrote, but at the time I needed to slice a few more % off the total import time for a file with 20K records that was uploaded to a website periodically.
P/Invoke Marshalling
This one is a big deal behind the scenes and occasionally in the foreground too. When you want to call a Windows API function or use a native DLL, P/Invoke gives you ways to achieve this without having to mess about with building memory buffers in both directions. The marshalling methods use reflection to do translation of certain things - strings and so on being the obvious example - so that you don't have to get your hands dirty. All based on the Type object that is the foundation of reflection.
Fact is, without reflection the .NET framework wouldn't be what it is. No Attributes, no Expressions, probably a lot less interop between the languages. No automatic marshalling. No LINQ... at least in the way we often use it now.

Writing and changing code at runtime

I have a situation where I'd like to build MVC style views at runtime using their EditorFor/DisplayFor templates (or something similar).
Ideally our application would let the user choose which fields they want in their UI (so they can add /remove any as they see fit), to this end I thinking it'd be handy to be create viewmodel classess at runtime and add the various dataannotation attributes to them according to what user selects (ie. stringlength, required etc).
One thing I need to be able to support is changing of the generated classes at runtime without affecting other users or having to do a full iisreset.
To go about this I've been doing a bit of research and it seems like there might be 3 different approaches, CodeDom, RunSharp / Relfection.Emit,Roslyn.
From what I can tell reflection.Emit/Runsharp would allow me to create the classes and add attibutes and properties to them at runtime and probably also modify them when I need to without adverse effects.
I'm not sure if Roslyn would allow this, I haven't been able to track down any simple examples of creating a class with properties or attributes in it, and I've seen a few mentions that Roslyn's output is immutable so I'm not sure how that goes for allowing me to modify it at a later date without adverse effects.
In general from what I've seen most people don't recommend CodeDom so I'm not entirely sure if I should bother going down that route.
Can anyone give me an idea of which of these directions might be viable for me?
So, none of these solutions are going to work, and honestly, generating type at runtime really isn't what you want here.
When it comes to the CLR, once you have a type with fields and methods, you can't really add new members or change members at runtime. The closest we come to doing that is the edit-and-continue features in Visual Studio, we're highly restricted to what changes we can make. We often 'cheat' by not adding methods or attributes where you think they added, but we hide them somewhere else and emit IL that references this secret location when you make an edit. Crazy things like removing members is entirely unsupported. Even if it was supported, lots of code likes to presume that doing someObject.GetType().GetMembers() returns the same thing over and over again.
As far as Roslyn is concerned, when we say the results are "immutable" we don't mean that puts any requirement on any IL that you might generate with it. Rather, when you ask Roslyn to parse something or analyze source code, the objects (syntax trees, type information, etc) is immutable. Still, it doesn't matter since you can't modify types in the CLR once they exist.
I'm with svick in his comment -- this isn't what you want to do. Use some appropriate data structures to represent your information at runtime, rather than trying to think of this as a concrete class that can be mutated somehow.

How does one detect mutation in a C# function?

I've been reading articles on how to program in a functional (i.e F#) style in C#, for example, foregoing loops for recursion and always returning a copy of a value/object instead of returning the same variable with a new state.
For example, what sort of code inspection things should I watch out for? Is there any way to tell if a method on a BCL class causes a mutation?
The tool NDepend can tell you where you have side effect. It can also ensure automatically that a class is immutable (i.e no side effect on its object instances) or a method is pure (i.e no side effects during the execution of the method. Disclaimer: I am one of the developers of the tool.
In short, trick is to define an attribute, such as, MyNamespace.ImmutableAttribute
and to tag classes that you wish to be immutable.
[Immutable]class MyImmutableClass {...}
If the class is not immutable, or more likely, if one day a developer modifies it and breaks its immutability, then the following Code Rule over LINQ Query (CQLinq) will suddenly warn:
warnif count > 0
from t in Application.Types
where !t.IsImmutable && t.HasAttribute("MyNamespace.ImmutableAttribute")
select t
On a side note, I wrote an article on immutability/purity/side-effects and NDepend usage:
Immutable Types: Understand Them And Use Them
Here are two things that would help you find variables and fields whose values are getting changed. Mutability is more complex than this, of course (for example these won't find calls to add to collections) but depending on what you're looking for, they may be helpful.
Make all of your fields readonly; then they can only be set from the constructor, and not changed thereafter.
Pick up a copy of ReSharper. It expands on Visual Studio's syntax highlighting, and has an option to set up custom highlighting for mutable local variables. This will let you see at a glance whether locals are being modified.
Unfortunately there's no easy way to do that in C# currently. If you're lucky the documentation will tell you, but generally that is not the case.
Inspecting the code with Reflector (assuming we're talking managed code) can reveal if the current implementation has any side effects, but since this is an implementation detail there's no guarantee that it will not change in the future, so basically you will have to repeat the verification every time you update the code in question.
Tools such as NDepend can help you find out dependencies between types - i.e. where you have too look for side effects.
For your own types, you can implement immutability, by making sure instances never leak references to internals. Make sure to copy the contents of reference type instances used to instantiate the objects as other may otherwise keep references to internal state.
Without testing the method, you won't be able to tell if it has any side effects. It would be handy if the documentation mentioned any side effects of a method or function but unfortunately it doesn't.
Keep in mind that you will have to do some extensive testing to be certain that no side effects can occur. If you want to you can always disassemble the assembly and read the code for side effects.

What is a dynamic language, and why doesn't C# qualify?

Listening to a podcast, I heard that C# is not dynamic language while Ruby is.
What is a "dynamic language"? Does the existence of dynamic languages imply that there are static languages?
Why is C# a dynamic language and what other languages are dynamic? If C# is not dynamic, why is Microsoft pushing it strongly to the market?
As well why most of .NET programmers are going crazy over it and leaving other languages and moving to C#?
Why is Ruby "the language of the future"?
What is a dynamic language?
Whether or not a language is dynamic typically refers to the type of binding the compiler does: static or late binding.
Static binding simply means that the method (or method hierarchy for virtual methods) is bound at compile time. There may be a virtual dispatch involved at runtime but the method token is bound at compile time. If a suitable method does not exist at compile time you will receive an error.
Dynamic languages are the opposite. They do their work at runtime. They do little or no checking for the existence of methods at compile time but instead do it all at runtime.
Why is C# not a dynamic language?
C#, prior to 4.0, is a statically bound language and hence is not a dynamic language.
Why is Ruby the language of the future?
This question is based on a false premise, namely that there does exist one language that is the future of programming. There isn't such a language today because no single language is the best at doing all the different types of programming that need to be done.
For instance Ruby is a great language for a lot of different applications: web development is a popular one. I would not however write an operating system in it.
In a dynamic language, you can do this:
var something = 1;
something = "Foo";
something = {"Something", 5.5};
In other words, the type is not static. In a statically typed language, this would result in a compiler error.
Languages such as C, C++, C#, and Java are statically typed.
Languages such as Ruby, Python, and Javascript are dynamically typed.
Also, this is not the same as "strongly or weakly" typed. That is something different all together.
I'm stunning at the way c# it's embracing a fundamental set
of programming paradigms.
We can say that c# alows a rich object oriented programming,
a rich component oriented programming,
a well integrated functional programing,
a complet set of query operations over differents types of data sources (linq),
a elegant aproach of cocurrent programming through pLinq and parallel extensions,
in the next release (c# 4.0) will have powerfull dynamic capabilities,
and it's almost sure that in c# 5.0 will have a solid set of meta-programming
features.
With just can say that c# it's doing a great job of integrating all this powerfull
stuff in just one tool box. That's in my opinion it's the way it must be,
because skipping from one programming language to another it's almost always very painfull.
C# is a statically typed language, because the type of every object you're working with needs to be known at compile time. In a dynamic language you don't need to know what type an object is at compile time. Maybe you import some classes that you don't know before hand, like you import all classes in a folder, like plugins or something. Or maybe even the type of an object depends on user-interaction.
You can achieve a similar effect by using interfaces or base classes, but it's not completely the same because you are limited to using classes that explicitly inherit from or implement that interface.
In dynamically typed languages it doesn't care what the type is when you compile it, it'll try to call the method you specified by name, if that method doesn't exist on the object it'll throw a run-time exception, so it's up to the programmer to ensure that that doesn't happen or handle it appropriately. You gain flexibility, but lose out a little on compile-time error checking.
Looking at the Wikipedia entry, we see that a dynamic language is one that does things are runtime that most do at compile time. Typically, in a dynamic language, a variable could change types quickly and easily, and there typically is no separate compile step (but rather either interpreted execution or really fast compiling). C# is a more conventional language, using variable declarations and being compiled.
The Wikipedia entry lists numerous dynamic languages.
"X is the Y of the future", on the other hand, means that somebody's trying to sell you something. (Not necessarily literally, but trying to influence your beliefs in a way convenient to the speaker.)
Did you know that VB6 is both static and dynamic?
If you declare variables with a given type, then you get static behaviour:
Dim name as Label
You can now only access members of name that are Labels and intellisense knows that.
If you have a class and add the implements keyword, then your class can implement methods of another class. This is inheritance of interface that VB6 allows. You can get some runtime polymorphism.
You can also declare variables like this:
Dim proxy As Object
Now intellisense doesn't give you any help and VB6 will allow you to do anything you like with proxy:
proxy.foo()
This line can sit inside a compiled and running program and cause no offence, especially if its not run itself. Its only when the line is run does the lookup take place.
You can also perform:
set proxy = <any instance>
and this will run. It doesn't matter whether <any instance> has a foo method or not.
And then any instance of any class that does implement foo can be assigned and the method called and VB6 will be happy.
Note that there are run-time performance penalties as you become increasingly dynamic.
In C# 3.0, the types of everything needs to be known at compile-time. It's a static language. A dynamic language uses dynamic dispatch at runtime to decide the type of things and what methods to call on those things. Both types of languages have their advantages and disadvantages. C# 4.0 will add dynamic capability. Anders Hejlsberg gave a great talk on static v.s. dynamic languages and C# 4.0 at PDC.
A dynamic language is generally considered to be one that can dynamically interpret & generate code at runtime. C# can't do that.
There are also dynamically typed & statically typed languages. Dynamically typed means that the type of a variable is not set and can change throughout the program execution.
The words static and dynamic are not cleary defined.
However, what is most often meant is two issues:
1) In static languages, the type of a variable (that is, the type of value the variable can contain or point to) cannot change during the course of a program. For example in C#, you declare the type of a variable when you define it, like:
int a;
Now a can only ever hold an int value - if you try to assign a string to it, or call a method on it, you will get a compile type error.
2) In static language the type of an object cannot change. In dynamic languages, an object can change in that you can attach or remove methods and properties, thereby basically turning it into a completely different object.
c# is statically typed, ie int i =0; try setting i to be a string. the compiler will complain,
where as python a variable that used to hold an integer can then be set to hold a string,
Static: Types are final,
Dynamic: Types can be changed,
c# is trying to add more dynamic like features, var for instance
There is no true "language of the future".
Different languages have different purposes.
At most, you could say Ruby is a language of the future.
According to Wikipedia:
Dynamic programming language is a term
used broadly in computer science to
describe a class of high-level
programming languages that execute at
runtime many common behaviors that
other languages might perform during
compilation, if at all. These
behaviors could include extension of
the program, by adding new code, by
extending objects and definitions, or
by modifying the type system, all
during program execution. These
behaviors can be emulated in nearly
any language of sufficient complexity,
but dynamic languages provide direct
tools to make use of them.
Most dynamic languages are dynamically typed, but not all.
Ruby is a dynamic language and C# is not, since Ruby is interpreted and C# is compiled. However, C# does include some features that make it appear dynamic.
A language is dynamically typed, that means a variable in that can be used for anything.
Variables are not typed, values are. A variable can have the value of any primitive type, or it can reference to any object.

Code Generators or T4 Templates, are they really evil?

I have heard people state that Code Generators and T4 templates should not be used. The logic behind that is that if you are generating code with a generator then there is a better more efficient way to build the code through generics and templating.
While I slightly agree with this statement above, I have not really found effective ways to build templates that can say for instance instantiate themselves. In otherwords I can never do :
return new T();
Additionally, if I want to generate code based on database values I have found that using Microsoft.SqlServer.Management.SMO in conjunction with T4 templates have been wonderful at generating mass amounts of code without having to copy / paste or use resharper.
Many of the problems I have found with Generics too is that to my shock there are a lot of developers who do not understand them. When I do examine generics for a solution, there are times where it gets complicated because C# states that you cannot do something that may seem logical in my mind.
What are your thoughts? Do you prefer to build a generator, or do you prefer to use generics? Also, how far can generics go? I know a decent amount about generics, but there are traps and pitfalls that I always run into that cause me to resort to a T4 template.
What is the more proper way to handle scenarios where you need a large amount of flexibility? Oh and as a bonus to this question, what are good resources on C# and Generics?
You can do new T(); if you do this
public class Meh<T>
where T : new()
{
public static T CreateOne()
{
return new T();
}
}
As for code-generators. I use one every day without any problems. I'm using one right now in fact :-)
Generics solve one problem, code-generators solve another. For example, creating a business model using a UML editor and then generating your classes with persistence code as I do all of the time using this tool couldn't be achieved with generics, because each persistent class is completely different.
As for a good source on generics. The best has got to be Jon Skeet's book of course! :-)
As the originator of T4, I've had to defend this question quite a few times as you can imagine :-)
My belief is that at its best code generation is a step on the way to producing equivalent value using reusable libraries.
As many others have said, the key concept to maintain DRY is never, ever changing generated code manually, but rather preserving your ability to regenerate when the source metadata changes or you find a bug in the code generator. At that point the generated code has many of the characteristics of object code and you don't run into copy/paste type problems.
In general, it's much less effort to produce a parameterized code generator (especially with template-based systems) than it is to correctly engineer a high quality base library that gets the usage cost down to the same level, so it's a quick way to get value from consistency and remove repetition errors.
However, I still believe that the finished system would most often be improved by having less total code. If nothing else, its memory footprint would almost always be significantly smaller (although folks tend to think of generics as cost free in this regard, which they most certainly are not).
If you've realised some value using a code generator, then this often buys you some time or money or goodwill to invest in harvesting a library from the generated codebase. You can then incrementally reengineer the code generator to target the new library and hopefully generate much less code. Rinse and repeat.
One interesting counterpoint that has been made to me and that comes up in this thread is that rich, complex, parametric libraries are not the easiest thing in terms of learning curve, especially for those not deeply immersed in the platform. Sticking with code generation onto simpler basic frameworks can produce verbose code, but it can often be quite simple and easy to read.
Of course, where you have a lot of variance and extremely rich parameterization in your generator, you might just be trading off complexity an your product for complexity in your templates. This is an easy path to slide into and can make maintenance just as much of a headache - watch out for that.
Generating code isn't evil and it doesn't smell! The key is to generate the right code at the right time. I think T4 is great--I only use it occasionally, but when I do it is very helpful. To say, unconditionally, that generating code is bad is unconditionally crazy!
It seems to me code generators are fine as long as the code generation is part of your normal build process, rather than something you run once and then keep its output. I add this caveat because if just use the code generator once and discard the data that created it, you're just automatically creating a massive DRY violation and maintenance headache; whereas generating the code every time effectively means that whatever you are using to do the generating is the real source code, and the generated files are just intermediate compile stages that you should mostly ignore.
Lex and yacc are classic examples of tools of allow you to specify functionality in an efficient manner and generate efficient code from it. Trying to do their jobs by hand will lengthen your development time and probably produce less efficient and less readable code. And while you could certainly incorporate something like lex and yacc directly into your code and do their jobs at run time instead of at compile time, that would certainly add considerable complexity to your code and slow it down. If you actually need to change your specification at run time it might be worth it, but in most normal cases using lex/yacc to generate code for you at compile time is a big win.
A good percentage of what is in Visual Studio 2010 would not be possible without code generation. Entity Framework would not be possible. The simple act of dragging and dropping a control onto a form would not be possible, nor would Linq. To say that code generation should not be used is strange as so many use it without even thinking about it.
Maybe it is a bit harsh, but for me code generation smells.
That code generation is used means that there are numerous underlying common principles which may be expressed in a "Don't repeat yourself" fashion. It may take a bit longer, but it is satisfying when you end up with classes that only contain the bits that really change, based on an infrastructure that contains the mechanics.
As to Generics...no I don't have too many issues with it. The only thing that currently doesn't work is saying that
List<Animal> a = new List<Animal>();
List<object> o = a;
But even that will be possible in the next version of C#.
Code generation is for me a workaround for many problems found in language, frameworks, etc. They are not evil by themselves, I would say it is very very bad (i.e. evil) to release a language (C#) and framework which forces you to copy&paste (swap on properties, events triggering, lack of macros) or use magical numbers (wpf binding).
So, I cry, but I use them, because I have to.
I've used T4 for code generation and also Generics. Both are good, have their pros and cons, and are suited for different purposes.
In my case, I use T4 to generate Entities, DAL and BLL based on a database schema. However, DAL and BLL reference a mini-ORM I built, based on Generics and Reflection. So I think you can use them side by side, as long as you keep in control and keep it small and simple.
T4 generates static code, while Generics is dynamic. If you use Generics, you use Reflection which is said to be less performant than "hard-coded" solution. Of course you can cache reflection results.
Regarding "return new T();", I use Dynamic Methods like this:
public class ObjectCreateMethod
{
delegate object MethodInvoker();
MethodInvoker methodHandler = null;
public ObjectCreateMethod(Type type)
{
CreateMethod(type.GetConstructor(Type.EmptyTypes));
}
public ObjectCreateMethod(ConstructorInfo target)
{
CreateMethod(target);
}
void CreateMethod(ConstructorInfo target)
{
DynamicMethod dynamic = new DynamicMethod(string.Empty,
typeof(object),
new Type[0],
target.DeclaringType);
ILGenerator il = dynamic.GetILGenerator();
il.DeclareLocal(target.DeclaringType);
il.Emit(OpCodes.Newobj, target);
il.Emit(OpCodes.Stloc_0);
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Ret);
methodHandler = (MethodInvoker)dynamic.CreateDelegate(typeof(MethodInvoker));
}
public object CreateInstance()
{
return methodHandler();
}
}
Then, I call it like this:
ObjectCreateMethod _MetodoDinamico = new ObjectCreateMethod(info.PropertyType);
object _nuevaEntidad = _MetodoDinamico.CreateInstance();
More code means more complexity. More complexity means more places for bugs to hide, which means longer fix cycles, which in turn means higher costs throughout the project.
Whenever possible, I prefer to minimize the amount of code to provide equivalent functionality; ideally using dynamic (programmatic) approaches rather than code generation. Reflection, attributes, aspects and generics provide lots of options for a DRY strategy, leaving generation as a last resort.
Generics and code generation are two different things. In some cases you could use generics instead of code generation and for those I believe you should. For the other cases code generation is a powerful tool.
For all the cases where you simply need to generate code based on some data input, code generation is the way to go. The most obvious, but by no means the only example is the forms editor in Visual Studio. Here the input is the designer data and the output is the code. In this case generics is really no help at all, but it is very nice that VS simply generates the code based on the GUI layout.
Code generators could be considered a code smell that indicate a flaw or lack of functionality in the target langauge.
For example, while it has been said here that "Objects that persist can not be generalized", it would be better to think of it as "Objects in C# that automatically persist their data can not be generalized in C#", because I surely can in Python through the use of various methods.
The Python approach could, however, be emulated in static languages through the use of operator[ ](method_name as string), which either returns a functor or a string, depending on requirements. Unfortunately that solution is not always applicable, and returning a functor can be inconvenient.
The point I am making is that code generators indicate a flaw in a chosen language that are addressed by providing a more convenient specialised syntax for the specific problem at hand.
The copy/paste type of generated code (like ORMs make) can also be very useful...
You can create your database, and then having the ORM generate a copy of that database definition expressed in your favorite language.
The advantage comes when you change your original definition (the database), press compile and the ORM (if you have a good one) can re-generates your copy of the definition. Now all references to your database can be checked by the compilers type checker and your code will fail to compile when you're using tables or columns that do not exist anymore.
Think about this: If I call a method a few times in my code, am I not referring to the name I gave to this method originally? I keep repeating that name over and over... Language designers recognized this problem and came up with "Type-safety" as the solution. Not removing the copies (as DRY suggests we should do), but checking them for correctness instead.
The ORM generated code brings the same solution when referring to table and column names. Not removing the copies/references, but bringing the database definition into your (type-safe) language where you can refer to classes and properties instead. Together with the compilers type checking, this solves a similar problem in a similar way: Guarantee compile-time errors instead of runtime ones when you refer to outdated or misspelled tables (classes) or columns (properties).
quote:
I have not really found effective ways to build templates that can say for instance instantiate themselves. In otherwords I can never do :
return new T();
public abstract class MehBase<TSelf, TParam1, TParam2>
where TSelf : MehBase<TSelf, TParam1, TParam2>, new()
{
public static TSelf CreateOne()
{
return new TSelf();
}
}
public class Meh<TParam1, TParam2> : MehBase<Meh<TParam1, TParam2>, TParam1, TParam2>
{
public void Proof()
{
Meh<TParam1, TParam2> instanceOfSelf1 = Meh<TParam1, TParam2>.CreateOne();
Meh<int, string> instanceOfSelf2 = Meh<int, string>.CreateOne();
}
}
Why does being able to copy/paste really, really fast, make it any more acceptable?
That's the only justification for code generation that I can see.
Even if the generator provides all the flexibility you need, you still have to learn how to use that flexibility - which is yet another layer of learning and testing required.
And even if it runs in zero time, it still bloats the code.
I rolled my own data access class. It knows everything about connections, transactions, stored procedure parms, etc, etc, and I only had to write all the ADO.NET stuff once.
It's now been so long since I had to write (or even look at) anything with a connection object in it, that I'd be hard pressed to remember the syntax offhand.
Code generation, like generics, templates, and other such shortcuts, is a powerful tool. And as with most powerful tools, it amplifies the capaility of its user for good and for evil - they can't be separated.
So if you understand your code generator thoroughly, anticipate everything it will produce, and why, and intend it to do so for valid reasons, then have at it. But don't use it (or any of the other technique) to get you past a place where you're not to sure where you're headed, or how to get there.
Some people think that, if you get your current problem solved and some behavior implemented, you're golden. It's not always obvious how much cruft and opaqueness you leave in your trail for the next developer (which might be yourself.)

Categories