Awwya fool... Jonas Avellana (aka DJ LeDude) brought both his coding speedos and .Net skills to the edmug meeting this evening. Jonas delivered a couple of hours of Linq, SQL and .Net 3.5 nyahhhhh with a flair that's all his own. For those who missed it, here are the top 10 Jonasisms of the evening:
10. Awwww ya!!!
9. Thats Frickin' Cool
8. Thats Frickin' Awesome
7. You can do it like that if you're deepcore
6. var crapDataContext = new DragAndDropCrapDataContext(); [typed not vocalized]
5. First, I'm gonna show you the ghetto way...
4. ... now we'll do some Linq Kung Foo
3. Well, you know we don't have many chicks in the west end so the woman's prison is pretty good
2. Aghhhh my eyes!!!
1. I don't know how it works but its pretty awesome
A little bit of a let down was that he didn't find a way to work bescumber into the presentation but he made up for it by delivering an excellent Linq packed presentation. Thanks Jonas! It takes a lot of time and effort to do a presentation like that and myself and the rest of the .Net community really appreciate it. Now you can get back to ghost riding the whip.
You can read more from Jonas on his blog: http://blog.ezed.ca
Thursday, May 29, 2008
Top 10 Jonasims From the LinqToYourBrain Talk
Saturday, May 24, 2008
How to read a programming book
Earlier this week Seth Godin had an inspirational post titled How to read a business book in which he postulates that many people read non-fiction for the enjoyment of a factual adventure. Magic books rarely produce the next Houdini but the masses still enjoy reading about the mechanics behind the tricks. Similarly not everyone who reads a business book becomes a millionaire, rather we enjoy hearing about the daring capitalist who went from rags to riches.
Seth supports this claim by stating the recipe of a business book can be distilled down to a couple of pages. If one just wanted to read a business recipe they could do so in just a few minutes. But the truth is, as Seth writes:
- Bullet points are not the point.
The value in a business book is the fluffy stuff around the recipe. If read in the right state of mind it will motivate you to reflect on your own perspective and behavior. If read with the intent to change these books can, in fact, help you to change your life.
In our own industry the electronic aisles of Amazon are littered with How To and recipe style books that miss the essence of persuasion. These books tend to have a shelf life rarely exceeding that of a top 10 pop hit. These books will not change your life even if you wanted them too.
There are other books, however, that can change your life if you read them with the intent to change your life. As Seth says,
the goal of reading, then, isn't to persuade you to change rather to help choose what to change.
While I'm not an expert on the matter, my advice to reading a programming book requires a few tools. First go out and buy a stack of index cards, or post-it notes or even a pad of paper. Second, find a pencil, pen or feather and ink... check between the cushions of your car seat you'll find something to write with. Once you've got those things try these 6 steps:
1. Start with an intent to change. Make the decision before ever opening the book. Pick a handful of pain points in your daily grind. It may be technical pain that can be solved with design patterns. Perhaps its pain with requirement gathering that may be solved through understanding a different software process. In any event, write each pain down on its own index card. At the end of this process each card will form a recipe for your success.
2. Read and write. Now read the book. But don't just read it, write about it as well. As you're reading keep your pain points in mind and when you encounter something that may help solve your problem jot it down on the card. These are your solutions.
3. Set a goal. Now that you've identified problems and solutions you just need a goal. Missing the important step of setting goals is where most people fall short, but not you!. Rise above the rest and write down what you want to achieve and a reasonable time frame in which you will achieve it. Remember there are no unrealistic goals only unrealistic deadlines.
4. Just do it. Remember that you've invested your valuable time in reading the book, you've invested the effort of reflection and you now have a card that tells you exactly how to change. Bring those cards to work and read them a few times during the day. Keep your goals at the forefront of your concentration and the rest will follow suit. You will achieve your goals if you concentrate on them. Whenever you achieve one give yourself a gold star. You've earned it!
5. Don't stop there. Repeat this cycle in small increments over and over again. The process is called Kaizen by the Japanese and it means making continuous changes over time through tight increments of small change. The software industry is more susceptible to change than any other. We are at the mercy of change in technology, paradigms, business, globalization and an unnamed butterfly in the amazon jungle. The only way to avoid extinction in this field is to change continuously.
6. Tell everyone. Tell your team, your manager, your friends and even your grandmother. Pass the book around and tell them what you've achieved. Blog about it and encourage others to change as well. If you're in a position of leadership consider this quote from Seth:
Effective managers hand books to their team. Not so they can be reminded of high school, but so that next week she can say to them, "are we there yet?".
Remember that as exciting as the plot of a programming book may be, reading it is an investment of your time. Cash in on your investment by changing something in your life.
Tuesday, May 20, 2008
Fun With Boo's List Generators
I know I'm a bit late to the party but I've just recently become infatuated with Boo's List Generators. Being a bit of a nerd I thought I'd take a shot at implementing a Eratosthenes Prime Number Sieve using one of these generators. I know this may not be an optimal solution from an algorithmic perspective but the syntax is really cool. Here's what I came up with:
last = int.Parse(argv[0])
filters = []
def IsPrime(number as int):
for filter as ICallable in filters:
if filter(number): return false
return true
def HandlePrime(i as int):
unless i > System.Math.Sqrt(last): filters.Add({ number as int | return number%i == 0})
return i
print List(HandlePrime(i) for i in range(2,last) if IsPrime(i))
NYAHHHH!!!
Saturday, May 17, 2008
Kicking Ast with Boo
I'm currently working on a project that consumes a third party web service. This web service uses xml serializable DTOs to pass a fairly complex object model across the wire. The downside of this interface is that our code base (especially the tests) is littered with blocky new statements and setters like this (we're still in 2.0 land so we can't use object initializers):
PersonDTO person = new PersonDTO();
person.FirstName = "Neil";
person.LastName = "Bourgeois";
person.Address = new AddressDTO();
person.Address.Number = 10160;
person.Address.Street = "115 St.";
person.Address.City = "Edmonton";
person.Address.PostalCode = "T5K 1T6";
person.Address.Country = "Canada";
person.Email = "neil.bourgeois.junk@gmail.com";
person.Age = 30;
I started writing builders with a fluent interface to help alleviate some of the typing and improve the readability so a person can be constructed like this:
PersonDTO person = BuildPerson.With
.FirstName("Neil")
.LastName("Bourgeois")
.Address(BuildAddress.With
.Number(10160)
.Street("115 St.")
.City("Edmonton")
.PostalCode("T5K 1T6")
.Country("Canada")
.Build())
.Email("neil.bourgeois.junk@gmail.com")
.Age(30)
.Build();
The builder looks something like this:
public class PersonBuilder
{
private readonly PersonDTO person = new PersonDTO();
public static PersonBuilder With
{
get { return new PersonBuilder(); }
}
public PersonBuilder FirstName(string firstName)
{
person.FirstName = firstName;
return this;
}
public PersonBuilder LastName(string lastName)
{
person.LastName = lastName;
return this;
}
public PersonDTO Build()
{
return person;
}
}
Its a much nicer way to define our DTOs, however, building the builder class proved a taxing experience. Even with a dab of generics and a splash of inheritance the monotony of defining the builders made me almost throw this pattern out the window. But then I remembered a bit of Boo AST magic described by Ayende and thought, why can't I get a compiler to do this work for me? I did some googling to find this helpful post by Luis Diego Fallas and started to cut some code.
Essentially this code creates the a builder class for each DTO in our source assembly (hardcoded as SampleDTO). The result of running it is a new assembly called builder.dll that contains all the fluent builders. Builder classes are defined by creating expressions in an Abstract Syntax Tree (AST) and running that tree through the boo compiler.
To start with we need to define a new class. I like fluent interfaces to read like an English sentence so I chose to give the builder classes names like: BuildSomething. I also strip out the DTO portion of the name as just adds clutter.
baseName = type.Name.Replace("DTO", string.Empty)
newClass = ClassDefinition(Name:"Build" + baseName)
Once the class is defined we need to add a member variable for the type we are going to create:
newClass.Members.Add(Field(Name:"item",
Type:SimpleTypeReference(type.FullName),
Modifiers:TypeMemberModifiers.Private))
Next I want the constructor to initialize the member variable (eg. item = new PersonDTO()):
ctr = Constructor()
ctr.Body.Add(ExpressionStatement(
Expression:BinaryExpression(
BinaryOperatorType.Assign,
MemberReferenceExpression(
Target:SelfLiteralExpression(),
Name:"item"),
MethodInvocationExpression(ReferenceExpression(type.Name)))))
newClass.Members.Add(ctr)
Now we can add the Build() method that simply returns our member variable..
buildMethod = Method(
Name:"Build",
Modifiers:TypeMemberModifiers.Public,
Body:Block(),
ReturnType:SimpleTypeReference(type.FullName))
buildMethod.Body.Add(ReturnStatement(Expression:
MemberReferenceExpression(
Target:SelfLiteralExpression(),
Name:"item")))
newClass.Members.Add(buildMethod)
... and the static With property to give us a natural way to construct the builder. Remember that properties actually require a method behind the scenes to do the real work. So we will start with a getter that constructs a new instance of our builder and immediately returns it:
withGetMethod = Method(
Name:"internalWithGetter",
Modifiers:TypeMemberModifiers.Public | TypeMemberModifiers.Static,
Body:Block(),
ReturnType:SimpleTypeReference(newClass.Name))
withGetMethod.Body.Add(ReturnStatement(Expression:MethodInvocationExpression(ReferenceExpression(newClass.Name))))
Now we can add the With property:
withProperty = Property(
Name:"With",
Getter:withGetMethod,
Modifiers:TypeMemberModifiers.Public | TypeMemberModifiers.Static)
newClass.Members.Add(withProperty)
Finally we want to loop through all properties in our DTO and create fluent setter methods. We want this method to look like this:
public PersonBuilder FirstName(string firstName)
{
person.FirstName = firstName;
return this;
}
We'll start by creating a new method that has the same name as the property we want to set. To facilitate the fluent interface the return type of this method is the type of our builder class:
m = Method(Name: property.Name,
Modifiers:TypeMemberModifiers.Public,
Body:Block(),
ReturnType:SimpleTypeReference(newClass.Name))
Next we want to add a parameter argument to this method. This is the value we want to set the DTO property to:
parameterName = property.Name
m.Parameters.Add(ParameterDeclaration(
Name: parameterName,
Type:SimpleTypeReference(
Name:property.PropertyType.FullName)))
Now lets take that parameter and assign it to the appropriate property in our DTO. This step was a bit tricky to get right the first time but it makes sense when you think about assignment (a = b) as a binary operation (like a + b or a > b):
m.Body.Add(ExpressionStatement(
Expression:BinaryExpression(
BinaryOperatorType.Assign,
MemberReferenceExpression(
Target:ReferenceExpression("item"),
Name:property.Name),
ReferenceExpression(parameterName))))
Last but not least we need to return the instance of the builder class (this):
m.Body.Add(ReturnStatement(Expression:SelfLiteralExpression()))
Once the AST for our new builder types is complete we can take it and compile it into an assembly. Here is the code that brings it all together (Note the call to BuildClass, this is where the AST for our builder is created):
a = Assembly.Load("SampleDTO")
cu = CompileUnit()
mod = Boo.Lang.Compiler.Ast.Module(
Name:"Builder",
Namespace:NamespaceDeclaration(Name:"Builder"))
cu.Modules.Add(mod)
mod.Imports.Add(Import(Namespace:"System"))
mod.Imports.Add(Import(Namespace:"SampleDTO"))
for type in a.GetTypes():
mod.Members.Add(BuildClass(type))
pipeline = Pipelines.CompileToFile()
ctxt = CompilerContext(cu)
ctxt.Parameters.OutputType = CompilerOutputType.Library
pipeline.Run(ctxt)
Defining types in AST is a bit like walking in mud: slow and painful. What can be accomplished with 3 lines of code using a higher level language can take many many more. Hang in there, the frustration wears off after a few eureka moments and the benefit of learning this stuff can be huge. In my case a few hours writing AST (which was really interesting work) saved many more dull and tedious hours of writing boring property setters.
Remember that Reflector is your best friend for this type of work!!
As a side note, the overall framework for this is pretty cool. Whenever there is a new release of a web service we can run a NAnt build script that does the following:
1. Use wsdl to generate a proxy class (and all DTOs)
2. Compile the proxy and DTOs into an assembly
3. Run the fluent builder generator on the new assembly
4. Run ILMerge to create a new assembly with the outputs from 2 and 3
The result is a single assembly containing the Proxy, DTOs and Builders... its pretty slick!
