June 2010 - Posts

Using Rx for Event subscription

I thought I would have a quick look to determine wether Rx would create a strong reference under the hood or not when one object subscribed to another objects events. In this case the Consumer object subscribes to the SampleData objects's SampleDataChanged event. This type of strong reference causes memory leaks in applications because the garbage collector will not clean up the event consumer even though the consumer may be out of scope. The result of my testing indicates that unfortunately there is still a strong reference because once the Consumer object goes out of scope and once Garbage collection has been called, calling the event on SampleData still causes the event to be raised in the Consumer meaning that the consumer has not been garbage collected. Can I use the System.WeakReference object to resolve this issue? I will follow up on this shortly...


using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace WeakReferenceTestConsole

{

    class Program

    {

 

        static void Main(string[] args)

        {

 

            SampleData sampleData = new SampleData();

 

            for (int i = 0; i < 3; i++)

            {

                WorkOnData(sampleData, i);

            }

 

            sampleData.RaiseSampleDataChanged("Sample Data change - Consumer outside scope");

 

            // Force garbage collection

            GC.Collect();

            GC.WaitForPendingFinalizers();

 

            sampleData.RaiseSampleDataChanged("Sample Data change - Consumer outside scope - After garbage collection");

 

            Console.ReadKey();

        }

 

        private static void WorkOnData(SampleData sampleData, int iteration)

        {

            // Create a consumer which registers a method with the sample data objects SampleDataChanged event

            Consumer consumer = new Consumer(sampleData);

            consumer.Name = "Consumer " + iteration.ToString();

 

            //Raise the sample data object's data changed event

            sampleData.RaiseSampleDataChanged("Work on data - iteration : " + iteration.ToString());

        }

 

    }

 

    public class Consumer

    {

 

        //private SampleData _sampleData;

 

        public Consumer(SampleData sampleData)

        {

            //_sampleData = sampleData;

            //sampleData.SampleDataChanged += new SampleData.SampleDataChangedEventHandler(Consumer_SampleDataChanged);

 

            Observable.FromEvent<SampleDataChangedEventArgs>(sampleData, "SampleDataChanged").Subscribe(

                args =>

                Consumer_SampleDataChanged(sampleData, (SampleDataChangedEventArgs)args.EventArgs)

                );

 

        }

 

        public string Name { get; set; }

 

        void Consumer_SampleDataChanged(object sender, SampleDataChangedEventArgs e)

        {

            Console.WriteLine("Sample Data Changed : {0} - Notified Consumer : {1}", e.Message, this.Name);

        }

 

        ~Consumer()

        {

            Console.WriteLine("Consumer finalizer");

        }

    }

 

    public class SampleData

    {

        public event SampleDataChangedEventHandler SampleDataChanged;

        public delegate void SampleDataChangedEventHandler(object sender, SampleDataChangedEventArgs e);

 

        public void RaiseSampleDataChanged(string message)

        {

            SampleDataChangedEventHandler handler = SampleDataChanged;

 

            if (handler != null)

            {

 

                SampleDataChangedEventArgs e = new SampleDataChangedEventArgs(message);

                SampleDataChanged(this, e);

            }

 

        }

 

    }

 

    public class SampleDataChangedEventArgs : EventArgs

    {

        public SampleDataChangedEventArgs(string message)

        {

            this.Message = message;

        }

 

        public string Message { get; set; }

    }

 

 

}

 

 

 

The enemy within. A bleak view into the lack of regulation in the IT industry.

“I value simplicity over everything; I always look for simplicity.”

 Anders Hejlsberg quote

As a programmer I love writing code. Make no mistake. I love flexing my mind and seeing if I can find a short and elegant route to the solution required to resolve a problem or satisfy a business requirement. The key words in that sentence are "short" and "elegant". What I mean by those words are that I prefer the fewest lines of code possible and I feel a strong need to leverage the available technologies in the most efficient and effective manner possible. Since I am a C# programmer, "efficient" means selecting the necessary 3rd party libraries or preferably using the standard libraries that come with the .Net framework that provide acceptable performance. "Effective" meaning they solve the problem in a way that produces the minimum amount of technical debt.

My favourite saying has always been "The only thing I enjoy more than writing code ... is deleting code." What I mean by this is that when I approach a legacy application in order to make changes to it or to update the functionality I keep a keen eye on attempting to identify the areas where I can delete unnecessary code.

This includes:

a) Code that has been is duplicated, not properly encapsulated into re-usable units.

b) Identifying areas where the wheel has been re-invented. An API or set of tools/libraries already existed that do the job in a more elegant (and probably more efficient) manner.

c) Identifying areas where there are unnecessary abstractions or layers of indirection.

I firmly believe that it is our duty as programmers to build maintainable and scalable applications which minimize the level of complexity within the code we write. By managing the complexity within the code we write we are able to handle and thus implement more complex business rules. This leads me onto the main reason for this blog post... The problem is that programmers admire complexity and sometimes over complicate solutions to gain "intellectual control" over the code they produce. The more difficult or complex a solution the more likely the business will develop a dependency on the developer that built that solution to maintain that solution, since they understand the solution the best and would require the least amount of time to make bug fixes or updates to the code. Management are unable to identify code that has been made to be unnecessarily complex, and when they do they are presented with reasons such as "The solution is re-usable" or "We might need that functionality for scenario A...", and needless to say scenario A is as inevitable as being hit by a meteorite.... Possible but highly unlikely.

At the moment the IT industry is suffering from the following symptoms:

1) Legacy systems that have been difficult to maintain and are undocumented.

2) Having developers take control of the core of the business by becoming dependent on the custom in house Software built to run the business.

3) Having no control mechanisms in place that will review code written by the developers.

As Billy Hollis rightly states we are all code addicts as programmers, and we need to fight this code addiction. We the programmers must avoid becoming the enemy within the organization and ensure our code is maintainable and well documented. I will attempt to provide a set of processes which management can put in place to avoid the symptoms mentioned above.

Posted by jean with no comments
Filed under: