I stick with static typing because of its programming to interface (client contract). I am attracted by dynamic typing with its ability to add behaviors at runtime. Unfortunately, you can only have one or the other, but not both. Even mixing them in one language like C# (.NET 4 has some dynamic typing capabilities now), you lose the capability to have dynamic behaviors when you use static typing, and you lose programming to contract when you use dynamic typing. Or is it?
Dynamic Behaviors With Static Typing
The reason for dynamic typing to be able to add dynamic behaviors at runtime is that it works directly with objects without involving classes (remember, no class in prototype-based programming). In the blog Adapt to Changes With Dynamic Behaviors, I pointed out that dynamic typing is sufficient but not necessary for dynamic behaviors. In static typing, we can directly work with objects, too. That is what Component-Based Object Extender (CBO Extender) does.
CBO Extender is an object extensibility framework for .NET and works directly with objects and interfaces. It does not know or care, and is completely decoupled from, components from which objects are created. Any interface methods can be decorated with extra behaviors at runtime. Cross-cutting concerns like logging, security checking or transaction management can be presented as dynamic behaviors which are added to objects at runtime as needed (see article Dynamic Object Programming for examples). Business requirements like sorting or anything (e.g., Hello World!) can also be presented as dynamic behaviors which are added to objects at runtime (see articles Application Development With Component-Based Object Extender and OOP, AOP and OP).
You now end up with best of both worlds: programming to interface and dynamic behaviors. You use static typing to define your interfaces, classes and components. An application developer can expect a software component with core business functionality and well-defined client contract (interfaces). He/She can use CBO Extender to add extra functionality to objects of the component as needed at runtime.
To see how easily you can add dynamic behaviors to an application, here, I reuse the Hello World! example presented in the blog OOP, AOP and OP.
Say, you have a DoAnything
component that implements an IDoAnything
interface. The application code is listed as follows:
namespace HelloWorld
{
public interface IDoAnything
{
void DoThing();
}
public class DoAnything : IDoAnything
{
public void DoThing()
{
}
}
class Program
{
static void Main(string[] args)
{
IDoAnything doAThing = new DoAnything();
doAThing.DoThing();
}
}
}
Of course, the DoThing
method of doAThing
object does nothing. Now, let’s define a SayHello
aspect method and a SayBye
method, and use ObjectProxyFactory.CreateProxy2
method of CBO Extender to add them to the doAThing
object as extra behaviors. The application is listed as follows:
using CBOExtender;
namespace HelloWorld
{
public interface IDoAnything
{
void DoThing();
}
public class DoAnything : IDoAnything
{
public void DoThing()
{
}
}
class Program
{
static void Main(string[] args)
{
IDoAnything doAThing = new DoAnything();
doAThing = ObjectProxyFactory.CreateProxy2<IDoAnything>(
doAThing,
new string[] { "DoThing" },
new Decoration2(SayHello, null),
new Decoration2(SayBye, null)
);
doAThing.DoThing();
}
public static void SayHello(AspectContext2 ctx, dynamic parameters)
{
System.Console.WriteLine("Hello World!");
}
public static void SayBye(AspectContext2 ctx, dynamic parameters)
{
System.Console.WriteLine("Bye!");
}
}
}
Now, the DoThing
method of doAThing
object outputs the “Hello World!
” and “Bye!
”.
Actually, there is nothing that can stop you to put any logic into the SayHello
method or SayBye
method. You can also create any number of objects of DoAnything
and add any number of aspect methods. Your DoAnything
component indeed can do anything!