// ThomasWeller

C#/.NET software development, software integrity, life as a freelancer, and all the rest


News

Stack Overflow profile for Thomas Weller
Thomas Weller on bitbucket.org


Gallio Banner

Mercurial

Typemock Isolator

Can’t code without   The best C# coding assistance and
    refactoring plugin for Visual Studio

My Stats

  • Posts - 43
  • Comments - 127
  • Trackbacks - 0

Tag Cloud


Recent Comments


Recent Posts


Archives


Post Categories


Free e-Books


Toolbox: Development


Toolbox: Documentation


Toolbox: Productivity


Toolbox: Static analysis


Toolbox: Testing


Toolbox: Textual analysis



Lately I played around a bit with Aspect Oriented Programming, especially with PostSharp. I wanted to see how I could use it to reduce the amount of infrastructural code that clutters a common class like this:

public class Person : INotifyPropertyChanged

{

    private string firstName;

    private string lastName;

    private int age;

 

    public string LastName

    {

        get { return this.lastName; }

        set

        {

            // check the argument value

            if (value == null)

            {

                throw new ArgumentNullException("value");

            }

            if (value == "")

            {

                throw new ArgumentException("Last Name must not be empty.", "value");

            }

            if (value.Length > 50)

            {

                throw new ArgumentException("Last Name must not be longer than 50 characters.",

                                            "value");

            }

 

            // do nothing when trying to set the same value twice

            if (value == this.lastName)

            {

                return;

            }           

 

            // set the value

            this.lastName = value;

 

            // fire PropertyChanged events

            this.OnPropertyChanged("LastName");

            this.OnPropertyChanged("FullName");

        }

    }

 

    public string FirstName

    {

        get { return this.firstName; }

        set

        {

            // check the argument value

            if (value != null)

            {

                if (value.Length > 30)

                {

                    throw new ArgumentException("First Name must not be longer than 30 characters.",

                                                "value");

                }

            }

 

            // do nothing when trying to set the same value twice

            if (value == this.firstName)

            {

                return;

            }

 

            // set the value

            this.firstName = value;

 

            // fire PropertyChanged events

            this.OnPropertyChanged("FirstName");

            this.OnPropertyChanged("FullName");

        }

    }

 

    public string FullName

    {

        get

        {

            return (this.firstName + " " + this.lastName).Trim();

        }

    }

 

    public int Age

    {

        get { return this.age; }

        set

        {

            if (value < 18 || value > 65)

            {

                throw new ArgumentOutOfRangeException("value", "Age must be between 18 and 65.");

            }

 

            this.age = value;

        }

    }

 

    #region INotifyPropertyChanged implementation

 

    public event PropertyChangedEventHandler PropertyChanged;

 

    private void OnPropertyChanged(string propertyName)

    {

        if (PropertyChanged != null)

        {

            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));

        }

    }

 

    #endregion // INotifyPropertyChanged implementation

 

} // class Person

Most of the code of this class is value-checking and a bit of INotifyPropertyChanged-logic, like you frequently have it with business objects and some sort of Model-View-Presenter/Controller-style UI coupling or WPF. But no matter how important such code is in terms of correct program behavior, it is repetitive and boring - certainly not the kind of stuff that made me become a developer. Code like this is mostly written in the 'classic' copy-paste-modify coding style, with all the problems that this may bring...

Now look at that:

[Validate, NotifyPropertyChanged(OnPropertyChanged = "OnPropertyChanged")]

public class PersonWithAspects : INotifyPropertyChanged

{

    [NotNullOrEmpty, MaximumLength(50)]

    [PropertyChangedDependency("FullName")]

    public string LastName { get; set; }

 

    [PropertyChangedDependency("FullName")]

    [MaximumLength(30)]

    public string FirstName { get; set; }

 

    [InRange(18, 65)]

    [NoPropertyChangedEvent]

    public int Age { get; set; }

 

    public string FullName

    {

        get

        {

            return (this.FirstName + " " + this.LastName).Trim();

        }

    }

 

    #region INotifyPropertyChanged implementation

 

    public event PropertyChangedEventHandler PropertyChanged;

 

    private void OnPropertyChanged(string propertyName)

    {

        if (PropertyChanged != null)

        {

            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));

        }

    }

 

    #endregion // INotifyPropertyChanged implementation

 

} // class PersonWithAspects

This version of the Person class is absolutely identical to the first one in terms of behavior (except that it throws a different exception type), but it has almost no hand-written code, only some declarative attributes. This reduced the number of code lines for the properties in this simple example from 36 to 11 - or by about 70%! Wow...

I did it with the ValidationAspects aspect library, that sits on top of the PostSharp aspect weaver and allows for placing Design by Contract - like attributes on properties (and also on method arguments). Additionally, I took the INotifyPropertyChanged sample from the PostSharp 1.5 download and modified it slightly to include the NoPropertyChangedEvent and PropertyChangedDependency attributes. It was not much work, and the result is quite impressive, I think.

Besides the pure technical aspects (much better readability and expressiveness, dramatically reduced error-proneness etc.), code like this gives me the warm feeling of having done a good job. In fact, deleting code (while preserving functionality) is one of my favorite activities in writing software. I know that this might sound a bit strange from someone who calls himself a software developer - but if you think about it for a minute, it perfectly makes sense...

 

kickit
shoutit
delicious facebook digg reddit linkedin stumbleupon technorati mrwong yahoo google-48x48 twitter email favorites
  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Comments

Gravatar # re: AOP can save you tons of repetitive code
Posted by Sean Blakemore on 9/18/2009 1:49 AM
Great work with this.

One suggestion, unless other code of yours is explicitly subscribing to the events, shouldn't it be possible to move the actual implementation of INotifyPropertyChanged to being weaved in by PostSharp also? This wouldn't effect runtime subscription to the event by databinding infrastructure. Now that would really by the icing to this...
Gravatar # re: AOP can save you tons of repetitive code
Posted by Thomas Weller on 9/18/2009 5:39 AM
Hi Sean,

thanks for the kind words.

Doing what you suggest would of course be the most elegant solution in terms of aspect implementation, and it would reduce the number of code lines even more, leaving only the bare minimum.
The reason why I decided to not do it that way in the end is - as you suppose - that I think the INotifyPropertyChanged interface should be visible for calling code (to do things like mocking, event subscription, casting...) and for readers. Totally 'hiding' the interface behind an aspect IMHO would make the code slightly less flexible and expressive.

- Thomas

Gravatar # re: ccan save you tons of repetitive code
Posted by essay on 9/23/2009 3:05 PM
very detailed and helpful information for my site about AOP
Gravatar # re: AOP can save you tons of repetitive code
Posted by Luke Winikates on 1/5/2012 9:35 PM
This is pretty cool-- I love the idea aspect-oriented stuff for things like INotifyPropertyChanged.

Do you think that "[PropertyChangedDependency("FullName")]" could be taken a step further? It seems like some kind of static analysis could see that two other properties participate in the definition of "FullName", and could apply the equivalent PropertyChangedDependency automatically. I'm dreaming of either a trick to get ReSharper to do this for me, or a class-level aspect that could somehow accomplish this with a similar concision to your example, which is awesome.
Post A Comment
Title:
Name:
Email:
Website:
Comment:
Verification: