I love Silverlight. It is absolutely amazing what Microsoft has been able to pull off with 2.0. What a quantum leap from 1.0.  With 3.0 about to drop this year, it will only get better as a RIA platform. However, I would anticipate that there are some issues that will still be present in Silverlight 3.0 that simply went along for the ride in Silverlight 2.

Recently, as part of a gig with a very large and well known Fortune 50 company, I had an extremely difficult project to pull off with either:

  • ASP.NET w/AJAX
  • InfoPath
  • WinForms
  • WPF
  • Silverlight 2
  • Some combination of all the above

To make a long story short, InfoPath was not up to it, enterprise IT would make any fat client deployment hell on earth, and I just don't like ASP.NET/AJAX all that much for maintainability considerations. I chose Silverlight. It was a roll of the dice, as Silverlight had *just* been released two weeks earlier. I expected huge fits of unforeseen issues, as the RTW was branding spanking new and was not travel tested at all.

Surprisingly, the RTW of Silverlight 2.0 worked astonishingly well. All technical mountains were eventually scaled, but there were a lot of discoveries along the way. Here are the Silverlight lessons learned that I will blog about over the next few weeks:

  1. Silverlight Memory Pressure Management
  2. Synchronous to Asynchronous UI patterns
  3. Dynamic Localization
  4. Silverlight Application Controllers
  5. The Dark Side of MV-VM
  6. Dynamic Object Graph Management
  7. WCF gotchas with Silverlight

Posted by: ezekiel.brooks
Posted on: 6/30/2009 at 9:09 PM
Tags: , ,
Categories: Mentoring
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed
 
 

Recommended Patterns

Some things are inevitable in life. The same is true in software development. One of those inevitable things in writing code is a system exception. The basic goal for handling exceptions in any software is to pick from 4 basic good patterns:

  • Handle
  • Wrap
  • Replace
  • Propagate

Whenever your code encounters a system error, it should take one of the above actions. Listed below are some design patterns for how to handle a .NET exception in your application.

Handle Pattern

The Handle pattern shows up most often in network transaction handling code where retries of some sort or another are normal and expected. When using this pattern, you must be diligent in avoiding blocking for long amounts of time.

private List<Widget> GetWidgets()

{

List<Widget> widgets = new List<Widget>();

try

{

//try fetching the widgets from the main server first.

widgets = DataAccess.GetWidgets(servers.Main);

}

catch (WidgetDatabaseUnavailableException offline)

{

//Let’s ‘handle’ this specific exception. In this example, we want to

//redirect to a secondary service or device.

//Make sure that we record the first failure.

Logger.Write(offline);

 

//try again with the alternate server cluster.

//If this attempt fails, then

//we truly have an unresolvable system failure.

//The exception will be raised to the client code.

widgets = DataAccess.GetWidgets(servers.FailOver);

}

//return our list, empty or not.

return widgets;

}

 

Wrap Pattern

The Wrap pattern is most commonly used to provide a more context sensible exception. The general pattern is to embed or ‘wrap’ the root exception, which may be way too verbose or technical, inside of a context specific user exception.

This allows the original exception to be accessed along with stack and trace information if it needs to be accessed. Here is how to define a ‘wrap-able’ user defined exception:

class WidgetDatabaseUnavailableException : Exception

{

public WidgetDatabaseUnavailableException(string msg,Exception x):base(msg,x)

{

}

 

public WidgetDatabaseUnavailableException()

: base()

{

}

}

 

And here is an example of a Wrap exception handling pattern:

private List<Widget> GetWidgetsWrap()

{

List<Widget> widgets = new List<Widget>();

try

{

widgets = DataAccess.GetWidgets(servers.Main);

}

catch (SqlException rootProblem)

{

//Let’s wrap this exception inside of another, more context

//specific exception.

WidgetDatabaseUnavailableException widgetException =

new WidgetDatabaseUnavailableException(

Properties.Resources.UnableToLoadWidgets,rootProblem);

 

//now throw our more specific exception along with detail information about

//the root cause of our problem, the SqlException problem. The complete

//stack trace is available in the inner exception to the UI code or other

//callers.

throw widgetException;

}

//return our list, empty or not.

return widgets;

}

 

Replace Pattern

The Replace pattern is often used to avoid exposing sensitive information, like credit card numbers and social security. It is a common pattern to replace the exception that contains sensitive information with one that has number masks or similar methods to protect customer or entity identity information from being displayed in user interfaces.

private void ChargeVisa(Charge customerCard)

{

try

{

//we are attempting to charge a customer's credit

//card. Because of Sarbanes-Oxley, we cannot display

//the customer's credit card number. If an exception

//occurs, then we will log the true exception, but

//pass a sanitized exception back to the UI.

BillingCenter.Charge(customerCard);

}

catch (CreditCardExpiredException expired)

{

//The customer's credit card did not work.

//Log the root cause of the problem (with specifics)

//to the system database.

Logger.Write(expired);

 

//Replace the original exception and pass a replacement

// back to the User Interface or other client code.

//The application can choose to retry the transaction and

//display sanitized customer card information to the user.

throw new BillingCenterException(customerCard.CardHolder,

customerCard.MaskedCardNumber, customerCard.Expiration, customerCard.Amount);

}

}

 

Propagate or ‘Bubble’

The propagate pattern targets one or more exceptions which are unconditionally thrown to the caller. However, the Propagate pattern may also be constructed to process any remaining exceptions with alternate courses of action. In the following example, we are going to retry fetching the widgets a second time as long as the database did not report ‘offline’.

private List<Widget> GetWidgetsPropagate()

{

List<Widget> widgets = new List<Widget>();

try

{

widgets = DataAccess.GetWidgets(servers.Main);

}

catch (WidgetDatabaseUnavailableException offline)

{

//Let’s ‘handle’ this specific exception. In this example,

//the widget database is offline. If the database is

//offline, there is no point in retrying. PROPOGATE this

//exception immediately upward to the caller.

throw;

}

catch (Exception allOtherExceptions)

{

//Let’s attempt to handle all other exceptions by retrying.

widgets = DataAccess.GetWidgets(servers.FailOver);

}

 

//return our list, empty or not.

return widgets;

}

 

 

Exception Handling Anti-patterns

In most cases, exception handling is relatively well defined. However, there are some anti-patterns that will cause red flags in code reviews. The most common errors are:

1.      Suppressing Exceptions

2.      Losing stack traces

3.      Failure to log exceptions correctly

4.      Wrapping and replacing exceptions out of context

5.       

Here are some examples of each anti-pattern and a couple of good patterns

Anti-pattern: Suppress

try

{

int x;

int zero = 0;

//this will cause a DivideByZeroException

x = 50/zero;

}

catch (Exception exception)

{

//Very bad!!! I didn't do anything with the exception. The application has no

//idea that this caused a problem!

}

 

 

Anti-pattern: Suppress and Log

try

{

int x;

int zero = 0;

//this will cause a DivideByZeroException

x = 50/zero;

}

catch (Exception exception)

{

//Very bad!!!. The client code has no

//idea that this caused a problem! To make it even worse, I

//will log the exception, but the application may exhibit

//strange behaviors as the exceptions pile up during runtime

Logger.Write(exception);

}

 

 

Anti-pattern: Suppress and Return false, 0, or null

try

{

int x;

int zero = 0;

//this will cause a DivideByZeroException

x = 50/zero;

}

catch (Exception exception)

{

//don't do anything with the exception. The application has no

//idea that this caused a problem!

return false;

}

Anti-pattern: Losing Stack Trace

try

{

int x;

int zero = 0;

//this will cause a DivideByZeroException

x = 50 / zero;

}

catch(Exception exception)

{

//uh oh! We don't know what really happened. We will lose

//all stack trace information in this case.

throw new Exception("My custom exception");

}

 

 

Anti-pattern: Log and Throw

try

{

int x;

int zero = 0;

//this will cause a DivideByZeroException

x = 50 / zero;

}

catch(Exception exception)

{

//ok. We are going to log this error, but the problem is

//that the call may do the same thing – resulting in

//multiple error messages in the log of the same thing!

Logger.Write(exception);

throw ;

}

 

 

Anti-pattern: Wrap and Lose Stack

try

{

int x;

int zero = 0;

//this will cause a DivideByZeroException

x = 50 / zero;

}

catch(Exception exception)

{

//This is also quite bad. We lost the stack trace!

MyCustomException mine = new MyCustomException(“I had a bad attempt”, exception.Message);

throw mine;

}

 

 

 


Posted by: ezekiel.brooks
Posted on: 6/18/2009 at 2:54 PM
Tags:
Categories: C# | Mentoring
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed
 
 

I was talking with one of my clients tonight and we were discussing putting together a team in 2010 to build a large Silverlight application to replace a legacy system. We were going over the project cost, team size, and likely delivery milestones. Because my client is the CEO,  I saw it as an opportunity to get rare insight about how business people feel about working with software professionals. 

Of course, it is also to my advantage as a private consultant to understand the psyche of people who are the key decision makers - especially those who give go/no-go to software project funding. The context here is that I am replacing another consulting group that simply didn't deliver what this company needed. Project hit the wall, the technical staff was frustrated, the app didn't work. The business owner flushed the consulting group. So I bravely asked. "What happened with the previous vendor?".

"Well, that is a loaded question, Zeke" He said to me. "Look. We're simple people trying to run a business here. We need software. I know I can't grow my business without it. I have tried to instill respect and honesty as best I can in everything we do...". I could tell that he was very still very upset about the previous vendor. 

I waited to let him develop his thoughts. He continued. "Boy, where do I start? First of all, they acted like they were smarter than everybody else - a bunch of jackasses, in my opinion. I have a multimillion dollar business here - they don't. I turn a profit equal to their salaries every week. It grates on me that they acted like we're a bunch of idiots. We don't know how to write software, but we know how to make money. I know that this doesn't sound very nice, but my staff hated the lead guy. They never understood anything he was talking about and he got frustrated when asked to explain things to them in detail. Worse than that, he could never give a straight answer about anything and the crap they delivered didn't work - cost me a year of progress on this end in building my business".

Wow. I was stunned. Then I realized that, as software professionals in general, our technical skills have gotten infinitely better over the last 10 years. OOAD, OOD, Business Domains, IoC, DI, MVVM, Cloud Computing. The list goes on and on. However, I am of the opinion that many of us may have gone completely backwards in interpersonal and communications skills.

I can't count the number of times that I've interviewed folks over the years and get asked by the decision makers "How are their communications skills". I mean, I've seen some seriously skilled folks come through and they weren't hired because, quite frankly, they suck at expressing themselves, or seem to be somewhat arrogant or insensitive. 

On the bright side, we can always get better. But we have to work at it. Our discipline is bigger than the latest coding tricks or paradigms. Check out some of these articles. It never hurts to get better Wink

http://blogs.techrepublic.com.com/programming-and-development/?p=36

http://searchwindevelopment.techtarget.com/tip/0,289483,sid8_gci347660,00.html

http://stackoverflow.com/questions/96879/advice-to-improve-programmer-communication-skills

 


Posted by: ezekiel.brooks
Posted on: 6/18/2009 at 1:50 PM
Tags:
Categories: Mentoring
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed
 
 

Well, it's been a few days since I blogged. I've been bogged down with finishing up a Silverlight project for a soon to be former employer. Back into private practice. Woohoo!

Something that's been on mind lately has been the issue of self esteem among software professionals. I have a really close buddy of mine, who is relatively new in the world of high powered programming enclaves. He was so intimidated by his co-workers 'great knowledge' that he was effectively unable to do his job well without fear, trepidation, and generally low self esteem.

After an extended session of talking about the spiritual and philosophical issues at the root of his current dilemma, he concluded that maybe 'he wasn't cut out for this [software development]'. "But, you're a fine programmer" I countered. After much pep talk, he felt better, but his lack of joy at the time actually convinced me to address this issue in Meta { ! } Think.

For the record, everyone can do something well. Software organizations, like any other, require a wide swatch of skills and abilities to be truly healthy. As an example, take Microsoft. They have their prime time players who are the face of the organization. Great visionaries who steer the technical direction of the company. Great computer scientists who write and blog about all kinds of arcane subjects and are the center of attention at every software conference. 'Gee', you think. 'I wish that was me'.

Infamous Microsoft Example

Well, remember that these folks have the job of strategic thinking. They are truly looking at the whole, or a big chunk, and not the specifics. These are the folks who think strategically and drive Microsoft's long term goals. Think Bill Gates. Think Microsoft Research. Think about any Microsoft superstar.

Now, can Mr. Gates do functional testing for Server 2008 subsystems? Maybe, but I wouldn't want him on my Server Test team. I'll take the person who has successfully and consistently found hidden defects that even unit testing failed to find. A loss of sales due to product defects that my team finds, even with Mr. Gates on the team, is a failure. So, who's more valuable?

Ah, you say. Bad comparison, Zeke. Bill Gates - hands down. At least we could start another company with him and get rich. Lol. Maybe. But in the focus of this hypothetical, let's think about this. Do this search on Google: http://www.google.com/search?hl=en&q=bill+gates+windows+crash&aq=1&oq=Bill+Gates+windows&aqi=g10 Now, I ask you. Who is more valuable to the organization?

Look at all of the damage caused to Microsoft by this now infamous event. Notice Apple gleefully pounding Microsoft on this issue. Heck, a new series of Mac vs. PC commercials was born out of this type of incident. This was not the first time Windows has embarrassed Microsoft because of something that escaped failed functional testing efforts.  Now I ask you - who's more valuable?

Advice

Well, it depends on the situation. And that is my point. Figure out what you do best and put yourself into the right situation that needs you! If you are best with competencies that require skills a foot wide and 20 miles deep, like targeted development niches or functional testing, then focus on that. That is your fit in the IT Ecosystem. Be proud of it and feel good. Heck, you could have even saved Microsoft a lot of pain.

Consider this advice I found in "The Message", by Eugene Peterson:

Galatians 5:26 (The Message)

 

 25-26Since this is the kind of life we have chosen, the life of the Spirit, let us make sure that we do not just hold it as an idea in our heads or a sentiment in our hearts, but work out its implications in every detail of our lives. That means we will not compare ourselves with each other as if one of us were better and another worse. We have far more interesting things to do with our lives. Each of us is an original.

Amen to that. ;-)

 


Posted by: ezekiel.brooks
Posted on: 6/15/2009 at 4:59 PM
Tags:
Categories: Mentoring
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed