Click here to Skip to main content
Click here to Skip to main content

Delegates Are Good, and Good For You

By , 29 Aug 2011
 
Have you ever been in the situation where you have a considerable base of existing code, and you need to add functionality, but you simply don't have the time to refactor all of the code to explicitly support the desired functionality? I'm sure anyone here with more than a few years of experience can answer "yes" to that question.
 
Today, I was faced with just such a situation. I'm working on a Silverlight app that displays a page on a button press. This page displays one of dozens of available views (depending on the button that caused the page to be displayed), and each view contains a collection of panels that display various data items. The panels can be manually expanded - or "zoomed" - by the user to consume the entire viewable area. The data for the panels may or may not be available, meaning that one or more of the panels would essentially be empty (or display a message saying no data is available). In that event, we want to automatically expand the panel that DOES contain data.
 
The best way (I think) to do this would be to change the constructor for the various chart views (there are several already implemented), but that could possibly cause problems with what is already expected, thus slowing development by everyone involved. I had to come up with a different solution, and the result is my tip.
 
I used a delegate. Delegates are kind of scarey for new programmers, but they're a godsend when you need a quick fix that doesn't require extensive changes to method/constructor parameter lists and such.
 
First, I came up with the method in my parent class:
 
public void ZoomPanelFromView(PanelType panel)
{
    // The methods called here already exist and are event handlers for when 
    // the user clicks one of the associated zoom buttons.
    switch (panel)
    {
        case PanelType.Main       : zMain_MouseLeftButtonUp(null, null); break;
        case PanelType.Ahead      : zAhead_MouseLeftButtonUp(null, null); break;
        case PanelType.AlibiTrend : zTrend_MouseLeftButtonUp(null, null); break;
    }
}
 
Next, I declared a globally accessible delegate that implemented the prototype for the method I was trying to "expose" from the parent class.
 
public delegate void PanelZoomer(PanelType panel);
 
Then, I declared a data member in a static class that I use for globally accessible methods and data members:
 
public class Globals
{
    // this delegate allows the chart classes to callback to the parent page and 
    // zoom the specified  panel
    public static PanelZoomer PanelZoom;
 
    public static Globals(){}
}
 
Now, with all of the pieces in place, I could set it in the parent class:
 
Globals.PanelZoom = this.ZoomPanelView;
 
...and use it from my view class that knows nothing of the parent page:
 
    if (Globals.PanelZoom != null && m_dataPoints.Count == 0 && string.IsNullOrEmpty(m_data.textData))
    {
        Globals.PanelZoom(PanelType.Main);
    }
 
My solution didn't break anything, and requires no regression testing beyond making sure the user can still manually zoom the panels. Because I check for nullness on the delegate, I'm ensuring that the delegate has been set before using it. Everyone's happy, nobody has to change what they're doing or have already done with regards to the code already written, and we're free to add an overloaded constructor at our convenience. For the record, this is the only reason so far that the view class would have to know about the parent page at all, and IMHO, this doesn't warrant creating an overloaded constructor that allows the page to pass a pointer to itself to the view.
 
Yeah, I acknowledge that this breaks pretty much any OOP rule you might mention, and a band-aid like this is probably not the best solution, but the realities of working in a production environment are the biggest contributing factors of what you can and cannot implement when you're on a schedule.
 
I view OOP rules (and pretty much any other stuff you might consider to be a rule) as mere guidelines of things you SHOULD do, not what you MUST do. Finally, as long as your code is well documented (INCLUDING the *why-I-did-it" AND "where-I-did-it" behind the code), maintenance programmers can easily follow and modify your code without any problems at all.
 
There are a couple of additional tips here. Don't be rigid in your compliance with "industry standards", and be ready to look at a problem from different angles.
 
EDIT (29 Aug 2011) ================
 
Fixed some glaring typos.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

John Simmons / outlaw programmer
Software Developer (Senior)
United States United States
Member
I've been paid as a programmer since 1982 with experience in Pascal, and C++ (both self-taught), and began writing Windows programs in 1991 using Visual C++ and MFC. In the 2nd half of 2007, I started writing C# Windows Forms and ASP.Net applications, and have since done WPF, Silverlight, WCF, web services, and Windows services.
 
My weakest point is that my moments of clarity are too brief to hold a meaningful conversation that requires more than 30 seconds to complete. Thankfully, grunts of agreement are all that is required to conduct most discussions without committing to any particular belief system.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralWhy couldn't you have overloaded the constructor? The origi...memberSteve Roberson6 Sep '11 - 9:53 
Why couldn't you have overloaded the constructor? The original constructor could still be called and not break existing code.
GeneralReason for my vote of 5 Good article with clear explaination...memberAll Time Programming5 Sep '11 - 21:28 
Reason for my vote of 5
Good article with clear explainations.
GeneralReason for my vote of 5 Good aricle John and i agree with yo...memberKurniawan Prasetyo5 Sep '11 - 21:25 
Reason for my vote of 5
Good aricle John and i agree with you.
GeneralReason for my vote of 5 Good articlemembermandar13051 Sep '11 - 21:34 
Reason for my vote of 5
Good article
GeneralReason for my vote of 5 Thanks, John.subeditorWalt Fair, Jr.29 Aug '11 - 13:51 
Reason for my vote of 5
Thanks, John.
GeneralReason for my vote of 5 Great use of delegates. When I first...memberElad Shalom28 Aug '11 - 3:36 
Reason for my vote of 5
Great use of delegates. When I first started delegates did look scary, but with helpful tips from the CodeProject members I learned to master my fear Smile | :) Thanks for sharing, keep up the good work.
GeneralReason for my vote of 5 Good one johnmvpthatraja23 Dec '10 - 4:37 
Reason for my vote of 5
Good one john
GeneralYou "suspect"? This is precisely one of the uses for delegat...mvpJohn Simmons / outlaw programmer16 Nov '10 - 10:15 
You "suspect"? This is precisely one of the uses for delegates - to specify a method to call without actually naming the method where you're calling it from. I therefore put it to you that your vote of 3 is unwarranted.
GeneralReason for my vote of 3 Delegates have their uses but I susp...memberdmjm-h16 Nov '10 - 5:10 
Reason for my vote of 3
Delegates have their uses but I suspect this is not one of them. Granted you are aware of the mismatch of existing design and new requirement but I foresee difficulties with the next new functionality.
GeneralReason for my vote of 5 Thanks for sharing this tip.memberlinuxjr11 Nov '10 - 11:40 
Reason for my vote of 5
Thanks for sharing this tip.
GeneralStatic ConstructormvpAspDotNetDev29 Aug '11 - 13:12 
Not sure why you have an empty static constructor:
public static Globals(){}
Also, static constructors cannot have access modifiers on them. They are public by default and can't be anything except public, so the compiler doesn't allow access modifiers.
Martin Fowler wrote:
Any fool can write code that a computer can understand. Good programmers write code that humans can understand.

GeneralTyposmemberaspdotnetdev25 May '10 - 13:58 
Looks like I don't have the authority to fix the typos in your tip/trick, so I thought I'd mention them so you can fix them yourself:
  • alreay
  • guidlines

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130516.1 | Last Updated 29 Aug 2011
Article Copyright 2010 by John Simmons / outlaw programmer
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid