Wednesday, September 22, 2010

Simple abstraction and decoupling example

Just code.


We have a logger and a log viewer, could be better but I wanted it to be simple.


This is the window that is also the log viewer
/// <summary>
  /// Interaction logic for MainWindow.xaml
  /// </summary>
  public partial class MainWindow : Window, ILogViewer
  {
    public MainWindow()
    {
      InitializeComponent();
      Logger.RegisterViewer(this);
    }

    public void Log(string message)
    {
      // do the write logic
    }
  }

This is the interface of viewers
public interface ILogViewer
{
  void Log(string message);
}
This is logger
public static class Logger
{
  static List<ILogViewer> viewers = new List<ILogViewer>();

  public static void RegisterViewer(ILogViewer viewer)
  {
    viewers.Add(viewer);
  }

  public static void Log(string message)
  {
    foreach (ILogViewer viewer in viewers)
    {
      viewer.Log(message);
    }
  }
}

Tuesday, September 14, 2010

Simple Rx Sample - UI Performance tuning

The case I'm talking about is Binding with the UpdateSourceTrigger = PropertyChanged, and a heavy logic behind each change that can cause bad UX, like ui freeze on each key press in a text box.

Here is a nice sample that demonstrate this case:
I have a window with a text box and 2 buttons, the IsEnabled of the buttons is bounded to custom properties that depends on the TextBox text bounded field to decide if the button should be enabled (just like commands).
This is the window
This is the window xaml




<Window x:Class="ReactivlyPropertyChanged.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525" x:Name="this">
    <Grid>
        <StackPanel>
            <TextBox Text="{Binding SomeText, ElementName=this, UpdateSourceTrigger=PropertyChanged}"/>
            <Button IsEnabled="{Binding ElementName=this, Path=CanSplitInMiddle}">2</Button>
            <Button IsEnabled="{Binding ElementName=this, Path=CanSplitToThreeParts}">3</Button>

        </StackPanel>
    </Grid>
</Window>


This is the bounded properties implementation (I added sleep to demonstrate long time consumers)
private string _someText;

        public string SomeText
        {
            get { return _someText; }
            set
            {
                _someText = value;
                RaisePropertyChanged("SomeText");
            }
        }

        public bool CanSplitInMiddle
        {
            get
            {
                if (SomeText == null)
                    return false;
                Thread.Sleep(100);
                return SomeText.Length % 2 == 0;
            }
        }

        public bool CanSplitToThreeParts
        {
            get
            {
                if (SomeText == null)
                    return false;
                Thread.Sleep(100);
                return SomeText.Length % 3 == 0;
            }
        }

As you can see there is a simple length check of the entered string, now you probably think that the application would get stuck for each key press for at least 200 ms.


Take a look at the property changed handling:


public MainWindow()
{
    // Sets the buffer time for property changed
    var interval = 500;

    InitializeComponent();

      // Create observable from the property changed event
    var propertyChangedObservable = 
        Observable.FromEvent<PropertyChangedEventArgs>(this, "PropertyChanged").
        BufferWithTime(TimeSpan.FromMilliseconds(interval));

      // Define our query from the event, we want to get all fired propertyChanged
    var query = from changedProps in propertyChangedObservable
                where changedProps.Count > 0 
                select changedProps;
                            
      // start listening
    query.Subscribe(listOfChangedStuff =>
    {
// When fired group all events by property name and handle each property with Changed method
        var events = from distinctEvent in listOfChangedStuff
                                 group distinctEvent by distinctEvent.EventArgs.PropertyName into byPropertyName
                                 select byPropertyName;

        foreach (IGrouping<string,IEvent<PropertyChangedEventArgs>> groupedEvent in events)
        {
            Changed(groupedEvent.Key);
        }
    });        
}

public void Changed(string propertyName)
{
    if (propertyName == "SomeText")
    {
       // Make the properties recalculate themself
        RaisePropertyChanged("CanSplitInMiddle");
        RaisePropertyChanged("CanSplitToThreeParts");
    }
}

public void RaisePropertyChanged(string propertyName)
{
    var handlers = PropertyChanged;
    if (handlers != null)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}


So WTF?


One of Rx many features is buffer,I can tell property changed event to buffer himself for some time, and when the time passed take all fired events and work with them, what I did is to group all events by the property name (like distinct in sql) and handled each group as a single event.


So even if the user is a super turbo writer(or the bot that test the ui) , the event will fired only 2 times in a second, for 500 ms interval.


I think this is awesome, you can configure the buffer interval according to how complex and time consuming your logic is, and avoid freezing ui.


I wanted to upload the code to somewhere but o got to fly...

Monday, September 6, 2010

For AMT Rx for .net

Here is a good place to  start with Rx for .net

And here you have the wiki with examples

Enjoy!

Thursday, September 2, 2010

WCF client side proxy memory leaks

Today I ran into a guy who worked with me on my previous project.
On that project I was responsible to rewrite the WCF channels (proxies) generation management and lifetime management of them.
I decided to do some research and found some good stuff here.
So this guy (aka Kurki) tells me they found a memory leak in my manager, what was the problem?

So i messed up like I always do (well, only 90% of the time, like a good programmer).

I wrote a code that registers to the Faulted event of the channel, kills the channel when Faulted and creates a new one to work with, everything looked fine, only one screw up (I'm sure some of you can guess).
I forgot to unregister from the Faulted Event.

On the web they tell you to do some unique logic to kill your channel in a safe way, what they don't talk about is that it'll stay in memory and fire events if you won't unregister from stuff although you think it is dead.

So please do not forget to unregister from stuff even if the object is disposable.

Or consider the use of weak event listeners and problem solved.

Wednesday, September 1, 2010

Unit Test PropertyChanged

One of the basic stuff you wanna test as a client side developer, is that all of your UI bounded classes aka Controller, Model, ViewModel, Presenter, PresentationModel, or the code behind of your view if your just having fun.

Let's assume we have a person class with a name property:

public class Person : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private string _name;

    public virtual string Name
    {
        get { return _name; }
        set { _name = value;
        FirePropertyChanged("Name");
        }
    }

    protected virtual void FirePropertyChanged(string propertyName)
    {
        var handlers = PropertyChanged;
        if (handlers != null)
        {
            handlers(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
The simplest way to perform this test is to write this code:

[TestFixture]
public class PersonTest
{
    [Test]
    public void SetName_SomeNewString_FirePropertyChanged()
    {
        Person person = new Person();
        string changedPropertyName = string.Empty;
        person.PropertyChanged += (sender, args) => changedPropertyName = args.PropertyName;
        person.Name = "Test";
        Assert.AreEqual("Name", changedPropertyName);
    }
}

Hello World

public class Chen
{
  public void SayHello()
  {
    Console.WriteLine("Hello everyone! this is my first blog post, its about time");
  }
}