8/29/07

Making ICollection inherit from more fine-granular interfaces

In my previous post I hinted about a rule which I apply to the design of interfaces:

An interface should have at most one member.

This is to emphasize, that interfaces often model abilities that are mixed in to the main entity. And you mostly need only one member to model an ability.

To illustrate this, here's an example. Sometimes I regret that System.Collections.Generic.ICollection<T> doesn't consist of such more fine granular little interfaces. It would really make things simpler in some scenarios. For example, consider a method which adds a lot of stuff into some bag:
void AddLotsOfStuff(ICollection bag)
{
bag.Add(stuff1); ... bag.Add(stuff1000000);
}

Now my problem is this. I'd also like to also pass objects that don't implement ICollection into this method. I'd only implement the Add method and I don't want to additionally implement Remove, Count, IsReadOnly etc. If ICollection would inherit from IAllowsAdd, things would have been much more simple:
void AddLotsOfStuff(IAllowsAdd bag)
{
bag.Add(stuff1); ... bag.Add(stuff1000000);
}
I'm using only the Add ability of the bag inside the method anyway, so I don't care about other ICollection abilities - I don't need them here. And now - voila - I can pass ICollections and my custom objects that solely implement IAllowsAdd.

You might ask: why not simply return stuff in an IEnumerable instead of stuffing it into a bag passed as parameter? Well, one could do that, but this would be a little slower - we need some temporary storage where we'd store the output before we actually put it in the bag outside. In time-critical scenarios you can save a lot of time if you directly put your stuff into the bag instead of first returning it and then putting it into the bag somewhere outside the method.

A more concrete example - imagine some code editor would like to show an IntelliSense drop down list box with 1000 words and you have a GetPossibleCompletionWords() method that is supposed to put a 1000 strings into the listbox. If you first return the strings, you have to accumulate them in some temporary list first:
StringList results = new StringList();
results.Add(word1); ...
return results;

This costs both time and memory. Even if you use iterators and yield return, you will have additional costs connected with storing the method's control flow state machine in the heap. It saves you a lot of time if you directly insert the words into your destination listbox and pass the listbox as a parameter. However, you have a problem: your listbox doesn't implement ICollection. But it does implement IAllowsAdd (or IFillable, or ICanAddStuff or whatever).

That's why I wish the ICollection interface of the .NET Framework would actually consist of more fine granular interfaces which could be reused in places where I don't need the entire collection. And - who knows - maybe such interfaces will be introduced sometime in the future, because splitting an interface into several new interfaces is not a breaking change - one could continue to use existing ICollection, but one also would get new, reusable interfaces like IAllowsAdd, ICountable, ISet, etc.

Please let me know what do you think about it - I welcome your opinions, ideas and suggestions.

Update: it seems that there is a nice workaround with delegates. You can just pass a delegate as parameter to the method. This delegate can point to any Add method you like. This would be even more flexible than using fine-granular interfaces. Hmm... this sounds good: everywhere where you'd use an interface with one method, you could actually use a delegate instead. The performance tradeoff would be virtual call vs. delegate invocation.

Choosing: Interface vs. Abstract Class

Interfaces and abstract classes in .NET are pretty similar in functionality - you can't instantiate them, but still objects of various runtime types can hide both behind an interface or behind an abstract class. So when to use which?

The "Framework Design Guidelines" book by Brad Abrams and Krzysztof Cwalina is a very good book for all those who like asking such questions. Particularly, there is a whole section 4.3 "Choosing between class and interface" discussing this issue. I'll spoil the plot ending and post the main advice right away:

Do favor defining classes over interfaces.

The main argument of the authors is flexibility of classes. This applies mostly to layered architectures, where a client layer uses the framework layer. Classes can provide default implementation, so even if you already have derived classes in your client layer and you're adding a new virtual method to your base class in the framework, the clients won't even have to recompile their derived classes - the new virtual method magically appears in the derived types automatically and you don't have to change anything in the client. On the contrary, if you add a new method to an interface, which is already being implemented by some clients, you can't provide the default implementation - it would introduce a breaking change (all clients would have to manually add methods to implement the new method of the interface).

This is a very good point - once you ship an interface you basically can't change it anymore - it's carved in stone starting from the very moment anyone on the client side implements it. Unless you want to break that client and make them recompile or even worse - re-deploy.

When I was developing an editor for C# it was based on a framework for editors. During design of the framework and the editor, I learned a lot about how to use interfaces (more precisely, how not to use them). Now I want to share my experiences with you to add a couple of measly cents to the dollars of wisdom of .NET architects.

My whole editor framework is built around a concept of a 'block' - a rectangular thing which can be displayed on the screen and contain text and other blocks. The framework is basically a hierarchy of classes that inherit from the Block class. If you're familiar with the Composite design pattern and the text editor example from the GoF book, you'll immediately recognize that blocks are simply Glyphs - basic elements from which documents are composed. Now, I had an interface IBlock and an abstract class Block, which implemented IBlock. As it turned out many lines of code later, this was the most stupid thing to do:

  • Anytime I wanted to add new members to the class hierarchy, I had to update both the base class and the interface

  • Once I'd ship the IBlock interface and a client would implement it, I wouldn't be able to add anything to it anymore

  • The only situation where IBlock would be useful is when some client would want to implement it without inheriting from Block - and who on earth would ever want that?

I removed the IBlock interface and changed all its usages to use the abstract class Block instead. This simplified my life so much.

What I've learned from this: interfaces are good when you want to work with some distinguished feature or ability of an entity, and not the whole entity. For example, if you want to enumerate something, it is sufficient for you to receive an IEnumerable - you don't care about the rest of the entity. It can be anything, of any complexity - for you is only important that it allows to enumerate itself. A good occasion to use an interface is having many base classes - you don't have to inherit from Collection, you have various base classes and the only thing you have to do is to implement IEnumerable. As I said, interfaces describe part of the functionality, and you can mix-in this functionality to existing class hierarchies without adding a new base class.

Classes, on the opposite, are good for modeling whole entities, entire complete entities as a whole. That was my mistake - I used an interface for the whole entity "Block", where I should have used a class instead. With classes, you can't mix in a new base class to an existing one - that would mean merging two clearly separate stand-alone entities into some weird-looking hybrid. That is one of the reason multiple inheritance is not allowed in .NET - you shouldn't mix entities together, it's not a good practice. On the opposite, you should do your best to separate your entities from one another. It's like normalization of relational databases - you split your tables until each table describes a clearly defined entity with exact boundaries and strictly defined connections and relationships to other entities.

A common design mistake is called "burning the base class" - it's when you make your whole hierarchy inherit from some base class just to add some functionality to the entire class hierarchy in one simple step. As a rule, this functionality doesn't represent a separate, stand-alone entity, but still you waste your base class to add partial functionality. As I said before, interfaces are best when you want to add part of a functionality - you can mix it in to an existing hierarchy without burning the base class. An example of burning the base class is a System.MarshalByRefObject from the .NET base class library. Clearly, we waste a base class of all Windows Forms controls just to add some ability to all the classes at once. Adding an ability is done best by interfaces. However, this way requires more typing because an interface can't provide a default implementation.

To reiterate: use classes to model whole entities, and use interfaces to add abilities to existing entities. The only exception to this rule I can currently think of - is when you don't want your entities to be extended in the future. That is, you'd like to specify a precise contract for an entity, and you can guarantee that this entity won't have additional abilities in the future - at least not in your scope. Then, it's OK to use an interface to capture the entity and carve it in stone. Clients are free to add functionality to this entity, but you don't want to see it in your framework. You'll only work with this strictly defined entity and it's not going to change.

Finally, I've discovered a rule of thumb for myself which generally helps me to use interfaces correctly. An interface should define at most one member. Yes, that easy. One could even have an FxCop rule for it. If you want to define an ability on some entity, one member is mostly enough: GetEnumerator() for an enumerable, Clear() for a clearable, Count for countable and so on and so forth. If you want a more complex ability or a composed entity, use interface inheritance:

ICollection : IAllowsAdd, IAllowsRemove, IEnumerable, IClearable, Indexable, ICountable, ISet

Purists can push this rule even further:
An interface can either:
  1. declare no members and inherit from no interfaces ("a marker interface"), or

  2. declare a single member, or

  3. inherit from two other interfaces.

This would be some minimal "interface normal form" à la Chomsky, to which any interface hierachy could be reduced. Unfortunately, this mathematically beautiful "normal form" wouldn't be practical for everyday development.

kick it on DotNetKicks.com

8/28/07

Structured editors

This post is about structured (or syntax-driven) code editors and my experiences in this area. Here right away some screenshots as a bait - how my current structured editor implementation looks like.

Structured editing - to be or not to be?

Structured editing is a topic surrounded with scepticism and controversy for the past 20 years. Some argue that directly editing the AST on screen is inflexible and inconvenient, because the constraints of always having a correct program restrict the programmer way too much. Others expect structured editors to be more helpful than text editors because the user operates atomically and precisely on the language constructs, concentrating on the semantics and not on syntax.

In summer 2004, my professor initiated a student research project - we started building a structured editor for C#. I took part because I was deeply persuaded that good structured editors can actually be built, and it was challenging to go and find out for myself.

As one of numerous confirmations for my thoughts, in 2004, Wesner Moise wrote:

...I see a revolution brewing within the next three years in the way source code is written.
Text editors are going to go away (for source code, that is)! Don't get me wrong, source code will still be in text files. However, future code editors will parse the code directly from the text file and will be display in a concise, graphical and nicely presented view with each element in the view representing a parse tree node. ...


I remember how I agreed with this! After three years, in 2007, the prototype implementation is ready - it became the result of my master's thesis. I still agree with what Wesner was envisioning in 2004 - with one exception. Now I believe that structured editors shouldn't (and can't) be a revolution - fully replacing text editors is a bad thing to do. Instead, structured editors should complement text editors to provide yet another view on the same source tree (internal representation, or AST).


General conclusions


As a result of my work, I'm convinced that structured editors actually are, in some situations, more convenient than text editors and providing the programmer with two views on the code to choose from would be a benefit. Just like Visual Studio Class Designer - those who want to use it, well, just use it, and the rest continues to happily use the text editor. All these views should co-exist to provide the programmer with a richer palette of tools to chooce from.


Hence, my first important conclusion. A program's internal representation (the AST) should be observable to allow the MVC architecture - many views on the same internal code model. With MVC, all views will be automatically kept in sync with the model. This is where for example something like WPF data-binding would come in handy.


As for the structured editor itself - it is still a work in progress and I still hope to create a decent replacem... err... complement for text editors. It has to be usable and there are still a lot problems to solve before I can say: "Here, this editor is at least as good as the text editor". But I managed to solve so many challenging problems already, that I'm optimistic about the future.


Current implementation


The current implementation edits a substantial subset of C# 1.0 - namespaces, types, members (except events), and almost all statements. If you're interested, you can read more at http://www.guilabs.net/ and www.osenkov.com/diplom - those are two sites I built to tell the world about my efforts. I also accumulate my links about structured editing at del.icio.us: http://del.icio.us/KirillOsenkov/StructuredEditors


Here, I'll just add one more thing. It turned out that it makes sense to build structured editors not only for C#, but for other languages as well - XML, HTML, Epigram, Nemerle, etc. That is why, at the very beginning, the whole project was split in two parts - the editor framework and the C# editor built on top of it. In some later post I'll share my experience of building frameworks.


If you want to know more, or if you want to share your opinion on this, please let me know. Thanks!

New blog about design and developer tools

I can't resist anymore. I have to start blogging.

First things first - an introduction. My name is Kirill Osenkov and one could say that I'm a software developer who develops software for software developers. That puts it quite nicely - my main interests are currently in the design and architecture of developer tools. I spent two summer internships at Microsoft working with the DSL Tools team. I learned a lot there, especially about using DSLs to raise expressiveness while modeling and programming. In July 2007 I finished my Master's Thesis, where I built an experimental structured (syntax-driven) editor for C#. And now, I hope to continue working on developer tools and share my thoughts via this blog.

Now about what you can expect here. Going meta is popular these days, in the age of DSL, intentional programming, language-oriented programming, and all those X-oriented-programmings out there. For me, going meta means reflecting on how developers develop software and how to develop good developer tools. That's why I'm interested in parsers and parse trees, compiler API, languages, syntax, language services, resolvers, editors and how to put all this stuff together in an extensible way. Clearly, I'm not the only one who's interested in this stuff.

Other than that, I'll also write about design, architecture, OOP and .NET programming.