RSS CodeBetter.Com

http://codebetter.com/blogs/

Stuff you need to code better!

Last checked 7 months ago.

4 people have subscribed to this feed.

Feed frequency

post frequency (last month)

PostRank™ filter

latest 15 posts

« older items




Wednesday February 20th, 2008

1.0

Automatic Properties - In case you didn't know

CodeBetter.Com From CodeBetter.Com, 7 months ago, 0 comments Comment

The following snippet of code (C# 3.5) is allowable, and gives you the benefit of unnecessary extra verbosity with the benefits of encapsulation. Of course, if you need to implement logic in your property, then you don't want to think about automatic properties:

public T Item { get; private set; }

Tuesday February 19th, 2008

5.1

If it feels good, do it

CodeBetter.Com From CodeBetter.Com, 7 months ago, 0 comments Comment

When my daughter was born, and even during the nine months leading up to it, my wife and I read a *LOT* of books. On pregnancy, on child rearing, on labour, on how to cryogenically freeze the blood from the umbilical cord.

But when it came down to the really hard questions, I did what almost every new parent does: I called an expert I trusted. I.E. My mother. See, books can take imageyou only so far when you're learning. Yes, they're important to get a general sense of things but nothing beats a proven expert's opinion and, even better, good old-fashioned experience.

I remember a conversation I had with said expert. At the time, I was asking about some stupid little thing that new parents worry about. After she calmed my worries, I asked my mother: How do you deal with all the conflicting advice you get from people and books and magazines?

She said: Do what you think is right, then find a book that says you did the right thing if it'll make you feel better.

Now, eight years after the birth, I'm a little more seasoned as a parent. I've gained some experience and can handle most anything she throws at me (though she still surprises me). There are more than a few cases when I'll consult with peers on things like study habits, social skills, symptoms for illnesses, but for the most part, I leave it up to an intuition that has been honed over the years.

It's about time to bring this back to software development and hopefully, you'll see the parallels. If not, well, they can't all be gold.

I'm not suggesting you call your (or my) mother the next time you need to figure out how to resolve a dependency. But chances are, you have a network of peers and experts (sometimes the same people, sometimes not) that you turn to when you have questions or just want to discuss software in general.

That, coupled with the aforementioned old-fashioned experience, is how I become a better software developer/parent. Books and articles and blogs and even discussion groups are good for giving you a sense of what's good and bad. But if you're faced with a situation you've never seen before, or if you've done the "right thing" and are feeling something's off, it's time to break out the free will, baby.

This is important for people who are just starting out in software development or even in an area of it they haven't much experience in. It can be overwhelming trying to figure out what the "right thing" is. Or worse, you get into a situation where the "right thing" doesn't actually apply to your scenario specifically and you start fretting about whether you should deviate.

I've been putting "right thing" in quotes because, well, you can't see me making quote-y motions with my hands a la Dr. Evil. But rest assured, I'm making them. And the reason is that the "right thing" differs from one situation to the next and, more importantly, from one person to the next. All it takes is one look through the altdotnet discussion list to find an example. Even given the exact same conditions, one person's preference may not match another's. And both may be equally valid.

So if you'll feel better having a second aggregate root in your domain, by all means do it. But make sure it isn't simply a quick fix so you can go home. Maybe a single aggregate, lazy loading, and a unit of work will solve your problem. But then again, maybe it won't.

In the end, a little confidence goes a long way. You're smart people. Like the title says, if it feels good, do it. But make sure you are always questioning what feels good.

Kyle the Enlightened

7.5

LINQ To SQL and Stored Procedures : Visual Studio 2008 and Repository Factory

CodeBetter.Com From CodeBetter.Com, 7 months ago, 0 comments Comment

I forgot to mention that while I was at SQLSaturday in Tampa, Florida I ran into some very passionate database administrators (DBAs). They were more than happy to give me unsolicited opinions on the evils of O/R Mappers and Dynamic SQL as well as the importance of the DBA on development teams.

I wasn't planning on entering a debate on these topics, but more importantly wanted to make sure that they understood that LINQ To SQL supported Stored Procedures. Now if they would have attended my talk on SQL Server Data Access Tips & Techniques, they would have known this :)

 

LINQ To SQL and Stored Procedures

You can add stored procedures to LINQ To SQL in a few ways, but the easiest way to add stored procedures support to LINQ To SQL is to drop stored procedures from the Server Explorer in Visual Studio 2008 to the LINQ To SQL Designer Surface. One half of the LINQ To SQL Visual Designer is for mapping classes to tables in SQL Server, the other half allows you to drag and drop stored procedures for stored procedure support. Here is an example using the Northwind Database, where we see the Category Entity that maps to the Categories Table as well as several stored procedures that I dragged and dropped onto the Visual Designer:

 

LINQ To SQL Designer Surface in Visual Studio 2008 

 

I talked about the process of adding stored procedures in a previous tutorial:

Once you add the stored procedures to the LINQ To SQL Visual Designer Surface, you can map the stored procedures to the CRUD operations of the DataContext Class. Normally the DataContext class will dynamic create parameterized SQL for you to do insert, update, delete, etc. of Categories. However, in this case I specified that LINQ To SQL should use the stored procedures I added to the designer surface instead. Here we see me overriding the runtime behavior with a custom behavior to insert a new category using the InsertCategory Stored Procedure:

 

LINQ To SQL Stored Procedures

 

Now when you do something as simple as inserting a new category into the categories table, you will notice that LINQ To SQL calls a stored procedure as opposed to creating a parameterized query at runtime:

 

NorthwindDataContext db = new NorthwindDataContext();
db.Log = Console.Out;

Category category = new Category();
category.CategoryName = "Green Tea";
category.Description = "Yummy...";

db.Categories.InsertOnSubmit(category);

db.SubmitChanges();

 

You can view these results by reviewing the data sent to the DataContext.Log Property or using SQL Server Profiler.

 

Visual Studio 2008 and Repository Factory

 

At my presentation, I also received a few questions / concerns about Visual Studio 2008 and the Repository Factory. You can find more information about using the Repository Factory for generating a data access layer here:

I also have two screencasts on the Repository Factory:

Here is a screencast on the older Data Access Guidance Package that used to ship with the Web Service Software Factory:

 

Personally, it is my humble opinion that if you are using Visual Studio 2008 to target the .NET 3.5 Framework, I would use LINQ To SQL within my respository classes. This will avoid the fact that there is currently no Visual Studio 2008 version of the Repository Factory Guidance Package, and LINQ To SQL does what the Repository Factory does and then some.

Some reasons for using LINQ To SQL over Repository Factory when targeting .NET 3.5 Framework:

  • As mentioned above, all you need to do is drag and drop your stored procedures to the LINQ To SQL Visual Designer Surface to support stored procedures.
  • The amount of code to maintain is dramatically reduced as all of those Factory Classes generated by the RepositoryFactory for converting IDataReader to Entity Classes is done for you by LINQ To SQL.
  • LINQ To SQL will also detect timestamp columns in your SQL Server tables just like the Repository Factory as well as support other types of concurrency methods.
  • LINQ To SQL does change tracking, something the Repository Factory does not do.
  • LINQ To SQL supports dynamic SQL, the Repository Factory does not.
  • LINQ To SQL can be used with other cool technologies easily like ASP.NET Dynamic Data and ADO.NET Data Services.
  • etc...

 

Repository Factory

 

Don't get me wrong, I appreciated the Repository Factory when we did not have LINQ To SQL and the upcoming ADO.NET Entity Framework. It was an okay interim solution, but now I think it is time to move on, at least when you are targeting the new .NET 3.5 Framework.

Hope this helps.

by David Hayden

Monday February 18th, 2008

4.6

Solution folders

CodeBetter.Com From CodeBetter.Com, 7 months ago, 0 comments Comment

So what's your collective take on solution folders with Visual Studio?

For the longest time, I didn't pay them no never mind. Then there was a brief period when I had an intense love affair with them. Everything went into my solution. Third-party libraries, testing tools, documentation, damning evidence that other members of the team were plotting to beat me up and steal my lunch money. At my last contract, even the projects were organized within solution folders and when I first saw that, I nodded approvingly to myself.

The rationale was that if it was in the solution, I didn't need to leave Visual Studio to deal with source control. It was safe in Visual Studio. It gave me comfort. Even joy. Windows Explorer was a scary place and this TortoiseSVN/Explorer integration wackiness was just plain FREAKY FRIDAY! Better to stay in my happy place.

Then I noticed cracks in the veneer. I couldn't add a physical folder to a solution folder and have it magically add all the files within it to my solution. I felt a slight twinge of annoyance at having to navigate an extra layer to get to the project I wanted. And at the risk of being called a "slave to my tools" (which is a funny accusation at the best of times, unless the accusers writes code in Notepad and compiles from the command line with csc), I do enjoy the Collapse All Projects feature of Gaston Milano's CoolCommands, which didn't work as nicely with that extra layer.

So now I find myself back to having all my projects at the top level and using solution folders sparingly for things like batch files, build files, and readme files. I ventured out of my comfort zone in Visual Studio and learned to deal with third party library folders and tool folders externally. And really, it only took one time re-creating the full NAnt folder structure in solution folder format to make me drop the practice.

How about you? What do you store in solution folders? Do you maintain a project hierarchy in them? Use them for any non-code-type files? Love them long time or hate them with a Charles Bronson-like vengeance?

Kyle the Solvable

5.6

(R) evolutionary changes

CodeBetter.Com From CodeBetter.Com, 7 months ago, 0 comments Comment

When developing software you are dealing with changes. Changes in what your creations have to do; changes in the way you create your software. The process of change sometimes seems to be a goal on itself. We are almost beaten to death by both the enormous amount of new tools and techniques to create software. To some of our customers changing specifications has become a form of survival on itself. All too often the words revolutionary or evolutionary come by to stress the importance of change. In this post I want to take at change from the perspective of my original studies as an evolutionary biologist. I do know biological evolution can be laden topic, not just in the US. I do take evolution as a given part of biological science. Developing software is a science as well; which deals with observation and repeatable experiments. Developing software can even be a form of art but it does not answer any questions on the meaning of life. I'm quite happy discussing the non scientific aspects of evolution with you, but not here on CodeBetter.

On revolutionary changes I can be short. In the days I went to university kicking against anything available was all part of social life. But I don't think revolution taken too seriously leads to much good. Looking at history shows so many well intended fresh ideas which ended in a situation worse than the one they tried to overthrow. CodeBetter used to be the basis of a revolutionary blogger who considered the state of software development to be in status quo which required an uprising of the coding masses. In his struggle he alienated quite a few people from a cause which was on itself not bad at all.

Let's now take a look at some aspects of evolution and see what happens when you try to apply them to software development.

At the basis of evolution lies variation. Not all offspring has the same qualities, those whose qualities are best fit in their environment are selected as parents for the next generation. There is also a huge variation in the tools to develop software. Those tools which produce the most working software are most likely to be selected for the next projects. It is a survival of the fittest. Note that this selection happens at time of reproduction. A strong parent which carries a lethal disease which does not expose itself until a later age is not selected against. A software tool which produces a shiny project which was built with a lot of wizardry is likely to be selected for the next project. At a later age of the project, when it has turned out to be un-maintainable, the tool has already spread.

So this selection which happens at the time of reproduction is like taking a snapshot. In the next generation, under circumstances which are different, selection can favor something completely different and push change into an opposite direction. In many an old textbook on evolution you will see progressive evolutionary lines. Step by step the small rabbit-like mammal evolves in a swift racing horse. Far more famous is the line from a chimpanzee to a modern human being. The lines suggest a line of progress. A less biased study of the fossil record and the already mentioned observation of selection as a snapshot do show that evolution is in fact a wide spreading tree. With many branches which end in extinction. When you follow one specific path in this tree, jumping from branch to branch, you can construct a classic progressive evolutionary line; but it is still one of the many paths possible. The same applies to software tools. Does anybody remember languages like Algol-68 or Logo? At the time they looked like the starts of very promising lines. But they have vanished into oblivion and given place to languages with far older ancestors. Ancestors who only served a niche market for quite some time. This zig-zag behavior can also be observed within a line. Notorious are the many, many versions of Delphi. Version 5 is still alive in many a location, but version 6 is almost extinct. After that the .NET environment has lead to an adaptive radiation of Delphi versions. Some are far more successful than others. Yet another analogy is living fossils like Cobol. That language has never changed that much over the years and is still fit enough to survive.

(Image nicked here)

So far we have only observed that there are changes in life forms and in software tools. A very interesting aspect of evolution is the time scale over which these changes happen. Up till recently it was believed that evolutionary changes happen gradually over time. In every generation there is a variation in the offspring and selection will cause the generations to differ from their ancestors. When scientist actually started to track and measure this gradual change they found out that the species studied actually did not change at all over a long period of time and space. Except for small isolated populations which rapidly changed after which these changes spread over a large area. This was formulated in the theory of punctuated equilibria by Stephen Jay Gould and Niles Eldredge. (You may know Gould as the great essay writer who has reached a large audience; his major profession was that of an evolutionary biologist) This pattern of punctuated equilibria can also be observed in software. I remember myself trying to convince the Delphi crowd of the merits of .NET. Not long after that I had to explain what Delphi was to the .NET people. TDD has been the hobby horse of a minority of evangelists, but the way it is now integrated in asp.mvc looks like a rapid main stream acceptance.

So far I have named some parallels in biological and software evolution. To me the major lessons are that there is no such thing as a constant linear progress. Many a path taken can lead to a dead end; there are periods of fast changes and there are periods of standstill. There is also no such thing as a plan or a direction. There is no intelligent design; there is no direction things will go in the future. All we can do is observe what has happened up till this very moment.

But there is one very big difference between biological and software evolution. It is human culture. Biological variation is dictated by the genes. Changing these is something which only happens in Science Fiction. But many more complicated life forms, like human beings, also pass information to next generations using other coding mechanism. Like stories, books or the internet. Any attempt to capture cultural evolution using the theory of biological evolution so far has lead to stories which might look appealing but have a very weak scientific base.

So take these words with some grains of salt and do concentrate on your human skills to learn and teach to keep the process of change under control.

Sunday February 17th, 2008

10

Architecting LINQ To SQL Applications, part 5

CodeBetter.Com From CodeBetter.Com, 7 months ago, 0 comments Comment

Let's return to the series on how to architect applications that use LINQ To SQL. First of all, for those you who missed it, a summary of where we have been:

Part 1, Introduction
Part 2, Layered Architectures
Part 3, DAOs and Repositories
Part 4, Dynamic Queries

Introduction

I had a couple of requests to provide some sample code. So I delayed this installment to start building something that will work to that purpose as the backbone for these articles. In the example we are modelling a system that allows us to store usernames and passwords for systems we own, just because that is a side project I am working on. It will go up on Google code toward the end of the series. I also had a number of requests to talk more about mapping and TDD, so this installment returns to that territory in more detail.

First, imagine that we have built some domain objects through Test-Driven Development. In our model an ITSystem has a collection of Keys (username and password) to systems and belongs to a Category.

   public class ITSystem
    {
        public Category Category {get;set;}
        public string Comments {get;set;}
        public string Name {get;set; }
        public List<Key> Keys {get;set;}
       
        ...
    }

We've built our domain model before we create a database schema to store it against. We know we do need to store it, but we want to be malleable until we do.

Aggregates and Repositories 

Within our domain we have repositories, which represent a collection of our objects and negotiates with infrastrtucture services to get that list of objects. We don't define a repository  for all of our entities, but for the root entities within an aggregate:

"An AGGREGATE is a cluster of associated objects that we treat as a unit for the purpose of data changes. Each AGGREGATE has a root and a boundary. The boundary defines what is inside the AGGREGATE. The root is a single, specific ENTITY contained in the AGGREGATE. The root is the only member of the AGGREGATE that outside objects are allowed to hold references to, although objects within the boundary may hold references to each other. ENTITIES other than the root have local identity, but that identity needs to be distinguishable only within the AGGREGATE, because no outside object can ever see it out of the context of the root ENTITY" [Evans]

In our example the root is ITSystem and the boundary includes the Keys for that system. We don't include Category within the boundary. Although an ITSystem has a category it does not manage the lifecycle of a Category. Deleting an ITSystem does not delete the Category it belongs to.  As a corollary we might delete a Category, without deleting the IT System, if, for example, we were re-categorizing our systems.

Within our Category and ITSystem aggregates we can hold references to each other's root objects, but nothing below them. This does not make a huge difference here, because there are only two aggregates we care about: ITSystem and Category, but the point remains.

When working with an ORM I tend to view the point of crossing an aggregate boundaries as a good candidate for lazy loading. As well as using the collection based lazy loading common in ORMs you might also want to think about using a ghost [Fowler]. Of course beware the select N+1 problem if you know that you are likely to load a collection.

Working in memory 

So we need a repository that allows us to retrieve/persist the ITSystem root and its child Keys. We can write a unit test for that:

    [TestClass]
    public class ITSytemRepositoryFixture
    {
        [TestMethod]
        public void Should_Be_Able_To_Find_All_Systems()
        {
            //setup
            MockRepository mocks = new MockRepository();
            ISession session = mocks.Stub<ISession>();
            session.Systems = CreateSystemList();

            SystemRepository systemRepository = new SystemRepository(session);

            //exercise
            List<ITSystem> systems = systemRepository.FindAll();

            //verify
            AssertSystemListMatches(session, systems);                       
        }
    }

We are not showing the creation method CreateSystemList or the verification method: AssertSystemListMatches here, for simplicity.

The session will end up abstracting DataContext. It is our unit of work and has both the methods we need to submit changes, and contains the collections that we are accessing.

Remember how in part 3 we stated that when we crossed a layer boundary we wanted to depend upon an abstraction and not a concrete type. A proof here is that depending on an abstract type allows us to replace the real data context for unit tests. In the unit test we replace the dependency from the DataContext based repository with a in-memory stub implementation which acts as a Test Double for Db operations.

Note that I am not accessing the Db here, I am just building up the functionality of the repository. Within the implementation we use LINQ to return the result set. Note that this is so simple a case, as an example, that the use of LINQ may seem overcomplex, but we don't want to distract with complexity here.

My implementation looks like this:

    public class SystemRepository
    {
        private ISession session;

        /// <summary>
        /// Initializes a new instance of the SystemRepository class.
        /// </summary>
        /// <param name="session"></param>
        public SystemRepository(ISession session)
        {
            this.session = session;
        }

        /// <summary>
        /// Find all the systems
        /// </summary>
        /// <returns></returns>
        public List<ITSystem> FindAll()
        {
            return
                (from s in session.Systems
                    select s)
                    .ToList<ITSystem>();
        }
    }

Mapping 

We can go a long way working with this in-memory representation, building up the queries our repository manages for us against the  domain layer without ever touching peristence to a Db. Because we are not touching the Db as yet we are very malleable. We don't have to worry about versioning Db schemas. Where there is a lack of resistance to change, we tend to make more effort to keep our code clean.

Of course at some point we want to write the code that will persist our domain model. Again we can drive with tests.

Because these tests will be slow, we are touching the Db, we put them in a seperate assembly and tag them as Slow or Acceptance tests. Developers may want to skip running these tests when confirming their refactoring up until they check-in, so they don't break the rhythm.

We could have an equivalent test to that above:

    [TestClass]
    public class ITSytemRepositoryFixture: ITSystemTests
    {
        [TestMethod]
        public void Should_Be_Able_To_Find_All_Systems()
        {
            //setup
            ISession session = new KeySafeSession(new DataContext(ConfigurationManager.ConnectionStrings["KeySafe"].ConnectionString));
  
            SystemRepository systemRepository = new SystemRepository(session);

            //exercise
            List<ITSystem> systems = systemRepository.FindAll();

            //verify
            AssertSystemListMatches(session, systems);                       
        }
    }

But note how this time we are using a concrete session implementation initialized from our DataContext.

In order to get our domain classes working with DataContext we have to tell DataContext how to map them. We can add mappings in a seperate mapping file, or as attributes.

Which you prefer is somewhat to personal preference. One tradeoff is between polluting your domain class with mapping information and managing XML files. I have always leaned toward the mapping file, because I like to leave my domain clean of persistence knowldege, others are happy with attributes for what is an orthogonal concern. Here we will show use of attributes.

One thing to point out here though is that as we are building from our domain first, we have no schema to map to at this point. That's fine we are going to tag our domain classes for persistence, and then generate the Db from them.

First we need to identify the table that our domain class maps to. We simply add the Table attribute to our class to do that. [Table] allows us to map to a different name.

Although there are limitations to mapping (lack of implicit support for many-to-many, single table for inheritance hierachies) working from a clean domain gives us one of the simplest options for using LINQ To SQL as we are defining how to persist our domain, not trying to figure out what domain classes map from an existing schema. Working with a legacy schema with LINQ To SQL will always shape our domain to that schema.

We do not have an inheritance hierachy, so we don't need to use the [InheritanceMapping] attribute.

We need to add this to all of the classes we wish to persist.

    [Table]
    public class ITSystem

Next we tag those fields that we wish to persist as columns. Again we can rename if we don't like the domain name.

        [Column]
        public string Comments {get;set;}
        [Column]
        public string Name {get;set; }

Our entities must have an identity, that seperates them from other instances of the class. We need to tag this identity so that we can use it to identify instances of our identity. The Db will use a primary key for this so we tag a column as our primary key.

We can modify the name property of ITSystem as follows:

        [Column(IsPrimaryKey= true)]
        public string Name {get;set; }

Not all of our fields will be primitives. Where they are instances of another class the Db will need to represent this as a foriegn key pointing to a row in a table to which we persist the other class. We can show this mapping by using the attribute [Association]. We need to tell it how to hook up to our child i.e what property of the child holds the parent identifier. Our Key class looks like this at the minute:

    [Table]
    public class Key
    {
        [Column(IsPrimaryKey=true)]
        public string UserName {get;set;}
        [Column]
        public string Password {get;set; }

        public Key() {}

        public Key(string userName, string password)
        {
            UserName = userName;
            Password = password;
        }
    }

So we add a SystemName to Key so that we have the child knows its parent, and in instance of the ITSystem System so we can navigatge the relationship bidiectionally. Now we add an Association attribute to ITSystem to indicate how to map the child collection.

        [Association(OtherKey="SystemName")]
        public List<Key> Keys {get;set;}

And then we can add an Association in Key for the ITSystem so that we can traverse the relationship in both directions.

Note we need to switch to using  EntitySet for the backing storage for the many of side of our associations. We also need to use EntityRef to support the one side of our associations. This supports lazy loading, but pushes a persistence specific class info into our domain. I'm tolerant to this because it can be hidden in the public interface. We only intend to support lazy loading across an aggregate boundary, so from our ITSystem we will lazy load the category, but eager load the Keys. We will use DataLoadOptions to eager load where required. Read the documentation to see the restrictions here. So we end up with this:

        private EntitySet<Key> keys;

        [Association(OtherKey="SystemName")]
        public IList<Key> Keys
        {
            get{return keys;}
            set{keys.Assign(value);}
        }

Where we have an EntityRef<> or EntitySet<> we need to initialize the collection in the constructor, for example:

   category = default(EntityRef<Category>);

If you are too uncomfortable with using EntityRef and EntitySet see also Mathew Charles's notes on how to work around this restriction:  (http://blogs.msdn.com/digital_ruminations/archive/2007/08/28/linq-to-sql-poco-support.aspx) on supporting Persistence Ignorance with LINQ To SQL.

Building the Db 

Once we have all of our classes mapped out, we can generate a Db to support them. I add a utility console project to do this.

We build a KeySafeContext that looks like this, to help us get generation done. We'll come back to talk about linking it up to our ISession implementation KeySafeSession.

    public class KeySafeContext : DataContext
    {
        private const string DbName = "KeySafe";
        public Table<ITSystem> Systems { get; set; }
        public Table<Key> Keys { get; set; }
        public Table<Category> Categories { get; set; }

       
        /// <summary>
        /// Initializes a new instance of the KeySafeContext class.
        /// </summary>
        public KeySafeContext() : base(ConfigurationManager.ConnectionStrings[DbName].ConnectionString) 
        {
            Systems = GetTable<ITSystem>();
            Keys = GetTable<Key>();
            Categories = GetTable<Category>();
        }
    }

we can then use this with a simple script to build our Db:

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Generate new version of Db");

            try
            {
                KeySafeContext db = new KeySafeContext();
               
                if (db.DatabaseExists())
                {
                    Console.WriteLine("Deleting old version");
                    db.DeleteDatabase();
                }

                db.CreateDatabase();

                Console.WriteLine("Database created successfully.");
            }
            catch(Exception ex)
            {
                Console.WriteLine("Error creating Db...");
                Console.WriteLine(ex.Message);
                throw;
            }
        }
    }

This will pop out any errors for you in your mapping as you build, so its a great way to check that your domain is configured correctly. I certainly got one or two errors when I set this up for the first time.

Now you can use the generated Db to check how your mappings are coming out. You have a fair amount of flexibility to specify details of how you want your final mapping to look in your attributes. Review the docs. You can use the script above to modify and build until you are happy that your domain model is being mapped out in your preferred form.

For example the default storage for our strings is nvarchar(4000), which is way larger than we want, so we specify the size and constraints of the columns directly:

        [Column(DbType="NVarChar(50) NOT NULL", CanBeNull=false, IsPrimaryKey= true)]
        public string Name {get;set; }
       
I can keep adjusting the metadata in the attributes, and re-generating the Db using the utility until I get something I like.

This may also be the point where I decide to use an Id field as a key, instead of relying on natural keys, or add a version/timestamp field to support optimistic currency.

As it is possible that someone might choose to change the names of the systems and categories, I opt to add an Id column and use that as the primary key instead of the name. That change flows through to child objects, which now need to store an Id to represent the foriegn key portion of the association.

        [Column(AutoSync = AutoSync.OnInsert, IsDbGenerated = true, IsPrimaryKey = true)]
        public int Id { get; set; }

At the same time I need to adjust the mappings to reflect this. First the association with the Key class:

       [Association(OtherKey="SystemId")]
        public IList<Key> Keys {... }

and the Key class itself


    [Table]
    public class Key
    {
        [Column(AutoSync = AutoSync.OnInsert, IsDbGenerated = true, IsPrimaryKey = true)]
        public int Id { get; set; }
        [Column(DbType="NVarChar(50) NOT NULL", CanBeNull=false)]
        public string Password { get; set; }
        [Column]
        public int SystemId { get; set; }
        private EntityRef<ITSystem> system;
        [Column(DbType="NVarChar(50) NOT NULL", CanBeNull=false)]
        public string UserName { get; set; }
    ...
   
            [Association(OtherKey="Id", ThisKey="SystemId")]
        public ITSystem System
        {
            get{return system.Entity;}
            set{system.Entity = value;}
        }

    }

I also decide that as this is intended to be a multi-user system I'm going to support a versions to make optimistic concurrency work better i.e. not through comparing every field.

        [Column(AutoSync=AutoSync.Always, IsDbGenerated=true,    IsVersion=true)]
        public byte[] Version {get;set;}

Finally, where I want the field within the Db to be nullable, I switch to using a nullable type on my domain.

Summarizing the Mapping

Because things may have got a little confusing through all that let's review the mappings:

    [Table]
    public class ITSystem
    {
        [Column]
        public int CategoryId { get; set; }
  private EntityRef<Category> category = default(EntityRef<Category>);
        [Column]
        public string Comments {get;set;}
        [Column(DbType="NVarChar(50) NOT NULL", CanBeNull=false)]
        public string Name {get;set; }
        [Column(AutoSync = AutoSync.OnInsert, IsDbGenerated = true, IsPrimaryKey = true)]
        public int Id { get; set; }
        private EntitySet<Key> keys = new EntitySet<Key>();
        [Column(AutoSync=AutoSync.Always, IsDbGenerated=true, IsVersion=true)]
        public byte[] Version {get;set;}
        ...
     
              [Association(OtherKey="SystemId")]
        public IList<Key> Keys
        {
            get{return keys;}
            set
            {
                foreach (Key key in value)
                {
                    key.System = this;
                }
                keys.Assign(value);
            }
        }


        [Association(OtherKey="Id", Storage="category", ThisKey="CategoryId")]
        public Category Category
        {
            get
            {
                return category.Entity;
            }
            set
            {
                this.CategoryId = value.Id;
                this.category.Entity = value;
            }
        }
      }
     
    [Table]
    public class Key
    {
        [Column(AutoSync = AutoSync.OnInsert, IsDbGenerated = true, IsPrimaryKey = true)]
        public int Id { get; set; }
        [Column(DbType="NVarChar(50) NOT NULL", CanBeNull=false)]
        public string Password { get; set; }
        [Column]
        public int SystemId { get; set; }
        private EntityRef<ITSystem> system = default(EntityRef<ITSystem>);
        [Column(DbType="NVarChar(50) NOT NULL", CanBeNull=false)]
        public string UserName { get; set; }
        [Column(AutoSync=AutoSync.Always, IsDbGenerated=true, IsVersion=true)]
        public byte[] Version {get;set;}
        ...
     
                [Association(OtherKey="Id", ThisKey="SystemId")]
        public ITSystem System
        {
            get{return system.Entity;}
            set{system.Entity = value;}
        }
    }

    [Table]
    public class Category
    {
        private EntitySet<Category> children = new EntitySet<Category>();
        [Column(AutoSync = AutoSync.OnInsert, IsDbGenerated = true, IsPrimaryKey = true)]
        public int Id { get; set; }
        [Column(DbType="NVarChar(50) NOT NULL", CanBeNull=false)]
        public string Name {get;set; }
        [Column(DbType="Int", CanBeNull=true)]
        public int? ParentId { get; set; }
        private EntityRef<Category> parent;
        private EntitySet<ITSystem> systems = new EntitySet<ITSystem>();
        [Column(AutoSync=AutoSync.Always, IsDbGenerated=true, IsVersion=true)]
        public byte[] Version {get;set;}
        ...
   
            [Association(ThisKey="ParentId", OtherKey="Id")]
        public IList<Category> Children
        {
            get{return children;}
            set
            {
                foreach (Category child in value)
                {
                    child.Parent = this;
                }
                children.Assign(value);
            }
        }

        [Association(ThisKey="ParentId")]
        public Category Parent
        {
            get{return parent.Entity;}
            set
            {
                if (value == null)
                {
                    ParentId = null;
                }
                else
                {
                    ParentId = value.Id;
                    parent.Entity = value;
                }
            }
        }
    }

The good, the bad, and the ugly 

Mapping can be a little tricky, so put aside sufficent time in your project to make it happen. A couple of tips are that when you get null reference exception when submitting changes, consider commenting out parts of the mapping, until you can isolate the mapping that causes the error. In particular, watch your foreign keys, its easy to get confused and end up with a broken mapping. Secondly, once you have built the Db you can always create a new solution and within that use the designer to generate the suggested mappings and re-apply anything that is missing to your domain.

Some folks are going to look at the work involved in mapping from domain to Db, panic, and just adopt a schema first approach. Don't forget however that by going domain first, we focus on the ubiquitous language we share with the user, and by using TDD we have tests to preserve our domain behavior while we refactor to support our mapping.

As you can see, as the attributes build up, they can cause an accretion of 'noise' in our domain model whose pupose is orthogonal to the domain itself. If that bothers you, use an XML based mapping file instead.

We could probably, and should, revise these mappings a little more, but they will do for now.

LINQ and designing for testability

Once we have our Db generated we need to review our Session. It currently exposes its member collections as an IList<T>. While this is good enough for LINQ To Objects, LINQ To SQL needs an IQueryable. Our KeySafeContext works with a Table<T> for each class we are persisting.

For this purpose I have a helper library of classes, called Strain, that I have written that exposes a common interface, IQuerySource, which derives from both IQueryable<T> and IEnumerable<T> and adds Add and Remove methods. Both Table<T> and List<T> sourced collections can implement this:

    public interface IQuerySource<T> : IQueryable<T>, IEnumerable<T>
    {
        void Add(T item);
        void Attach(T item);
        void Remove(T item);
        void RemoveAll(IEnumerable<T> items);
    }

We expose the IQueryable<T> from a List<T>  by virtue of the conversion availabe from the Queryable.AsQueryable() method.

        public ListQuery(List<T> source)
        {
            impl = source;
            queryableImpl = impl.AsQueryable();
        }

and then just implement the IQueryable<T> in terms of this.

A Table<T> is already an IQueryable<T> so we don't need to do this conversion. We can simply implement the Add, Attach, etc. methods we are after from the Table e.g.

      public void Add(T item)
        {
            dataTable.InsertOnSubmit(item);
        }

I don't show the code for this helper library here, but I'll post it at a later date. However it should be possible to implement this yourself from this.

This allows us to modify our ISession to expose an IQuerySource<T> instead of a List<T> so that we can source it from either.

We also ensure that our context has the DataLoadOptions we need to populate our eager-loaded collections.


        public KeySafeContext() : base(ConfigurationManager.ConnectionStrings[DbName].ConnectionString) 
        {
            Systems = GetTable<ITSystem>();
            Keys = GetTable<Key>();
            Categories = GetTable<Category>();

            DataLoadOptions dataLoadOptions = new DataLoadOptions();
            dataLoadOptions.LoadWith<ITSystem>(s=>s.Keys);
        }

Our acceptance tests will also need to populate the data we intend to select into the Db by adding data to the repository and then calling SubmitChanges. To avoid issues with shared fixture state between tests, we wrap the modifications in a transaction that we never commit.

Our final test looks like this:


        [TestMethod]
        public void Should_Be_Able_To_Find_All_Systems()
        {
            //setup
            KeySafeContext context = new KeySafeContext();
            ISession session = new KeySafeSession(context);
            SystemRepository systemRepository = new SystemRepository(session);
            ITSystem system = CreateITSystem();

             //exercise
            using (new TransactionScope())
            {
                systemRepository.Systems.Add(system);

                session.SubmitChanges();

                List<ITSystem> systems = systemRepository.FindAll();

                //verify
                AssertSystemListMatches(session, systems);
            }
        }

With that, the tests pass. That is enough for this installment, but next time, I'll give some examples around dynamic querying options. After that we'll move on to look at the place for ORMs in distributed systems.

3.0

SQLSaturday Presentation Recap: Data Access Tips and Techniques - Tampa, Florida

CodeBetter.Com From CodeBetter.Com, 7 months ago, 0 comments Comment

Data Access Tips and Techniques - David HaydenWhat an awesome Saturday. I had the honor of presenting at the SQLSaturday Event in Tampa, Florida on one of my favorite topics - Data Access.

My presentation, entitled SQL Server Data Access Tips and Techniques, covered a variety of data access related technologies and proven practices from Microsoft:

  • ADO.NET
  • Enterprise Library Data Access Application Block
  • LINQ To SQL
  • ASP.NET Dynamic Data
  • ADO.NET Entity Framework
  • ADO.NET Data Services

What I really liked about presenting this material is that the technologies are so easy to use that one can literally do all the code samples from scratch. Sure I had some working code in case things went wrong ( DO THE JULIA CHILD as Rod so eloquently puts it ), but I didn't need it. It is amazing how intuitive the developer experience is with these data access tools and technologies, even the ones still in CTP!

People were absolutely amazed by the ASP.NET Dynamic Data Framework and ADO.NET Data Services. I still get excited about them, too. Download them as part of the ASP.NET 3.5 Extensions CTP if you haven't already.

I spent a considerable amount of time showing developers how to leverage LINQ To SQL with existing stored procedures and using dynamic SQL as a way to transition to it from ADO.NET, especially if they weren't quite comfortable with O/R Mapping. The same goes for the ADO.NET Entity Framework. I focused quite a bit on the Entity Client and Object Services with Entity SQL in addition to LINQ To Entities so people could transition to full blown O/R Mapping and/or LINQ in a more gentle way as their skills and confidence increased in that area.

Thanks to all of you who attended both my sessions and for the positive feedback.

I hope to see some of you again at my IASA Presentation on Aspect-Oriented Programming in Tampa, Florida on Thursday, February 28th. Register here.

Thanks, again.

Saturday February 16th, 2008

5.3

500th Post

CodeBetter.Com From CodeBetter.Com, 7 months ago, 0 comments Comment

This is my 500th post on CodeBetter, and as Dogbert would say, it's a big, round, scary number.  I can't imagine that I'll ever make it to a 1,000, so I'll do my retrospective now.  It's been a fun ride and I'd like to think Brendan for running CodeBetter and making it what it is.  I've met a lot of people through blogging and probably gotten some opportunities that I would have missed otherwise.  

I originally started the blog with some fuzzy idea of writing about TDD and other Agile practices to help the other .Net developers in my then company adopt and use those practices.  I don't know if any of that stuff ever helped my company, but I've gotten a lot out of writing the blog posts.  It's hard to imagine now from the constant chatter on my RSS feed and the ALT.NET groups, but three years ago Agile and .Net was a pretty rare combination. 

I don't particularly have any kind of agenda anymore with the blog, but I still enjoy writing it.  I do need to slow down my blogging rate for the rest of the year to concentrate on other projects and that pesky little "day job" thing.  The .Net blogosphere is a much richer, more vibrant place now and doesn't seem to be stopping.  Many of my favorite bloggers started in the last 12 months, and I figure that there's probably more great bloggers just waiting to get started.

I'm probably taking the next couple weeks off of writing because I'm finally making my move back to Austin late next week and things will be crazy at home.  I'll see you next month with the rest of "First Causes" and maybe some more "Build your own CAB" stuff. 

I've put together a pair of "Best Of's," you know, like a country music artist that has one hit song and cuts a Greatest Hits package the next year:

Best of the Shade Tree Developer and Best of the Shade Tree Developer Part II.

The relevant stats are 500 posts, 3,334 comments, and 1,458 trackbacks.  My most popular post is Test Driven Development with ASP.Net and the Model View Presenter Pattern, which is a bit ironic because I've even put up a warning message on that post pushing people to look at MonoRail or the MVC framework instead of the MVP pattern for web development.  A couple months after that I read the Pragmatic Programmer's book on Ruby on Rails and I've hated that ASP.NET post ever since.  If I had to pick my favorite post, I'd go with My Programming Manifesto.

 

Anyway, thanks to all of you who read, comment on, and link to this thing.  Here's looking to another three years or so.

3.4

Patterns, it's about teaching people how to fish

CodeBetter.Com From CodeBetter.Com, 7 months ago, 0 comments Comment

351022855_ebbb37749d_b[1]

Today Larry Brader (Our Lead Test Manager) and I were having an interesting conversation that led me to make the above statement. Larry and I were discussing the root drivers for many of the architectural qualities I have been pushing on within the "Prism" project. This includes qualities such as Simplicity, Subsetability (no I did not make this word up) and Compatibility. As I began to explain, I quickly started working back historically, until I ended up right back at Jeremy's "Build your own CAB" series and the great "CAB" bash that ensued from his initial talk at DevTeach.

The crux of Jeremy's argument was that if it's a choice between learning patterns or learning to use a tool that implements those patterns (CAB) then he would choose to learn the patterns. It may surprise you, but I agree completely (though not everyone agrees). The second part is that if you are going to use a tool, then knowing the underlying patterns behind the tool means you are more effective in the use of that tool and also gives cross transferable knowledge that you can use either in the absence of a tool, or apply to a different tool.

In Software Development we know that the one thing that is constant is change. Some things may stay the same, but as we make new discoveries at the hardware, software language, and methodology level, change occurs. Just about 60 years ago software development was limited to an elite few who developed software inscribed on Hollerith cards. The tools you use today will not be the tools you use tomorrow. Take languages for example. My first exposure to computing was Basic on a Commodore Vic-20. Since then I have learned several variations of Basic (at least 5 I can think of), Logo, Fortran, Pascal, A few flavors of Assembler, C, C++, Javascript, PHP, Java, C#, and now Ruby.

What's common about all these languages? It's the behavior those languages encapsulate which can be expressed in pseudo code. Quite simply (and this is an oversimplification), it's Input, Process and Output. This I would argue is another constant that won't change. At the end of the day every programming language needs to support this. As I said this is an oversimplification in that there's a ton of sub-behaviors that you could put under each of the three. However, even at that level you will can find a common set that pervades all languages. In essence these are patterns of languages. Once I understand these patterns that means I can learn any language. The semantics (implementation) of the language continually changes, but the patterns stay the same

It's the same with software design patterns. Take the Factory pattern for example. At an implementation level the Factories of today are very different than the factories that were created back when the gang-of-four first coined them, however they still are factories. If twenty years ago all I learned was how to use the OldLanguageFactory then that doesn't necessarily help me use the NewLanguageFactory of today. I may not have even understood that the OldLanguageFactory is in fact a factory. However if I understand the factory pattern, then I can use that transferable knowledge to use the NewLanguageFactory. I'm also able to build a NewLanguageFactory if one doesn't exist. The same argument can be applied when looking at the CAB. CAB at it's essence is an implementation of a set of patterns including Dependency Injection, Builder, Composite, Command, PubSub, etc. If you understand the underlying patterns then you have transferable knowledge that will have benefits that transcend the current tools.

In the Web Client Software Factory, it is this rationale that drove the MVP Bundle. Since I joined p&p, I heard countless feedback from customers who did not understand how to properly implement MVP. Having the automated recipes that generated the presenter, view, and view interface and wired everything together was not enough. It's like great you did that for me, but now what do I do? So in the MVP bundle, we decided to focus on the pattern itself and then show you how you can implement MVP yourself without having an dependencies on the CWAB (Composite Web Application Block). We then showed you additionally how using the CWAB aids you in implementing MVP. Having that understanding of MVP means you can take that knowledge and implement it yourself, look at other alternatives besides CWAB that might aid you or use CWAB. It's really up to you.

Back to the fishing metaphor. Think of the patterns as you would think of knowing how to fish. Then think of CAB, CWAB, Prism is different kinds of fishing poles. Think of the challenges you are addressing in your apps as the fish. If all you learn is how to use one fishing pole, then that's not very useful. Having a knowledge of fishing means you are free to choose the pole of your choice, or create your own ;-)

In the new "Prism" work you are going to see us driving seriously on the underlying patterns for building Composite WPF applications rather than just reusable code libraries. Yes we'll give you a fishing pole (though it may not be the right pole for catching every kind of fish) but we'll show you how to fish first.

Friday February 15th, 2008

4.6

Build your own CAB #18: The Command Executor

CodeBetter.Com From CodeBetter.Com, 7 months ago, 0 comments Comment

The rest of the Build your own CAB series can be found at the table of contents.

 

There's a thread on the altdotnet list this morning about how to unit test background operations originating from a screen Presenter.  I have a strategy for that in StoryTeller that I think has worked out quite well.  Instead of creating a background worker or thread directly in a screen presenter, I run all background actions through what I call a "Command Executor."  When a presenter or a menu command needs to run some sort of asynchronous command I have that class delegate to an instance of an ICommandExecutor interface.  The interface for the ICommandExecutor in StoryTeller is shown below:

    public interface ICommandExecutor : IStartable
{
void Stop();
void ExecuteCommandWithCallback(ICommand command, ICommand callback);
void ExecuteCommand(ICommand command);
}

You'll see that the ICommandExecutor takes in the inevitable ICommand interface because this was written in .Net 1.1 and ported upwards later.  I think for my new project I'm going to something more like this to take advantage of lambda expressions instead of cluttering up the code with extraneous class definitions.

public interface ICommandExecutor
{
void Execute(Action action);
void ExecuteWithCallback(Action action, Action callback);
}

Now, why would you do this?  Using a BackgroundWorker or a background thread isn't that hard, but:

  1. The threading code is noise code that distracts the reader from the real meaning of the code.  The CommandExecutor pattern let's us change the code semantics inside the Presenter into merely a call to "run this in the background."
  2. It's potentially a lot of repetitive code to set up threads or bootstrap a BackgroundWorker.  You have to remember to do the thread synchronization every single time.  By using a Command Executor you can write the multi threaded code once and only once, including the work to synchronize threads (I use a SynchronizationContext in my CommandExecutor for the callbacks.  No need for AOP black magic whatsoever).
  3. You do NOT want any important behavioral or business logic code to be coupled to the UI machinery.  I see a lot of teams absolutely screw themselves over by embedding logic directly into the DoWork event of a BackgroundWorker, rendering that code effectively impossible to reuse or unit test.  The CommandExecutor will help push teams to separate the behavioral logic away from threading infrastructure to make that code both easier to test and reuse.
  4. The background threading is rougher in unit testing.  Not impossible, but it does add some significant overhead to the unit testing effort.

Let's take the testing angle first.  The original problem was how to be able to unit test the background operation.  The easiest way is to simply turn the asynchronous behavior completely off by substituting in a synchronous command executor in the unit tests like this:

    public class SynchronousCommandExecutor : ICommandExecutor
{
public void Stop()
{
// no-op;
}

public void ExecuteCommandWithCallback(ICommand command, ICommand callback)
{
command.Execute();
callback.Execute();
}

public void ExecuteCommand(ICommand command)
{
command.Execute();
}

public void Start()
{
// no-op;
}
}

Now you can simply run your unit test and test the asynchronous behavior without having to setup ManualResetEvent's or other thread synchronization machinery.  In StoryTeller I usually just test that the proper ICommand message was sent to the ICommandExecutor and call it good enough.  I'll then turn around and test the ICommand.Execute() method in isolation in another unit test.

So far, I've found this pattern pretty well eliminates all of my unit testing problems with background operations.  For integration testing one of your challenges for testing a user interface is asynchronous events.  One of the solutions I've found to this problem is to route all background operations through some sort of CommandExecutor so that the test harness has a single place to watch in order to synchronize the test script with the user interface. 

 

 

Anyway, I banged this out fast.  Any thoughts?

5.8

Code metrics on Coupling, Dead Code, Design flaws and Re-engineering

CodeBetter.Com From CodeBetter.Com, 7 months ago, 0 comments Comment

There is a whole range of interesting code metrics relative to coupling. The simplest ones are named Afferent Coupling (Ca) and Efferent Coupling (Ce). Basically, the Ca for a code element is the number of code elements that use it and the Ce is the number of code elements that it uses.




You can define Ca and Ce for the graph of assemblies dependencies, the graph of namespaces dependencies, the graph of types dependencies and the graph of methods dependencies of a code base. You can also define the Ca metric on the fields of a program as the number of methods that access the field. This leads to 9 metrics all supported by the tool NDepend. We precise that when computing Ce, NDepend takes account of code elements defined in tier code such as the code of the .NET framework.

 

With NDepend, if you wish to know which methods of your program are massively used you can write the following CQL Query :

 

SELECT TOP 10 METHODS ORDER BY MethodCa DESC

 

Being used a lot is not necessarily a problem. However it is still interesting to know which part of your code base is used a lot. For example, if we apply the CQL query below to the core of the .NET framework (i.e mscorlib, System, System.Core, System.Xml…) we obtain the following 10 methods:

 

methods

Afferent coupling at method level (MethodCa)

System.Environment.GetResourceString(String)

2632

System.Object..ctor()

2416

System.ArgumentNullException..ctor(String)

2368

System.String.get_Length()

1795

System.Type.GetTypeFromHandle(RuntimeTypeHandle)

1762

System.IDisposable.Dispose()

1119

System.SR.GetString(String)

1115

System.InvalidOperationException..ctor(String)

1101

System.Object.ToString()

1056

System.ArgumentException..ctor(String)

1010

 

 

High Efferent Coupling and design flaws

 

If you wish to know which types of your program are heavy users of other types you just have to write:

 

SELECT TOP 10 TYPES ORDER BY TypeCe DESC

 

High Ce might reveal a design problem. Types with high Ce are entangled with many other implementations. The higher the Ce, the higher the number of responsibilities the type has. If we apply the CQL query above to the core of the .NET framework we obtain the following list:

 

types

Efferent coupling at type level (TypeCe)

Microsoft.CSharp.CSharpCodeGenerator

172

Microsoft.VisualBasic.VBCodeGenerator

161

System.Net.HttpWebRequest

138

System.Net.Sockets.Socket

137

System.AppDomain

131

System.RuntimeType

128

System.Xml.Xsl.XsltOld.Compiler

125

System.Xml.Xsl.Xslt.QilGenerator

124

System.Xml.Serialization.XmlSchemaImporter

120

System.Diagnostics.Process

116

 

As expected this list contains high level classes such as AppDomain, Process or Socket. This sort of classes with high Ce are needed to implement complex concepts that spawn numerous concerns. For example, by selecting the 131 types used by the AppDomain class I can tell that AppDomain is concerned by assembly security (Code Access Security, strong naming…), Windows users and file security, OS environment info, .NET Remoting, .NET Reflection, Threading and globalization.
 

Could the AppDomain class be split into several smaller classes? I guess no because this is such an essential class. But this is the exception. Generally, classes with high Ce would be more like the CSharpCodeGenerator class which represent alone a component. I can see that the class CSharpCodeGenerator deals with a lot of implementation detail of the C# language such as exception, type casting, all sorts of members (method, field, event, property…), comment, indentation etc. This sounds good as long as each details has its own implementation the class CSharpCodeGenerator acts as a high level mediator. But if I dig further and decompile some methods I can see that the class CSharpCodeGenerator also cops with file management and contains a lot of logic (>1000 Lines of Code) to handle some CodeDOM details. This is likely an indication that this code could have been better designed with the help of several smaller collaborating classes.

 

Afferent Coupling and Dead Code

 

Ce values are meaningful values when it comes to assessing some design and when you have to re-engineer code. Ca values are also useful, especially when equal to 0. A Ca value equals to 0 indicates a potential dead code element. A dead code element is an element that can be discarded because it is not used by the program anymore. Pruning dead code is a necessary task to make sure that your code is rationalized. Here also the tool NDepend can help you because it knows about Ca. However things get more complicated here because there are numerous cases where a zero Ca doesn’t mean dead code. For example, entry points (i.e Main methods), class constructors or finalizers represent some methods that will always have a zero Ca. However these methods are not dead code because the CLR will call them at runtime.

 

Here is the CQL rule that we provide by default to detect dead methods:

 

// <Name>Potentially unused methods</Name>

WARN IF Count > 0 IN SELECT TOP 10 METHODS WHERE

 MethodCa == 0 AND            // Ca=0 -> No Afferent Coupling -> The method 

                              // is not used in the context of this

                              // application.

 

 !IsPublic AND                // Public methods might be used by client 

                              // applications of your assemblies.

 

 !IsEntryPoint AND            // Main() method is not used by-design.

 

 !IsExplicitInterfaceImpl AND // The IL code never explicitely calls 

                              // explicit interface methods implementation.

 

 !IsClassConstructor AND      // The IL code never explicitely calls class

                              // constructors.

 

 !IsFinalizer                 // The IL code never explicitely calls

                              // finalizers.

 

Notice how we consider that public methods should be not considered as dead code in the general case. This rule generally matches a lot of false positive because when statically analyzing the IL code, we can see that often overridden implementations are not statically linked. Hence to get a first evaluation of dead code it is worth adding the restricting condition AND !IsVirtual. This particular issue will be addressed by further versions of NDepend.

 

Things gets more easy and efficient when it comes to detect dead fields and dead types. Here are the 2 CQL rules we propose by default and their particular conditions to avoid false positive:

 

// <Name>Potentially unused fields</Name>

WARN IF Count > 0 IN SELECT TOP 10 FIELDS WHERE

 FieldCa == 0 AND  // Ca=0 -> No Afferent Coupling -> The field is not used

                   // in the context of this application.

 

 !IsPublic AND     // Although not recommended, public fields might be used

                   // by client applications of your assemblies.

 

 !IsLiteral AND    // The IL code never explicitely uses literal fields.

 

 !IsEnumValue AND  // The IL code never explicitely uses enumeration value.

 

 !NameIs "value__" // Field named 'value__' are relative to enumerations 

                   // and the IL code never explicitely uses them.

 

 

 

// <Name>Potentially unused types</Name>

WARN IF Count > 0 IN SELECT TOP 10 TYPES WHERE

 TypeCa == 0 AND     // Ca=0 -> No Afferent Coupling -> The type is not 

                     // used in the context of this application.

 

 !IsPublic AND       // Public types might be used by client 

                     // applications of your assemblies.

 

 !NameIs "Program"   // Generally, types named Program contain a Main() 

                     // entry-point method and this condition avoid 

                     // to consider such type as unused code.

 

Notice how easy it is to customize these rules thanks to CQL facilities such as NameIs, NameLike, SELECT OUT OF/FROM etc…

 

 

Ranking Metrics

 

Since with NDepend, we have an efficient in-memory representation of internal dependencies of a code base, we got the idea of implementing the famous Google Page Rank algorithm to the graph of methods and the graph of types. As a consequence, the 2 metrics TypeRank and MethodRank indicate which types and which methods of a code base are the most important. As a web page with Google, a code element is considered as important if it is used by numerous code elements that themselves are considered more or less important.

 

When discovering a code base knowing which types and methods are important is -well- important, because they likely represent the cornerstone of the code base, the ones that you will have to understand first in order to dig into the program structure. If you have the chance to be educated on the code base by one of its developer, she will likely talk to you first about these important code elements in order to give you the basics. What is cool is that you can know automatically and objectively about this information thanks to the ranking metrics.

 

For example, suppose if you were a complete beginner in .NET programming, what would be the top 10 most important types to know about? Integer? String? Object? Bool? Let’s see what the TypeRank metric has to say about the top 10 most important types of the .NET framework:

 

SELECT TOP 10 TYPES ORDER BY TypeRank DESC

 

types

Type Rank

System.Runtime.InteropServices.ComVisibleAttribute

409.03

System.Object

380.89

System.Runtime.InteropServices.ClassInterfaceAttribute

329.73

System.Void

281.02

System.CLSCompliantAttribute

189.13

System.Int32

170.17

System.Boolean

168.88

System.Runtime.InteropServices.GuidAttribute

153.64

System.String

145.63

System.Runtime.InteropServices.InterfaceTypeAttribute

143.32

 

Hopefully we find the types that we considered important, but we also get some interesting finds that show how the COM and interop things such as ComVisibleAttribute or GuidAttribute are so pervasive inside the .NET framework MS implementation.

 

We also precise that code that is considered important deserves even more attention than the rest in terms of test code coverage and design.

 

NDepend supports also several others code metrics relative to coupling such the Association Between Classes, the Lack Of Cohesion of Methods (LCOM) and the Robert C.Martin metrics on assemblies. I will certainly write some thoughts on all these on future posts. Meantime you can read their definition and try them on your own code base. You can also have a glance and print the great NDepend Poster Metrics done by Stuart Celarier, Patrick Cauldwell and Scott Hanselman .

 

 

Wednesday February 13th, 2008

1.0

Nothin But WPF Class - Cancelled

CodeBetter.Com From CodeBetter.Com, 7 months ago, 0 comments Comment

Unfortunately due to low numbers the WPF class is going to be cancelled. I apologize to anyone who was planning on registering.

Thanks.

5.6

Code Camps are about Building Community, Not Presentations...

CodeBetter.Com From CodeBetter.Com, 7 months ago, 0 comments Comment

Although I appreciate the recent posts about presentation tips as we enter a new season of code camps, it is important to not lose sight of the real value of code camps. Code camps are not about presentations. Code camps are about building a healthy and active local developer community.

Code camps entice developers to come out and participate with other developers who share a similar passion. The developers come out and build new friends and relationships and eventually begin contributing to the community for which they have received so much. One of the best ways to contribute is to present at various developer groups and code camps.

This is an exciting turning point in both the developer and the community. The developer is no longer satisfied with just receiving, but wants to give back to the community by presenting at a local developer group or code camp. And even though they are probably fearful of failing and need to shell out their own money for expenses, the community means more to them. They are willing to face those fears and part with their hard earned money. I applaud them.

Personally, I want more new and maturing presenters at code camps. 80% of the battle to becoming a good presenter is to get past the fear and nervousness of presenting in front of a crowd. Sure you need to prepare for the presentation and various presentation tips that have been given are useful, but the key is confidence, and confidence is only gained by presenting and having a healthy developer community that encourages new and inexperienced speakers.

These new and inexperienced presenters at our code camps are the future rockstars and the life blood of the community. The cool thing is that we get to watch them develop their leadership, presentation, and technical skills in the community. One day the presenter is that nervous "unknown" developer, and the next day he or she is speaking at major conferences, working for Microsoft, or what have ya.

It is an amazing experience for us all.

For those of you organizing a code camp, I hope you help these future rockstars : CodeCamps - Encourage, Assist and Thank Your First-Time and Maturing Speakers

5.3

Presenter First - Who starts the presenter

CodeBetter.Com From CodeBetter.Com, 7 months ago, 0 comments Comment

Had a question recently with regards to presenter first deve