Boo and Duck Typing

A heated discussion broke out at work today over the pros and cons of allowing the UI to reference the data access layer.  I'm agnostic about this myself, but we have enforced this restriction and thus have a lot of pointless pass-thru methods that need to be maintained.  Without discussing the merits of any of this, I was wondering, theoretically, how we could avoid writing pass-thru methods were we to use a more dynamic language.

Enter boo and its duck typing.

Say I have a TestRepository, and it has a method GetUser:

class TestRepository(): def constructor(): pass def GetUser(name as string): Console.WriteLine(name)

And I have my TestServices, that contains a TestRepository.  I don't want to write the method on TestServices that just calls TestRepository, and maintain it an all of its parameters.


Instead, I can implement the interface IQuackFu, and implement its methods QuackInvoke, QuackSet and QuackGet

class TestServices(IQuackFu): testRepository as TestRepository def constructor(repository): testRepository = repository def QuackInvoke(name as string, args as (object)) as object: # need to parse parameters to handle overloads testRepository.GetType().GetMethod(name).Invoke(testRepository, args) def QuackSet(name as string, parameters as (object), value) as object: pass def QuackGet(name as string, parameters as (object)) as object: pass

Then if I have a service, declared as a duck (a valid type in boo), I can call any method on it and it will be handled by QuackInvoke.

[Test] def can_call_child(): services as duck services = TestServices(TestRepository()) services.GetUser("ignu")

services.GetUser("ignu") calls services.QuackInvoke("GetUser", "ignu") and our test passes:

Selected test: QuackTest.Test.can_call_child ignu

Yay!

Len: 1 Compiler: 0

Actually, scratch that.  This solution works... but it's not the most elegant solution in the universe.   It's more of a draw. 

We'll meet again, compiler.  Mark my words.