Lately, I’ve been playing with such things as MongoDB using F# to rapidly prototype ideas. With that, I’ve tried to rid myself of magic strings by using the F# dynamic lookup operator. I’ll cover exactly what I’m doing in the next post when using MongoDB, but in this post I’d like to explore a little of what you could do with a little noticed dynamic lookup operator in F#.
Much like C# 4.0 has the ability to do dynamic lookup, F# also has the same capability, although in a different capacity. The language has support for a dynamic lookup get operator ( ? ) and set operator ( ?<- ), but note that I said support and not actual implementation. The actual implementation is up to you and how you want to use it.
Let’s start off by implementing the get operator to get a public property (not super useful yet).
let (?) (this : 'Source) (prop : string) : 'Result = let p = this.GetType().GetProperty(prop) p.GetValue(this, null) :?> 'Result
We can write an example that verifies the behavior such as comparing a normal invocation and our “dynamic” invocation, as in this example of comparing getting the length of a string.
[<Fact>] let ``Dynamic lookup should equal normal``() = areEqual "foo".Length "foo"?Length
But, we’re not limited to that. For example, we could instead decide that we want to get a private member instead of a public one. We could change up our example from above just slightly.
let (?) (this : 'Source) (prop : string) : 'Result = let flags = BindingFlags.GetProperty ||| BindingFlags.NonPublic let p = this.GetType().GetProperty(prop, flags) p.GetValue(this, null) :?> 'Result
We can verify our behavior of this idea with a little example, for example invoking a private property in a custom class such as the following:
type PrivateProperty(propValue : string) = member private __.PropValue with get() = propValue [<Fact>] let ``Can invoke private property``() = let expected = "foo" let p = PrivateProperty(expected) let actual : string = p?PropValue areEqual expected actual
So, as you can see, this is quite useful so far, but we’ve only scratched the surface. We’ve just dealt with properties so far, but what about methods? The same applies here as well. In this instance, let’s take a method that could have any number of arguments and invoke it just as if we would normally.
open Microsoft.FSharp.Reflection open System.Reflection let (?) (this : 'Source) (member' : string) (args : 'Args) : 'Result = let argArray = if box args = null then null elif FSharpType.IsTuple (args.GetType()) then FSharpValue.GetTupleFields args else [|args|] let flags = BindingFlags.GetProperty ||| BindingFlags.InvokeMethod this.GetType().InvokeMember(member', flags, null, this, argArray) :?> 'Result
What we needed to do here is take not only the member but the arguments as well. If the arguments object is null (or unit), then we pass a null objet array, else if our type is a tuple, then we create an array from our tuple, and finally if it’s a single argument, then we make it into an array. Finally we invoke our member with the flags to say it is either a property getter or a method and invoke with our arguments. Let’s write an example of how to use this.
[<Fact>] let ``Can invoke method with dynamic lookup``() = isTrue ("dynamic"?Length() > 0) isTrue ("dynamic"?EndsWith("ic")) areEqual "dyn" ("dynamic"?Substring(0,3))
Above are three tests which show no arguments, a single argument, and finally tupled arguments. But what about setters?
Just as we have the ( ? ) operator reserved for the get operator, we have the ( ?<- ) operator reserved for the set. This allows us to be able to set any number of things with the same ease as the get. For example, we could set a public property:
let (?<-) (this : 'Source) (property : string) (value : 'Value) = this.GetType().GetProperty(property).SetValue(this, value, null)
This simply gets the property and then sets the appropriate value. And then we can write a test as an example of how it should work.
type MutablePropertyClass(value : string) = let mutable v = value member __.Value with get() = v and set(value) = v <- value [<Fact>] let ``Dynamic setter should set property``() = let m = MutablePropertyClass("foo") m?Value <- "dynamic" areEqual "dynamic" m.Value
In this example, we have a simple class with a property with a getter and setter and then we set our property using our special operator and then compare the values. Once again, this is flexible enough where we could set private properties much as we retrieved them above. Now, let’s put them together for a few quick examples.
One idea that we could go with is instead of using string keys for dealing with key value pairs, we could use our dynamic getter and setter instead. Nothing like a bit of syntactic sugar to brighten your day to lessen the noise. Our goal for this is to go from:
let d = Dictionary<string,obj>() d.["StaticKey"] <- "Meh"
To something like the following:
let d = Dictionary<string,obj>() d?DynamicKey <- "Totally!"
How could we pull this one off? Well, we could implement the dynamic lookup getter and setter to do nothing more than look in the dictionary as follows:
open System.Collections let (?) (this : #IDictionary) key = this.[key] let (?<-) (this : #IDictionary) key value = this.[key] <- value
Now we can verify our behavior with our test that we should have written first.
let ``Dictionary should get and set dynamically``() = let d = Dictionary<string,obj>() d?DynamicKey <- "hello" areEqual d.["DynamicKey"] d?DynamicKey
A solution like this could work well for situations like MongoDB, which we’ll get into with our next post. But, could go a step further and to say anything with the Item property could be ours for the taking.
In the .NET libraries, we have a few classes which expose an indexer property like an array, a Dictionary, and even a string. It would be nice to have a way to both get and set this value through the use of our dynamic lookup operator, but how could we pull this off? In some previous posts, I talked about generic restrictions in the F# language, and one in particular stands out, the member restriction operator. This operators lets us constrain a given object parameter so that it must implement the following methods and properties.
Remember, our overall goal is to support calling this:
open System.Collections.Generic let d = Dictionary<string,string>() d?DynamicKey <- "Totally!" type IndexedObject() = let d = Dictionary<string,string>() member self.Item with get(key) = d.[key] and set key value = d.[key] <- value let i = IndexedObject() h?IndexedKey <- "IndexedValue"
So, what we have is both a Dictionary<TKey,TValue> and a custom indexed object. Since they do not follow an inheritance chain which exposes an Item property, we cannot use the example from above with the IDictionary. Instead, we’ll use member restrictions for both the method get_Item and set_Item.
let inline (?) this key = ( ^a : (member get_Item : ^b -> ^c) (this,key)) let inline (?<-) this key value = ( ^a : (member set_Item : ^b * ^c -> ^d) (this,key,value))
What you see is that we’re calling both the get_Item and set_Item properties, which are the raw method names for the Item property. Now we’re able to verify our test using our IndexedObject class from above:
let ``Can use dynamic indexed getter and setter``() = let i = IndexedObject() i?SomeKey <- "Some value" areEqual i.["SomeKey"] i?SomeKey
A big word of caution when using this approach is that you’ll get a nice warning from the F# compiler that doing this may cause unverified code as F# treats the Item property specially. For example, all value types must be boxed before putting them into the collection.
let h = Hashtable() h?MyKey <- 3 // Don't do this h?MyKey <- box 3 // Do this
Very powerful way of doing things but also you must be careful with this approach if you use it at all.
So, as you can see, F#, just like C# has the facilities for dynamic lookup, although in F# you are left to implement it yourself in any which way you like. One great thing about these operator is that it doesn’t require .NET 4.0 to implement and use them. But with any power comes of course some responsibility for it, so use it wisely.
This is really exciting time these days. Most of .NET tooling vendors are about to provide a major upgrade of their products within the next weeks. And Reflector is part of the lot! A brand new version, Reflector v6, is about to be go live RTM on Monday 15th of February 2010. This will be the first time the company Red-Gate will update the product since it has been acquired from its original creator, Lutz Roeder, in August 2008.
There are 90% of chances you are using Reflector daily so don't be afraid: current Reflector features will continue to be provided in a free version of the tool. The Red-Gate strategy is to append new innovative features to the tool, and only these features will require a professional purchased version. The flagships features of Reflector v6 is the ability to debug source code decompiled from IL code, in the Visual Studio debugger. This is certainly a killer one: we all need at a point to have a better understanding of what's happening at runtime in Framework used by our code.
Having used Reflector v6 beta, I can say that plenty of cool featurettes have been also been added, including a bridge between Reflector and Visual Studio (ok this one is already provided more or less by several tools, including TestDriven.NET and NDepend)
Another cool thing is that the upcoming NDepend v3 is working hand-in-hand with Reflector v6 (as a Reflector addin). And as NDepend v3 is also a Visual Studio 2010 / 2008 /2005 addin, all NDepend features constitute more glue between Reflector v6 and Visual Studio, including:
Time flies when you’re having fun. It’s been almost a year since I’ve made an official StructureMap release, so I guess it’s about time. This morning I uploaded the binaries for the 2.6 release. This release just adds some bug fixes and a couple minor additions to the 2.5.4 release that I made in December but didn’t really publicize. The release notes below are long, but that’s because they represent almost a year’s worth of development. As I said yesterday, StructureMap is most likely moving to GitHub with the documentation going as well. After a massive effort to write documentation early last year, huge chunks of it is already obsolete and there’s been a lot of addition since. I’m hoping that the move to the Wiki will make it easier to keep the docs up. In the meantime, I’ll try to blog a bit about the newer pieces starting tomorrow.
A tiny bit of history. This is the 11th StructureMap release since it debuted way back in June of 2004. Almost nothing is the same. We use it differently, the expectations are different, and very, very little of the original code survives today. At QCon San Francisco in 2008 I talked about what I’d learned from evolving this codebase over so many years and changes.
This release includes a lot of patches from the community, and I’d like to thank all of you for that – especially Frank Quednau and Andreas Ohlund for taking on some nastier things. Josh and Kevin Miller do yeoman duty answering StackOverflow questions (so I don’t have to).
Ok, so now that we have talked about the Business Primitive concept lets go through some of the actual examples. Let's take an example of a 'Loan' class.
public class Loan { public int Id { get; set; } public int InterestRate { get; set; } public DateTime TradedOn { get; set; } public DateTime SettledOn { get; set; } public decimal Principal { get; set; } }
After some small tweaks.
public class Loan { public int Id { get; set; } public Rate Interest { get; set; } public DateTime TradedOn { get; set; } public DateTime SettledOn { get; set; } public Money Principal { get; set; } }
Already the code feels more robust to me. The dates aren't that interesting to the business other than they are dates so they haven't yet been uplifted into 'business primitives' but Interest has been converted to 'Rate', which immediately helps with math and providing meaningful math like methods, as well as Principal which is now 'Money' which also helps with math and the more pernicious rounding issues.
So how was 'Rate' implemented? What does it look like?
[DebuggerDisplay("{_rate}%")] public class Rate { int _rate; private Rate() { } //factory methods public static Rate FromWholePercent(int rate) { new Rate(){_rate = rate};} //equality overrides here //operator overrides here }
First, we have the 'DebuggerDisplay' attribute which is my new best friend, it allows you to customize how the debugger displays your object in the debug view, very helpful. I have wrapped the previous rate value in a very simple fashion, and now we have a nicely centralized place to put math based functions (myRate = baseRate+riskRate). I have also added a factory method that help explain how this Rate object is being made. From whole percents such as 78% or 22%. Because we have hidden the way we actually store the value, we could also add support for 22.2% by adding a new factory method and changing the internal storage with out changing any other part of the code base. Very cool.
Ok, so what about saving these value objects and now I need to bind them to the UI how do I get at that hidden variable? I have taken quite a few paths when trying to implement this and the way that I do things now is a combination interface + base class. If you are anything like me you are thinking 'base class, yuck' and well I still do but this is the best way that I have come up with and I am open for suggestions. :)
So my 'business primitives' inherit from an abstract class called 'Primitive<T>' this class helps to streamline the creation of my business primitives. It also EXPLICITLY implements an interface called ValueObject<T> that exposes the underlying value, that can be used by UI controls and persistance frameworks with out mucking up my public API. I love that I don't see 'SetValue' and 'GetValue' unless I want to (yes, this could have been a property, not sure why I choose this). Here is the interface:
public interface ValueObject<T> { void SetValue(T input); T GetValue(); }
and the base class
[DebuggerDisploy("{_primitiveValue}")] public class Primitive<T> : ValueObject<T> { T _primitiveValue; public Primitive() { } public Primitive(V primitiveValue) { _primitiveValue = primitiveValue; } void ValueObject<T>.SetValue(T input) { _primitiveValue = input; } T ValueObject.GetValue() { return _primitiveValue; } //equality stuff }
I really wanted to do some tricky generics to try and implement the operator overloads in the base class as well, but the compiler wasn't to happy about that so those still have to be implemented in the 'Rate' class. Now my 'Rate' object looks like this:
public class Rate : Primitive<int> { private Rate() { } private Rate(int value) : base(value){} //factory methods public static Rate FromWholePercent(int rate) { new Rate(rate);} //operator overloads should be implemented here public bool Equals(Rate other) { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; return base.Equals(other); } }
For saving these buggers? Well, using NHibernate we can persist this as an 'int' using an IUserType, which makes things very simple and still manages to keep NH out of our domain. Some links on implementing IUserTypes
Now that we have addressed the saving aspect, what's a good way to present these 'business primitives'? Because
inputLoanPrincipal.Text = loan.Principal.ToUiString();
I hope this helps :)
-d
The original discussion for this topic is here: http://groups.google.com/group/structuremap-users/browse_thread/thread/6d579f4e9b508c66
All,
I've never liked SourceForge and it's a PITA for me to use even though it's gotten better over the years. I'd like to move StructureMap off SourceForge and more importantly, get a real Wiki site up so that we have at least a fighting chance of keeping the documentation up to date. On the other hand, I get a significant number of patches from you guys (thanks for that) and I'd also like a better way of handling those submissions -- and making it easier for *you* to get involved.
Right now, Josh and I are thinking about moving StructureMap to GitHub (you knew that was coming) and trying to use the Wiki support on Github for now. Granted, Git is weird as hell for those of us used to SVN, but GitHub has some huge advantages for OSS community development. I'd *love* to start managing StructureMap patches through GitHub "pull" requests (or whatever the correct lingo is).
Any thoughts? Volunteers? ;)
Jeremy
iptables is a linux application that allows you to configure the built-in linux firewall. There are abstraction layers built on top of it, including nice GUIs, but I recently had some very basic rules I wanted to implement, and figured I'd learn how to do it directly in iptables. It turned out to be easy to configure, and I thought I'd give a very basic introduction.
First though, I relied on the ubuntu documentation to get up and running (https://help.ubuntu.com/community/IptablesHowTo). I'll pretty much just regurgitate what's in there - I've said it before, stop believing that linux documentation is written only for people who already know linux. Also, depending on your setup, most of these commands might require elevation (sudo).
By default, iptables defines three rule chains: INPUT, FORWARD and OUTPUT. We'll only concern ourselves with INPUT - namely the chain used for incoming packets directed at this particular machine. At any point, you can list the rules by entering iptables -L. If listing the rules turns out to be really slow, try using iptables -L -n. The -n option means that the display will output IP addresses and ports in numeric format, without trying to do a DNS lookup. If the -n option makes it fast, then you're system likely has incorrect DNS settings (you can check out http://www.cyberciti.biz/tips/linux-how-to-setup-as-dns-client.html for help with that).
INPUT
FORWARD
OUTPUT
iptables -L
iptables -L -n
-n
In my particular case, the server is has two network interfaces - a public facing one (on eth0) and a private one (on eth1). For my purposes, I want to remotely (eth0) access SSH from my static IP, and locally (eth1) access postgresql on port 5432.
eth0
eth1
To accomplish this we simply append two rules to the INPUT chain:
iptables -A INPUT -p tcp --dport ssh -s 205.38.19.199 -i eth0 -j ACCEPT iptables -A INPUT -p tcp --dport 5432 -i eth1 -j ACCEPT
The first rule appends itself to the INPUT chain. Its limited to the TCP protocol targeting the SSH port (22) with a source originating from 205.38.19.199 on the eth0 network interface. It jumps to an ACCEPT status (all other processing stops). The next rule is similar, except it allows any source so long as they are connected to eth0 and targeting port 5432 (over tcp).
TCP
SSH
205.38.19.199
ACCEPT
5432
tcp
We can now add a third rule to block all other access:
iptables -A INPUT -j DROP
if incoming traffic doesn't mean the first two criteria, we'll hit this third rule and the firewall will reject the connection.
We'll run into 1 issue with our above configuration though - we've blocked access to the loopback interface (127.0.0.1). We need to add a special rule to allow loopback connections (since a lot of programs rely on it). However, we can't simply append it as it'll never be reached. Instead of using -a to append, we'll use -i to insert:
-a
-i
iptables -I INPUT 1 -i lo -j ACCEPT
Here we are inserting our rule in the 1st position, and accepting all connections made on the special lo (loopback) interface.
A really neat thing about iptables is that they aren't persisted by default. So, if you happen to mess up and cut yourself off from your server, a simple reboot will reset everything (hopefully you have access to do a remote reboot from a web interface, or maybe you can just walk up to the machine and reboot it).
At some point though, you'll want to make sure your rules are persisted. Achieving this is a two step process. First, you save your rules to a file by using the iptables-save and redirecting STDOUT to a file:
iptables-save
iptables-save > /etc/iptables.rules
Second, and this depends on which distro you have but on debian/ubuntu, you make sure your rules are loaded on startup. Simply edit /etc/network/interfaces, find your interface, and add:
/etc/network/interfaces
pre-up iptables-restore < /etc/iptables.rules
to the list, so that it looks something like:
auto eth0 iface eth0 inet static address xxx netmask yyy gateway ddd pre-up iptables-restore < /etc/iptables.rules
That's it!
The hillbilly be all Java’d up these days. For coming on three weeks, I’ve been the lone developer on a project based on Google Web Toolkit. It’s a web framework (naturally) that allows developers to build applications in Java and compiles it down to JavaScript, CSS, and HTML. Scoff all you want, if it were any other company behind it, I’d probably be right there with you.
We considered quite a few technologies before landing on this one. We went through Ruby, Sharp Architecture, Open Rasta, Moo Tools, and probably several others. I can defend ending up Google Web Toolkit privately if you want but putting the thought process up in a public forum is going to lead to comments that I’m too tired to moderate these days. And yes, I’ve heard of Script #, too.
Coming at this from a .NET developer’s standpoint has been interesting. It’s surprising how much we take for granted in our IDE, for example. I’m still meandering my way through the keyboard shortcuts in Eclipse (after a brief fling with IntelliJ IDEA). One thing I’d really like is a keyboard shortcut for the GWT Compile button, which currently is available only via a toolbar button or a context menu, as far as I can tell. Was happy to find a VIM plugin for it too that works as advertised.
Not sure if this applies to Java in general but within the confines of the Google Web Toolkit, the ecosystem is freakin’ phenomenal. The documentation page alone encourages unit testing and the use of an MVP architecture. Once you start reading about it, you can’t help but stumble on a number of other projects:
The shocking thing from a .NET perspective is that these concepts are just sort of assumed. There’s little debate on whether dependency injection is necessary or whether passive view is overkill. Someone watched a presentation from Google IO last year, whipped up a command pattern project based on it, and lo! the people said it was good. Between support for Hibernate and the App Engine data store, I think people would look at you bug-eyed if you even suggested writing your own data access layer.
The downside to all this as that the tooling seems to be several steps behind what I’m used to in the Microsoft world. It’s still too early to make a fair comparison but even after digging a little deeper into Eclipse, I can’t imagine being quite as productive as I currently am in Visual Studio. Yes, there’s also IntelliJ but our anecdotal evidence suggests that neither Java IDE is seen as a de facto standard. For the moment, I’m sticking with Eclipse simply because all the documentation refers to it and the GWT and App Engine plug-ins for it work out of the box.
Couple of final shout-outs to two blogs that have been invaluable during the learning curve phase. First is Hive Development (currently featuring two posts on how to unit test MVP applications in GWT). Second is TurboManage, whose sample code is more detailed than many apps I’ve written.
Anyway, it’s been an interesting couple of weeks.
Kyle the Decaffeinated
From Robert the Grey, FubuMVC learns to speak Spark.
I've done the nearly solo OSS thing a couple times to mixed results. I'm painfully aware that good OSS projects have a deeper community of contributors than just one guy, and that's why I'm so thrilled to see this addition come into the nascent FubuMVC reboot from outside the Dovetail office.
In the past couple of Monads posts, we’ve talked briefly about the State and Reader Monads and their potential uses and misuses. Before this series completes, I have a few more to cover including the Writer, Continuation and eventually Observable monad. Today, we’ll get started looking at the Writer Monad and what it can do for us.
Before we dive deep into what the Writer Monad is, let’s go deeper into the motivation of why we might consider this approach. Like proper developers should when approaching a new concept, we should ask, “What problem are we trying to solve? What’s the motivation here?” else we end up with an over-applied solution to our problem. In this case, let’s take the simple example of logging or tracing in our application. Typically in logging scenarios, we could have the dreaded singleton logger.
let doSomething() = Logger.Instance.Log("Beginning doing something") // Doing something Logger.Instance.Log("End doing something")
Or perhaps, we could have an injected ILogger instance handed to us via a constructor for the purposes of logging.
type ILogger = abstract member Log : message : string -> unit type DreadedManager(logger : ILogger) = member __.DoSomething() = logger.Log ("Start doing something") // Do something logger.Log("End doing something")
Or even in other scenarios, we might imagine putting in some AOP behavior for the purposes of logging, but that may of course not be fined grained enough what we need. Instead of doing this, how about generating some output “on the side” in a more functional manner. What if we could instead write something like the following where I add two numbers (simplistic example I know) and then run the computation?
let addNumbers x y = writer { do! logMsg (sprintf "Adding %d and %d" x y) return x + y };; > val addNumbers : int -> int -> Writer<string list,int> > addNumbers 3 4 |> runWriter;; val it : int * string list = (7, ["Adding 3 and 4"])
What we’re seeing is that in my addNumbers function, I take two integer arguments and then log a message and finally return the computed value. What’s more interesting is the fact that we’re logging something physically alters the signature of our method to indicate such a thing is happening. When we compute our function, we not only get the result of 7 that we’re expecting, but also our transaction log as well. Then we can decide what we want to do with the log, for example persist it somewhere, clean it up, etc. So, how can we do this exactly?
So, now that we covered the motivations around what it is and why we might use it, let’s look at how we might implement it. In order to maintain both the transaction log and the return value of our method, we’ll need to create a container to hold these values. In this case, we have the Writer<’W,’T> where the ‘W is the writer, which in our case above was a simple string list, and the ‘T is the result of our method. We have a constructing function of our Writer which takes a function with no parameters and returns a tuple of our result and the log.
type Writer<'W,'T> = Writer of (unit -> 'T * 'W)
In addition, we’ll need a way to run our Writer so that we can return our tuple of our value and the log. Let’s create a function called runWriter which computes our Writer.
let runWriter<'W,'T> (Writer w) : ('T * 'W) = w()
Before we get started on the Monad part, there is another piece we need to understand, and that’s the Monoid.
Before everyone panics as I’ve brought up a work that sounds like Monad, just rest easy. In fact, it’s much easier to understand than the dreaded M word. A Monoid is an algebraic data structure with a simple associative binary operation and an identity element. Just to bring that into real-world speak, we could have a Monoid for natural numbers with an identity element of 0 and the associative binary operator of addition, or in the case of lists, we could have the identity element of an empty list and an associative binary operator of append. In Haskell, such a thing is implemented through a type class, but since in F#, we don’t have this, let’s instead create a simple interface to encompass the same behavior.
type IMonoid<'T> = abstract member mempty : unit -> 'T abstract member mappend : 'T * 'T -> 'T
In this instance, we have two methods we care about, defining our identity (mempty) and our binary operator (mappend). For example, we could implement a Monoid for a simple F# list such as the following:
type ListMonoid<'T>() = interface IMonoid<'T list> with member this.mempty() = [] member this.mappend(a, b) = a @ b
This instance in particular will come in handy when we’re talking about a simple logging solution. Our mempty simply returns an empty list of our ‘T objects and our mappend appends the first list to the next. Now, what we need is some sort of registration process for our IMonoid instances so that we could pick one up based upon the incoming type. We could use something like a Common Service Locator to do this and it could be idea for a testing situation, but for now, lets just hand roll a global associations which maps an instance of our IMonoid to our proper type.
type MonoidAssociations private() = static let associations = new Dictionary<Type, obj>() static member Add<'T>(monoid : IMonoid<'T>) = associations.Add(typeof<'T>, monoid) static member Get<'T>() = match associations.TryGetValue(typeof<'T>) with | true, assoc -> assoc :?> IMonoid<'T> | false, _ -> failwithf "No IMonoid defined for %O" <| typeof<'T>
Once we have this defined, we could add instances to this associations class such as a string list implementation:
MonoidAssociations.Add(new ListMonoid<string>())
And now we can use the associations class to call instances of our IMonoid for our functions of mempty and mappend.
let mempty<'T> = MonoidAssociations.Get<'T>().mempty let mappend<'T> a b = MonoidAssociations.Get<'T>().mappend(a, b)
After that little diversion, we’re now able to get back to the point of the post, the Writer itself. But outside of here, that’s probably the last time you’ll probably use the word Monoid. But, I’m sure now you could impress your friends with the use of said word.
As you may remember from the previous post, the monad must support three basic rules. First, a type construction, for each underlying type, we must be able to get the corresponding monadic type. Second, we must have a function that maps an underlying value to a value in the corresponding monadic type, which is called the return function. Third, we must have a binding operation where the first argument is a value in a monadic type, its second argument is a function that maps from the underlying type of the first argument to another monadic type, and its result is in that other monadic type.
Let’s first tackle the return function. From our previous creating a Builder posts, we should remember that the Return should have the following signature where we take a value of T and then return it’s Monadic type.
type Builder() = member Return : 'T -> Monad<'T>
Our implementation should take a value of a and construct a Writer with a function with no arguments and return a tuple of our value and an empty Monoid instance.
type WriterBuilder() = member this.Return<'W,'T>(a : 'T) : Writer<'W,'T> = Writer(fun () -> a, mempty())
Next, we need to define the bind operation. The point of this method is so that we can bind two monadic types together such as two let! or do! statements. As you might recall, this method takes a Monadic type of ‘T and a function that takes a ‘T and returns a Monadic type of ‘U, and the return type of our bind should be the Monadic type of ‘U.
type Builder() = member Bind : computation : Monad<'T> * binder : ('T -> Monad<'U>) -> Monad<'U>
Our implementation should look like the following which creates a Writer with a constructed function which takes no parameters and then calls runWriter on our first Writer m which returns a tuple of our result and a log. We then execute the binder function with our result a which then gives us our second result and a log. Finally, we return a tuple of our second result with our two logs appended to each other.
type WriterBuilder() = member this.Bind<'W,'T,'U>( computation: Writer<'W,'T>, binder : 'T -> Writer<'W,'U>) : Writer<'W,'U> = Writer(fun () -> let (res1, log1) = runWriter computation let (res2, log2) = runWriter (binder res1) in (res2, mappend<'W> log1 log2))
You can find the rest of the methods in order to create a fully functioned builder as a Gist on my GitHub. Now let’s talk about some helper methods. The first, and most useful method is the tell which adds an entry to our log. This function takes a log entry and creates a Writer with a function that takes no arguments and returns a tuple of unit (void for some folks) and our log entry.
let tell logEntry = Writer(fun () -> (), logEntry)
Next up is the listen function. This allows us to listen to our log output that is being generated by our writer. This function takes a Writer and executes it while returning a tuple of our result and a log, as well as a log.
let listen writer = Writer(fun () -> let (result, log) = runWriter writer in ((result, log), log))
The last function we’ll cover is the censor function. This function returns a new Writer whose result is the same, but the alters the log based upon what is supplied as a parameter
let pass m = Writer(fun () -> let ((a, f), w) = runWriter m in (a, f w)) let censor censoredValue writer = writer { let! result = writer return (result, censoredValue) } |> pass
Ok, our helpers are now defined, so let’s go back and figure out how we’re going to log messages. If you remember from above, we have the tell function which does exactly that. Let’s implement that to take a message and call the tell function with our message wrapped in a list.
let logMsg (message : string) = tell [message]
Now we can try it out in such a function which does some file processing for us with some logging along the way.
let processFiles files = writer { try do! logMsg "Begin processing files" for file in files do do! logMsg (sprintf "Processing %s" file) processFile file do! logMsg "End processing files" with e -> do! logMsg (sprintf "An exception occurred %s" (e.ToString())) }
At the end of this method, it should return to us a tuple of unit and our log entries that happened along the way such as this:
> processFiles files |> runWriter;; val it : unit * string list = (null, ["Begin processing files"; "Processing C:\Test1.txt"; "Processing C:\Test2.txt"; "End processing files"])
This of course is a pretty contrived and simple example, yet pretty interesting nonetheless. But, in an impure world that we live in with such languages as F#, C#, etc, how practical is it? That’s another matter altogether and good arguments on both sides. Using a writer implies some sort of change to your system to allow for logging, whereas in a more impure environment, logging could take place everywhere. So, when dealing with an impure world already, just go with what you know.
Once again, by looking at Monads, we can discover what abstractions can be accomplished with them, but just as well, what they are not about. Certainly, functional languages don’t need them, but they certainly can be quite useful. When we find repeated behavior, such as logging, this abstraction can be quite powerful. Practically though in languages such as F#, they can be useful, but other patterns and abstractions can as well. Find the right abstraction and use it.
In my last post I discussed how to export configuration. A follow up question in the comments was “What if the values change?” Meaning the values that are exported using the approach I illustrated are static. In the real world however values often can change based on some user setting etc. A variant of the approach however allows the values to not be static. Instead of exporting a value, export a Func which returns the value. MEF offers nice support for this through method exports. For example to allow the “recently used file” config item to change over time, we can modify the Exporter to export that value as a method rather than a property.
public class RecentlyUsedTrackerConfiguration { private IConfigurationProvider _provider; [ImportingConstructor] public RecentlyUsedTrackerConfiguration(IConfigurationProvider provider) { _provider = provider; MaxItems = provider.GetValue<string>("recentlyUsedTracker.maxItems"); } [Export("RecentlyUsedTracker.File")] public string GetFile() { return _provider.GetValue<string>("recentlyUsedTracker.maxItems"); } [Export("RecentlyUsedTracker.MaxItems")] public int MaxItems {get;private set;} }
public class RecentlyUsedTrackerConfiguration
{
private IConfigurationProvider _provider;
[ImportingConstructor]
public RecentlyUsedTrackerConfiguration(IConfigurationProvider provider)
_provider = provider;
MaxItems = provider.GetValue<string>("recentlyUsedTracker.maxItems");
}
[Export("RecentlyUsedTracker.File")]
public string GetFile() {
return _provider.GetValue<string>("recentlyUsedTracker.maxItems");
[Export("RecentlyUsedTracker.MaxItems")]
public int MaxItems {get;private set;}
Instead of exporting a property, we are now exporting the GetFile method. Method exports are imported as delegates, thus RecentlyUsedTracker now looks like this.
[Export] public class RecentlyUsedTracker { [Import("RecentlyUsedTracker.File")] public Func<string> File {get;set;} [Import("RecnetlyUsedTracker.MaxItems")] public int MaxItems {get;set;} }
[Export]
public class RecentlyUsedTracker {
[Import("RecentlyUsedTracker.File")]
public Func<string> File {get;set;}
[Import("RecnetlyUsedTracker.MaxItems")]
public int MaxItems {get;set;}
Notice above we are importing a Func<string> for the File item rather than string. This gives us the hook to dynamically change File each time it is accessed. You could even go further an parameterized File if you wanted to pass in context to determine which File is returned.
With this approach RecentlyUsedTracker is still easy to test. With lambda syntax it is pretty painless to pass in test values when the class is under test.
For over a year I have been using Server 2008, 64 bits, as OS for my laptop. The main reason for this platform was Hyper-V. Almost every other project I’ve been working on needs another virtual server. And each location I am working has a different network. With Hyper-V both switching servers and switching networks works fast and good. The downside of using Hyper –V is that it knocks out all possibilities of hibernating or putting my laptop to sleep. Server 2008 R2 boots a lot faster, but still. Another downside is that to use Hyper-V you have to run the 64 bit versions, R2 only comes 64 bits. Visual studio is a 32 bit app, runs OK on 64 bits but it is still not the most stable piece of software I know.
Due to circumstances I had to use my laptop more and more in typical mobile situations. Also the way my colleague presses the power button, is back where he was, does his thing, closes the lid and just walks away made me a little jealous. Perhaps I should move on to Windows 7 and try Virtual PC 2009. I had played with that combination and it looked promising.
To see if this was a good idea I set up some some tests
All version of hyper-V and virtual PC share the same virtual hard disk (vhd) format. They differ on the integration features, some piece of host specific software installed on the virtual machine to facilitate all communication with virtual machine. Both Hyper-V and Virtual PC have “Install integration features” as menu option.
As a test candidate I took a virtual machine with quite a history. It started its life in Virtual PC 200x as a Windows server 2003 machine with several monsters of sql 8 databases, sql reporting services and some COM custom app. Over the years it had been upgraded tot server 2008 and been living under several versions of Virtual server and Hyper –V. Not something to rebuild from scratch, just getting that version of reporting service to work is a piece of science on itself. In short: a typical real world machine. Under the several host OS-es it had seen several completely different versions of integration services. These were pretty screwed up. Every attempt to install the newest integration services resulted in messages complaining about previous versions. But the machine still worked.
The official recipe to migrate a virtual machine is to uninstall integration services, move the machine and reinstall the integration services of the new host. But you will not find integration services under the installed programs. All attempts to uninstall form the command prompt (/Uninstall) only resulted in the same messages about previous versions.
What worked is changing the HAL (Hardware Abstraction Layer) of the virtual machine:
After that I just shut down the machine, copied the hard disk and created a new virtual machine in W7 Virtual PC using the copied vhd file as hard disk.
The machine booted and complained about requiring new drivers. It also required renewed activation. I installed the W7 Virtual PC integration services and allowed the renewed activation (which is never a problem with MSDN OS licenses). And after that the machine just worked fine. All integration was smooth, all software had perfectly survived the migration.
I can be short on this. This works just as smooth as in Hyper-V
Changing the adapter in the settings is instantaneously reflected in the status of the virtual machines adapter. The good thing is that everything works just as well with an adapter with a dynamic IP address as with one with a static address.
The difference between sleep and hibernate is that in sleep mode the RAM of the PC is still powered, so actually the machine is still alive. In hibernate mode all RAM is saved to and restored from disk.
In Hyper-V the virtual machines are running on the machine level. In virtual PC you start a virtual machine as a logged in user. When logging off the virtual machines are shut down (or hibernated). Instead of logging of I tried both sleep and hibernate with the virtual machine still running. Again all news is good. All functionality completely survives both scenarios. Virtual PC is not ignorant of my actions. When hibernating it will (automatically) disable the integration services. When awakening it restores them.
The only hurdle I had to take was the HAL setting when migrating the machine. All the rest just worked. So I repaved my laptop with Windows 7 and virtual PC 2009. (Just skip the virtual XP step unless you need a virtual XP machine). I was quite satisfied with Server 2008 (except the required full boot) but do like Windows 7 even better. VS worked well and now even works better. But that could be the result of a fresh install (there is no upgrade possible from 2008 to 7).
And now I can also close the lid of my laptop and leave the building.
This is a different project than the one we hired for last time. If you've spoken to us before, please consider this position separately.
We're expanding the development team on our line of existing products. You'll be working on a small team that develops applications for large businesses using some of the latest technology. You will be involved in all aspects of solution development, including analysis, design, development, testing, documentation, and support.
We’re looking for a software developer with demonstrable C# (preferably .NET 2.0 or later) and HTML/CSS experience (ASP.NET MVC is a plus). Any experience with test-driven development or automated unit testing in general is a huge plus. Also, participation in the community (attendance of events, avid blog reader + commenter, or maybe you even have a blog yourself) will put you firmly in the running for this position. We’re looking for people that believe learning and continuous improvement are primary responsibilities of a software developer. We’re hiring motivated people for a terrific opportunity with a team of recognized .NET and agile community leaders.
Our practices and technologies include:
Email us and tell us why you’d make a great addition to our team: tech-jobs@dovetailsoftware.com
This is a full-time, on-site position in our Austin, TX office. Please DO NOT contact us for outsourcing or tele-commuting.
Yesterday I was able to “push” into Github the work I’ve been doing for convention based Html generation in FubuMVC. What the hell is “convention based Html generation?” you ask? It’s simple in concept. Your team has policies, formal or informal, for how you build Html elements for the fields in a ViewModel. If your familiar with MvcContrib’s Opinionated Input Builders or MVC2’s Templates feature (very well described by Brad Wilson here), we’re doing the same thing conceptually but with much different mechanics. Right now, I’m focused on the very basic building block methods that appear on FubuMVC view’s (remember that we basically force all views in FubuMVC to be strongly typed with a single ViewModel):
I’m dubious that the form auto-generation stuff that MVC2 does has much real world value, but it would certainly be possible to build on top of what we already have. In a follow up post I'll show more of the DSL-ey approach for creating simple forms that uses InputFor/DisplayFor/LabelFor as building blocks.
In our system we have a small Entity class named Address (all systems of any complexity have an “Address” class, but they’re all different) with a property for the first line of the address called Address1:
[Required, MaximumStringLength(250)]
public string Address1 { get; set; }
Leaving the appropriateness of the approach aside (it’s working very well), we use attributes for our simple validation rules (and also use those to generate “not null” / string length types of rules in our database). On the client side, we use jQuery Validation to do input validation in the browser. jQuery Validation is very simple to use (as long as you color within the lines). All I need to do is add classes and some attributes to the <input> and <select> elements to declaratively apply validation rules.
In usage, we could build the input Html element for a field by just calling InputFor() like this:
<dd><%= this.InputFor(m => m.Site.PrimaryAddress.Address1).Id("site-address1")%></dd>
In our Dovetail system the above call generates this Html:
<input id="site-address1" class="required" type="text"
name="SitePrimaryAddressAddress1" label="Address 1" maxlength="250" value=""/>
Did you see what happened there? When we create an input element for the Address.Address1, the conventions:
By the way, did you see how I overrode the “id” property of that textbox? I’ll talk more about that at the bottom, but that represents a huge advantage that FubuMVC’s model has over both MvcContrib and MVC2. You can happily modify or enhance the convention-generated Html input on a case by case basis.
One of the overarching principles of FubuMVC is to push the usage of Convention over Configuration as far as it can go while still allowing FubuMVC adopters to create and add their own conventions. The Html conventions are no different. When you register / configure conventions for the Html you can register either “Builders” that know how to generate the HtmlTag (I’ll explain HtmlTags later) for a certain class of properties:
public delegate HtmlTag TagBuilder(ElementRequest request);
public interface IElementBuilder
TagBuilder CreateInitial(AccessorDef accessorDef);
or “Modifiers” that enrich HtmlTag’s:
public delegate void TagModifier(ElementRequest request, HtmlTag tag);
public interface IElementModifier
TagModifier CreateModifier(AccessorDef accessorDef);
These ElementBuilder’s and ElementModifier’s can either be classes that you build yourself and “plug” in, or you can use the Html convention DSL shown below to create common, simple types of policies (think, if this attribute exists, add this class). A custom ElementBuilder might look like this:
// This builder is only for creating the display tag
// for a date time field on one of our "activity log"
// models
public class LogDateDisplay : ElementBuilder
// Does this builder apply to a property?
protected override bool matches(AccessorDef def)
return def.ModelType.Closes(typeof (LogViewModel<>)) && def.Accessor.PropertyType.IsDateTime();
// Renders a date in long time format and also sticks the header
// text into the title attribute
public override HtmlTag Build(ElementRequest request)
string title = LocalizationManager.GetHeader(request.Accessor.InnerProperty);
return new HtmlTag("span").Text(request.ToDisplay("{0:F}")).Title(title);
Alrighty, let’s move on to registering our conventions. From the top, I create a class to hold my project’s Html conventions like so:
// HtmlConventionRegistry is the base class that provides the DSL
// This is an example of "Object Scoping" from Fowler speak like
// StructureMap's Registry and Fluent NHibernate's ClassMap
public class DovetailHtmlConventions : HtmlConventionRegistry
public DovetailHtmlConventions()
validationAttributes();
numbers();
Profile("edit", x => x.Editors.Builder<EditInPlaceBuilder>());
editors();
Labels.Builder<LabelBuilder>();
Displays.Builder<LogDateDisplay>();
Displays.Builder<DisplayBuilder>();
private void editors()
Editors.Builder<ValueObjectDropdownBuilder>();
Editors.IfPropertyIs<bool>().BuildBy(request => new CheckboxTag(request.Value<bool>()).Style("width", "auto !important").Attr("value", request.ElementId));
Editors.Always.Modify((request, tag) =>
tag.Attr("label", request.Header());
tag.Attr("name", request.ElementId);
});
// Ugly hack because of the hacky Edit in Place jQuery plugin we use, but
// I'm gonna kill it some day
Editors.IfPropertyTypeIs(t => t.IsDateTime()).Modify(x =>
if (!x.HasMetaData(EditInPlaceBuilder.EDITABLE_ATTRIBUTE_NAME))
x.AddClass("DatePicker");
// Setting up rules for tagging elements with jQuery validation
// metadata
// I think that a lot of this gets added into the core Fubu as a
// "jQueryValidationPack"
private void numbers()
Editors.IfPropertyIs<Int32>().Attr("max", Int32.MaxValue);
Editors.IfPropertyIs<Int16>().Attr("max", Int16.MaxValue);
Editors.IfPropertyIs<Int64>().Attr("max", Int64.MaxValue);
Editors.IfPropertyTypeIs(t => t.IsIntegerBased()).AddClass("integer");
Editors.IfPropertyTypeIs(t => t.IsFloatingPoint()).AddClass("number");
// Declare policies for using validation attributes
private void validationAttributes()
Editors.AddClassForAttribute<RequiredAttribute>("required");
Editors.ModifyForAttribute<MaximumStringLengthAttribute>((tag, att) =>
if (att.Length < Entity.UnboundedStringLength)
tag.Attr("maxlength", att.Length);
Editors.ModifyForAttribute<GreaterOrEqualToZeroAttribute>(tag => tag.Attr("min", 0));
Editors.ModifyForAttribute<GreaterThanZeroAttribute>(tag => tag.Attr("min", 1));
The basis for FubuMVC’s Html conventions, and the big differentiating feature from the MVC2 and MvcContrib approach, is the usage of the “HtmlTags” library as a semantic model. All the Html generation in FubuMVC works by building up HtmlTag objects that represent an Html element graph (HtmlTag’s can have children). Think of the old TagBuilder class on steroids. A picture’s worth a thousand words, so let’s see some samples of HtmlTag in action:
// Setting the inner text and adding a class
HtmlTag tag = new HtmlTag("div").Text("my text").AddClass("collapsible");
// adding "MetaData" for the jQuery MetaData plugin
HtmlTag tag = new HtmlTag("div").Text("text");
tag.MetaData("a", 1);
tag.MetaData("b", "b-value");
[Test]
public void render_multiple_levels_of_nesting_2()
HtmlTag tag = new HtmlTag("html").Modify(x =>
x.Add("head", head =>
head.Add("title").Text("The title");
head.Add("style").Text("the style");
x.Add("body/div").Text("inner text of div");
tag.ToCompacted().ShouldEqual(
"<html><head><title>The title</title><style>the style</style></head><body><div>inner text of div</div></body></html>");
The HtmlTag model has been hugely advantageous because:
HtmlTags is a separate library within FubuMVC that can be used independently (I use it in StoryTeller now).
I’ve had this feature, and even the technical direction, in mind since last summer. I finally got to build it out for Dovetail usage because we needed to change the way we do configurable lists in our system. We keep list data in a database table where it’s easily editable and extensible (even to the point of adding cascading relationships after the fact for customizations). We need to validate certain fields against that list data, so we mark those fields like this:
// There is no logic associated with Origin
// other than externalized rules, so having it
// be a string does no harm
[Required, ValueOf(ListNames.Origin)]
public string Origin { get; set; }
Anytime a property is decorated with the [ValueOf] attribute we know that we need to build a dropdown list to edit that field. All the information that we absolutely need to know to construct that dropdown is available on the property itself, so it made perfect sense to move to convention based Html construction instead of all the repetitive “put list data on ViewModel in Controller, transmit to View, fill options in View code” work we were doing before. We cache the list data in a static class called ValueObjectRegistry that can give us list data. Using ValueObjectRegistry and the Html Conventions gave us this:
// Builds a <select> tag and fills in the list values
// for any property in our system that is "marked" as being
// a list field
public class ValueObjectDropdownBuilder : ElementBuilder
return def.Accessor.HasAttribute<ValueOfAttribute>();
string defaultValue = request.Value<string>();
if (defaultValue.IsEmpty())
request.ForListName(name =>
ValueObject @default = ValueObjectRegistry.FindDefault(name);
if (@default != null) defaultValue = @default.Key;
return new SelectTag(tag =>
request.EachValueObject(vo => tag.Option(vo.LocalizedText(), vo.Key));
tag.SelectByValue(defaultValue);
public static HtmlTag Build(string listName)
ValueObjectRegistry.GetAllActive(listName).Each(x =>
tag.Option(x.LocalizedText(), x.Key);
var defaultVO = ValueObjectRegistry.FindDefault(listName);
if (defaultVO != null)
tag.SelectByValue(defaultVO.Key);
Now that we have ValueObjectDropdownBuilder hooked into our Html conventions, all I need to do on the view is just say: “InputFor(x => x.Case.Origin)” and let the conventions handle everything.
Any questions?
I’m imagining the thought process of some of the session voters for the upcoming Mix conference. “Hey, here’s one on Open Rasta by the Coding Hillbilly. You know what would be funny? Let’s all vote for it even though he just submitted it on a lark to get some practice after taking time out from speaking engagements. It’ll be fun watching him explain to Mrs. Billy that he *has* to go to Vegas four weeks before he’s heading to Philadelphia for Udi Dahan’s course.”
Yeah, you’re all a bunch o’ comedians, ain’t ya. Well, I’ll show you. You’ll go to my Open Rasta session ready to watch me squirm and you’ll see no such thing. I don’t want to overhype it or anything but I can tell you without a doubt that this session is going to restore your virginity and then take it from you again. Savagely (but tastefully; last thing I need is a bunch of people accusing me of statutory rape in the middle of a presentation). Then maybe next time you’ll think twice before crossing a coder of the earth, woncha!
Couple of interesting tidbits on the session:
So while you’re waiting for Mix, have a gander at Open Rasta to see what all the hubbub is about. Between this and my new contract using Google Web Toolkit, that should set the stage for my post activity for the next few months.
Kyle the Bastardized
I recently needed a configuration mechanism which would detect changes without requiring an application domain restart. I also wanted to move away from XML. This is what I came up with (and hopefully I'll get some helpful feedback).
First, we declare a ConfigurationData object which holds our actual configuration values:
public interface IConfigurationData { bool LogAll{ get; } string CdnUrl{ get; } } public class ConfigurationData : IConfigurationData { private bool _logAll; private int _cdnUrl; public bool LogAll { get { return _logAll; } set{ _logAll = value; } } public string CdnUrl { get { return _cdnUrl; } set { _cdnUrl = value; } } }
There isn't much to explain here, so let's move on to the class that does the heavy lifting:
public static class Configuration { private static readonly string _applicationPath = HttpRuntime.AppDomainAppPath; private static ConfigurationData _instance = LoadInitialConfiguration(); public static IConfigurationData GetInstance { get { return _instance; } } private static ConfigurationData LoadInitialConfiguration() { var watcher = new FileSystemWatcher(_applicationPath, "settings.config"); watcher.NotifyFilter = NotifyFilters.LastWrite; watcher.Changed += (s, e) => _instance = LoadConfiguration(); watcher.EnableRaisingEvents = true; return LoadConfiguration(); } private static ConfigurationData LoadConfiguration() { return Converter.DeserializeFromFile<ConfigurationData>(_applicationPath + "settings.config", "_"); } }
The class essentially loads the ~settings.config file, and sets up a watch to reload it whenever it changes. Here I'm using JSON (and my own JSON library) to read the file, but you could use anything, such as yaml or xml. The file might look something like:
~settings.config
{ "logAll": true, "_cdnUrl": "http://cdn.mysite.com/" }
If you are using a DI framework, such as ninject, you can hook it via:
Bind<IConfigurationData>().ToMethod(c => Configuration.GetInstance);
otherwise, you can call it directly from code with:
if (Configuration.GetInstance.LogAll) {...}
There are two things you'll need to be careful with. First you'll want to make sure to avoid caching values within a class. For example, if you did something like:
public static class HtmlExtensions { private static readonly string _cdnUrl = Configuration.GetInstance.CdnUrl; }
then a copy of CdnUrl would be stored in _cdnUrl and changes to your file wouldn't be available to this class.
CdnUrl
Secondly, the Changed event is known to fire twice. This shouldn't cause any threading issues, but if your LoadConfiguration is particularly intensive, or if you happen to be debugging something, then you'll at least know to expect it.
Changed
About CodeBetter.ComCodeBetter.Com FAQOur Mission Advertisers should contact Brendan
Subscribe
Google Reader or Homepage del.icio.us CodeBetter.com Latest ItemsAdd to My Yahoo! Subscribe with Bloglines Subscribe in NewsGator Online Subscribe with myFeedster Add to My AOL Furl CodeBetter.com Latest Items Subscribe in Rojo
Member Projects
Sarasota Web Design - David HaydenPatterns & Practices - David Hayden dotMath - Steve Hebert Structure Map - Jeremy D. Miller StoryTeller - Jeremy D. Miller The Code Wiki - Karl Seguin
Friends of CodeBetter.Com
Red-Gate Tools For SQL and .NETTelerik ComponentArt VistaDB JetBrains - ReSharper Beyond Compare .NET Memory ProfilerNDepend Ruby In Steel SlickEdit SmartInspect .NET Logging NGEDIT: ViEmu and Codekana LiteAccounting.Com DevExpressFixx NHibernate ProfilerAForge.NET UnfuddleBalsamiq Mockups Scrumy <-- NEW Friend!
Site Copyright © 2007 CodeBetter.Com Content Copyright Individual Bloggers