Saturday, June 19, 2010

Tiny DSLs In The Code

I wanted to explore a little on the LINQ vs. lambda that Dave mentioned. I really don't have a direction for this post but wanted to get some thoughts down and see what others were thinking. Also it should be noted that I'm talking mostly about the IQueryable abilities and the two methods of using them (LINQ: from x in list where x.valid select x, and lambda: list.Where(x => x.valid))

The lambda syntax he mentions is just strictly straight up C#. You chain together the methods giving them the lambda expressions for the various actions to perform on the queryable you are working with. You get to build up what you want on a lazy evaluated data structure and it flows fairly cleanly inside C#.

There are some advantages to this, someone familiar with the basic idea of method chaining and the language idea of lambda expressions can easily understand the flow of the code. This sort of internal DSL gives us the ability to take advantage of language features and try to produce more expressive code. Several OSS libraries in the .NET world have certainly picked up on the fluent interface idea which is an internal DSL practice.

Then we have the LINQ syntax. It allows us to also build up what we want and have it lazily evaluated but now the you are working in a language that isn't really a part of C#. Although LINQ is a language feature of C# it still is more of an external DSL. It's a small language implemented on its own. Thankfully the compiler fully understands this DSL and can convert it to the expressions to form a fully valid C# program. You can still chain actions off of it and pass it around, but you are given a new language to express the idea with and not only relying on C#.

Now someone needs to know this new language in order to understand your code and not just C#. Perhaps LINQ is a bit of a simple example, but this new language can provide create expressiveness and higher levels of thinking. These are generally great but again now someone needs to know two languages. This second language though is purposefully designed to be smaller, stricter, more focused, and more expressive in its domain. Naturally I'm speaking about DSLs and their advantages and disadvantages.

I wonder if DSLs will generally catch on. Like I mentioned in a comment on Dave's post the Ruby world seems like enjoy some DSLs. They are still really internal DSLs since they are implemented in and used in Ruby which is a general programming language but Ruby's flexibility in syntax allows for them to produce some pretty interesting results. I suppose the most famous is RSpec and how it can help a developer very expressively and cleanly say what his/her code is suppose to do. This does mean that you now have to learn how to write this new DSL but in return it offers a more natural and less ambiguous way to write what you mean.

.NET does have Boo which is pretty cool language. It's a general statically typed programming language on the CLR. Python inspired syntax but it has a very extensible compiler and a built in idea of macros. You can actually define new syntax in Boo with Boo. So you could actually write the core of the system in C# and then have areas that you write in a DSL in Boo that when compiled gets tied into the system (such as maybe a rules engine on customer pricing). Or you write the whole thing in Boo.

Now all this DSL stuff certainly brings more overhead and higher level of entry for a new developer so I'm curious what everyone's thoughts are. Do you think they are worth it? Has promise? Some people feel that proper use of DSLs or just in general polyglot environments are going to be what allows us to manage complexity better and improve our disciple. Instead of hitting everything with a hammer, you could add in a saw, coat hanger, and duct tape.

The .NET ecosystem of languages has certainly expanded with F# and IronPython being supported languages, let alone all the others that are out there. The Java world seems to embrace their ecosystem of languages and although many feel Java the language has become fairly stale the JVM has still been continuing to explode with ideas. Perhaps I should write a post about my thoughts on the big differences I feel between the .NET and Java world (mostly about open mindedness and OSS).

Anyway again, What do you guys think about polyglot environments and DSLs both internal and external?


  1. There's definitely a two-sided coin here. On the one hand, development shops generally want to homogenize their tools in order to keep the risk of unsupportability low. And on the other hand, you don't want to get in the habit of using a golden hammer.

    It's generally been my opinion lately to be more weary of the latter than of the former. Good developers can support good code. Bad developers can even support good code. But nobody can support bad code. And the language in which the code was written has very little bearing on its quality. Using a golden hammer can (and often does) very easily lead to improperly expressing a solution because the hammer wasn't really designed to solve that problem.

    (On a side note, that part about the language not really mattering reminds me of something my friends and I noticed back in school. Listening to other CS majors compare skills, you could easily tell who was new to the trade and who was more seasoned. Freshmen bragged about which languages they knew, seniors bragged about which design patterns they'd implemented and how they applied them to solve real problems. Even back then, in our youth and ignorance, we learned that the tools matter less than the design.)

    For example, despite my general preference of lambda over LINQ, I fully admit that there probably exist a wide variety of problems where the solutions are more clearly and effectively expressed using LINQ than chaining function calls with lambda syntax in them. It probably just so happens that I've barely touched upon that host of problems given that:

    1) LINQ is very much designed after database-style expressiveness;
    2) My personal experience with databases has always been fairly simple and straightforward, nothing terribly involved.

    But even with my preference and the quantum of elation I get when writing particularly cool lambda, I would be the first to call shenanigans if a decision maker for a development team ever decreed that "thou shalt not use LINQ in our environment." It would incite in me the same distaste as when somebody says "we can't use [insert tool here], we're a Microsoft shop." Last I checked, we're not owned by Microsoft. And I would think it foolish to place the business decisions for a company in the hands of another company that:

    1) Doesn't know or care who we are;
    2) Has a history of destroying other companies to improve its own bottom line.

    Don't get me wrong, Microsoft makes some great tools. So does Craftsman, but you won't see me driving a lawnmower to work each morning. The .NET Framework was designed to do a lot of things, "everyone should convert everything to C#" wasn't one of them.

    So I guess the point is that those tiny DSLs are a very good thing if used properly. Having a separate shared library written in BOO in one's C# environment can be great, as long as it exists for the right reasons. Was that library written in BOO because BOO allowed the developer to simply and clearly express a solution to a problem, or was it written in BOO because the developer just learned about BOO and thought it would be cool to use? The former should be encouraged, the latter is a pyrite hammer.

  2. Yeah, I think we are thinking a like on this topic. There certainly can be a lot of power by mixing languages (small and large), but there certainly has to be a balance. Finding this balance in everything we do has got to be the most difficult task in our field.

    Sure what you do right now can get the job done, but hopefully you care about making yourself and your code better. I am starting to feel that at some point this might include a more polyglot environment. Maybe a dynamic for UIs since they are generally lighter weight and require a lot of tweaks, maybe a functional language for the more algorithmic manipulation of data, static object-oriented language for the more well defined management of relationships between things, and possibly more. I think as the complexity goes up the effectiveness of a single language might go down.

    Certainly someone with enough solid experience in programming can pick up more languages and keep track of the syntax and culture around the languages they work in. So I don't think it's too much of a worry about trying to find someone with your exact skill sets that your job requires (this will most likely get harder over time anyway). I think it's more about finding someone that is good and that will stay with you.

    Also I think that to make sure that things are not thrown in just because they seem cool you need to give your team some room to experiment. There is a lot of value in Google's 20% time. Every one of their employees can work on whatever they want and this leads to people collaborating and coming up with some innovative ideas. It's where most of Google's popular products have come from.

    I think having this time to experiment when things would lead to less flaky ideas working their way into the production code. I heard about a company in Australia that does a similar thing but they call it Fed-Ex days. They get 24 hours (I don't know if that is a single day or 24 hours of work hours) to deliver something. They said it actually leads to some difficult tasks being tackled and solved. After the time period everyone presents on what their project was.

  3. Man I'm certainly missing using Python and Django now that I'm back on WebForms. It's a bit irritating to have to add that extra step of compiling or running the web application to play around with changes. I certainly get more and more respect for developing using such light weight (for the developer) tools like Django auto-reloading development server and Python's dynamic and interpreted style.

    Perhaps one day IronPython's compatibility will be high enough to run Django cleanly. I believe now it can run it with a few changes but I don't know how stable it is. I know IronPython 2.6 has on average more performance then CPython (the standard implementation) 2.6.