A Good Day

This isn’t a technical post, and far more “chick-a-dee” than usual for my blog. So skip it if the idea of multiple shades of “off-white” freaks you out.

A good day – shopping.

I hate to shop, I mean the normal way in the store I feel rushed, annoyed, fat, broke, and ripped off. An entire store built to make me believe I want to be someone and something that would never appeal to me in the absence of dishonest lighting and piped in music. All wiped clean of fingerprints marking the karma of evil within the pipeline of the stuff piled in our department stores. Shopping like that is just not my thing.

But at the UU church garage sale – now that’s different. It’s all for a good cause and Unitarians have cool crap!

I found a designer jacket that’s beautiful, knit and totally packable. Reversible if I remove the designer label. And a pretty patterned one. And a black jacket. And a button sweater when I need that matronly look. And a soft as the world cotton turquoise jacket. And all are wash and wear (I hate the chemistry and smell of cleaners).

Then I found a sweater. The kind of knit in pattern that I generally don’t wear – but this one I swear has my puppy and her sisters. Really. I mean really. And on the front, my pup sitting next to a boot. Not the kind of boot I’d wear but clearly the “I want to go to the mountains, mommy” look on the face. I need to listen to that look way more often for my own peace of mind. Oh and today it’s a grocery bag for 5$.

Wow.

And a fabulous wool jacket in my nieces size, and two sport coats my son might be able to use at Cambridge. And a designer necklace that matches the cotton jacket. And Luka Blum and Tom Adler CDs.

Wow. Now, you’d think I would stop there. Of course you would. I would think so.

But on the way in I’d passed a set of theatre seats. You know the plywood back plush seat 1930+ style. Wow. What do I need with theatre seats? Who in a normal suburban house needs theater seats? Not even the fancy stadium seats, but just normal seats. And they can sort of use recovering. Of course all the time I’m looking at clothes, I’m trying to figure out what I can do with theatre seats because they are just drop dead, freezer burn cool.

So I keep wandering and find a 14” embroidery hoop. Of course I don’t embroider, my eyes passed that point years ago and I’ll stick with hobbies where I don’t need glasses. BUT, they make the greatest earring racks, and if I get another I can buy more earrings on my travels – round racks of earrings by the bed as dream catchers.

And I’ve been planning to redo my family photo place and the mixed grouping up cheap frames aren’t going to look so hot. I find an entire box of brand new soapstone frames for $5.

But then there’s still the theatre seats. What can I do with theatre seats?

Suddenly I see them replacing the butt ugly bench in my breakfast nook that my dad and I have been going to replace for 3 years. Oh, man this is going to be so totally freakin’ cool.

So, I check. Yes, four seats in two pairs and the back and bench to a fifth are $40 total. Except it’s half price day. So I take the ticket to go buy them for $20. And you think that this seems like plenty of good luck for one day, right? You think I’d be done with it, right?

Then I see my children’s step mom who is also a friend of mine. She says. “Yeah, and I have the van to take them home.” Right. I had forgotten the little I need to get them home thing and she’s just right there. No need to fire up the transporter beam or my gas guzzling ¾ ton.

And you’re thinking “Enough already!”

So, I follow her home and happily she misses the stupid moped that crosses just in front of her. By ourselves we are able to unload the theatre seats. No need to annoy the men we share, who are at a movie anyway, perhaps seeing Dark Knight for the third or fourth time.

I think now about going to the circle of hell I’ve set aside for myself when I buy things from China (if you don’t get that, you aren’t paying attention). So I think. Hmm. Those frames are surely from China. Nope, India so I don’t go to that particular hell this week (probably to a few others).

And you know that off white upholstery that in the sun was just a “had to go” kind of thing. It matches my cabinets in the kitchen/breakfast room. And I knew from the get-go that I’d have to raise them. I found cedar 4x4’s to do that in the garage.

I don’t know how it gets much better than this. Finding more crap is certainly not better. Finding just the right amount of crap that fits into my life as it is today, and packable for whatever stage I wander off to next – now that’s a good day.

The only adjustment I’ll make is a donation in the plate next time I’m in church. I am feeling more than a wee tad guilty that I walked with all this stuff for $36.

In the meantime, tonight, right now, riding on all this luck, I’ll go for a walk and buy a lottery ticket.

Interfacing with Insanity

More and more we are becoming mutual support groups for the insanity around us, which also happen to write business apps on the side.

I set out a few weeks ago to intertwine a tall strong intelligent business object with a confident and independent business object. Seemed the perfect pairing.

While I can’t buy POCO and other things being responsible for common behaviors of business objects, I do have a deep appreciation for provider and injection patterns. It seems fine that the business object is self servicing – meaning it has a “save yourself” method, as long as it is passing the work off to someone else who can be switched out to match development, deployment and evolutionary needs.

This was a rite of passage for the common pattern I fall back on in business objects. I’ve had insight seeing people struggle to keep their UI and business layers clean. When we mound heaps of fabulous features into base classes it’s exceedingly difficult to keep the logical intent we start with – keeping the business logic and UI isolated. I’ve just lost faith that we can avoid using features that are sitting in the Intellisense drop down. I want the compiler in control of controlling me.

That means every layer has to talk to every other layer via an interface and providers. That means the business object starts with nothing but it’s own properties and three or four self-servicing methods. It has a base class that defines any further bases, and nothing in the base classes is protected. All, private.

That’s the theory. It was way more work than I expected to implement this against CSLA business objects, but it worked. The “way more work” part was partially because I accomplished two other things along the way. Please don’t get distracted about the fact I was using CSLA as a base. If you understand where I’m going here, it makes absolutely no difference. The interesting thing to talk about later is the interfaces. I’m quite happy with that outcome.

Then I dived into what I thought would be easy – the business collections. Items for budget, line items for invoices, etc. I spent an entire day thinking, ditzing, tinkering and got nowhere. Hmmm. What’s the root cause? It’s the fact I was trained as a scientist. When there seems to be something more going on – most likely there is more going on.

CSLA – and again, it makes no differences what implementation layer you have – I just want to use a good one and not write it from scratch – does a good job setting up bindable collections. But at what cost! I scribed out all the interfaces in play (many are in play multiple times so the order is a bit random. I’m including them below, but the punch line is Rocky implements 13 custom interfaces and 12 BCL interfaces with a total of 92 members. There are a few things in Rocky’s implementation having to do with n-tier deployment that you could potentially argue, but this is just what needs to be implemented to accomplish data binding.

That’s 92 things that are either directly available to the business collection or are available via interfaces. The interfaces are the killer – everything in any interface – all 92 members are potentially public. At the moment I’m primarily interested in isolating the programmer writing business logic – but all 92 interface members are available to the UI.

This isn’t a problem if we abandon the idea of independent business objects. Wow – NO WONDER WE DON’T DO A GOOD JOB OF INDEPENDENT BUSINESS OBJECTS.

Today, I’m just screaming. And walking. And maybe later drinking. Some place in this I’ll decide a solution for this client today. I’m still hoping to do a simple list, with a “AsBindingList” method for binding and a CSLA provider for persistence. But man does that look hard at the moment.

 

CSLA Interfaces

IEditableBusinessObject

   int EditLevelAdded { get; set;}

   void DeleteChild();

   void SetParent(IParent parent)

   void Delete();

IBusinessObject

ISupportUndo

   void BeginEdit();

   void CancelEdit();

   void ApplyEdit();

IUndoableObject

   int EditLevel { get; }

   void CopyState(int parentEditLevel, bool parentBindingEdit);

   void UndoChanges(int parentEditLevel, bool parentBindingEdit);

   void AcceptChanges(int parentEditLevel, bool parentBindingEdit);

ITrackStatus

   bool IsValid { get; }

   bool IsSelfValid { get; }

   bool IsDirty { get; }

   bool IsSelfDirty { get; }

   bool IsDeleted { get; }

   bool IsNew { get; }

   bool IsSavable { get; }

IUndoableObject

   int EditLevel { get; }

   void CopyState(int parentEditLevel, bool parentBindingEdit);

   void UndoChanges(int parentEditLevel, bool parentBindingEdit);

   void AcceptChanges(int parentEditLevel, bool parentBindingEdit);

ISavable

   object Save();

   void SaveComplete(object newObject);

   event EventHandler<SavedEventArgs> Saved;

IParent

   void RemoveChild(Core.IEditableBusinessObject child);

   void ApplyEditChild(Core.IEditableBusinessObject child);

IDataPortalTarget

   void MarkAsChild();

   void MarkNew();

   void MarkOld();

   void DataPortal_OnDataPortalInvoke(DataPortalEventArgs e);

   void DataPortal_OnDataPortalInvokeComplete(DataPortalEventArgs e);

   void DataPortal_OnDataPortalException(DataPortalEventArgs e, Exception ex);

   void Child_OnDataPortalInvoke(DataPortalEventArgs e);

   void Child_OnDataPortalInvokeComplete(DataPortalEventArgs e);

   void Child_OnDataPortalException(DataPortalEventArgs e, Exception ex);

IIndexSearchable<T>

IEnumerable<T>

   SearchByExpression(Expression<Func<T, bool>> expr);

IPositionMappable<T>

   int PositionOf(T item);

IExtendedBindingList

   event EventHandler<RemovingItemEventArgs> RemovingItem;

Serialization.Mobile.IMobileObject

   void GetState(SerializationInfo info);

   void GetChildren(SerializationInfo info, MobileFormatter formatter);

   void SetState(SerializationInfo info);

   void SetChildren(SerializationInfo info, MobileFormatter formatter);

13 interfaces

43 members

————————————

BCL Interfaces

System.IClonable

   object Clone;

System.Collections.IQueryable<T>

System.Linq.IQueryable

   Type ElementType { get; }

   Expression Expression { get; }

   IQueryProvider Provider { get; }

System.Collections.Generic.IEnumerable<T>

   IEnumerator<T> GetEnumerator();

System.Collections.IEnumerable

   IEnumerator GetEnumerator();

System.ComponentModel IBindingList

   bool AllowEdit { get; }

   bool AllowNew { get; }

   bool AllowRemove { get; }

   bool IsSorted { get; }

   ListSortDirection SortDirection { get; }

   PropertyDescriptor SortProperty { get; }

   bool SupportsChangeNotification { get; }

   bool SupportsSearching { get; }

   bool SupportsSorting { get; }

   event ListChangedEventHandler ListChanged;

   void AddIndex(PropertyDescriptor property);

   object AddNew();

   void ApplySort(PropertyDescriptor property, ListSortDirection direction);

   int Find(PropertyDescriptor property, object key);

   void RemoveIndex(PropertyDescriptor property);

   void RemoveSort();

System.Collections.Generic.IList<T>

   T this[int index] { get; set; }

   int IndexOf(T item);

   void Insert(int index, T item);

   void RemoveAt(int index);

System.Collections.IList

   bool IsFixedSize { get; }

   bool IsReadOnly { get; }

   object this[int index] { get; set; }

   void Clear();

   bool Contains(object value);

   int IndexOf(object value);

   void Insert(int index, object value);

   void Remove(object value);

   void RemoveAt(int index);

System.Collections.Generic.ICollections<T>

   int Count { get; }

   bool IsReadOnly { get; }

   void Add(T item);

   void Clear();

   bool Contains(T item);

   void CopyTo(T[] array, int arrayIndex);

   bool Remove(T item);

System.Collections.ICollection

   int Count { get; }

   bool IsSynchronized { get; }

   object SyncRoot { get; }

   void CopyTo(Array array, int index);

System.ComponentModel.ICancelAddNew

   void CancelNew(int itemIndex);

   void EndNew(int itemIndex);

System.ComponentModel.IRaiseItemChangedEvents

   bool RaisesItemChangedEvents { get; }

12 interfaces

49 members

Customer Service – Saga #1

UPDATE Aug. 26, 2008: My sister received a replacement computer from Lenovo yesterday. While this was initially handled very badly by Lenovo sales and the support people initially appeared to have their hands tied, in the end Mark and Lakeysha made it right – within 6 business days of when the problem was reported. That’s not too far from what you expect, and not bad considering that it first descended into chaos. The contact point appeared to be her post in the support forums. Moral of the story – if you’re right dealing with someone, don’t quit. I’m happy enough with the outcome that I ordered a very sweet Lenovo T400 last night.

UPDATE Aug. 18, 2008: My sister posted a link to this story in the customer service forums at Lenovo. As you can see in the comments, she got in contact with Mark at Lenovo and then another person via phone. It appears this will be resolved, and I will post an update when we get to the end of the story.

It amazes me when people ignore customer service. Nothing hurts a company more than bad rep on customer service. I have two stories. How two companies you may never have heard of – Jax Outdoor Gear (Fort Collins) and Chaco Sandals (Paonia, Colorado) went above and beyond in service twice in three weeks. The second is how Lenovo of legendary customer service just screwed my sister refusing to replace a brand new laptop that arrived dead in a timely manner. They told her she’ll have to wait six days for them to even tell her what they will do and she needs to teach with this in ten days. Needless to say that Lenovo T400 I was about to buy is not looking nearly as sweet as the Sony Vaio.

Let’s do the icky stuff first – Jax and Chaco deserve their own post.

My sister tells her story with Lenovo better than I would:

August 16th, 2008

I received my first ever laptop on Wed, Aug 13th but didn’t have time to take it out of the box to get it going until this morning. That is when the fun began. When I started it up, the screen acted weird – little tracer lines coming off to the right of the words as it started up. When the regular background screen w/ icons came up, all the text was ghosted and really hard to read. In my ignorance, I thought perhaps the battery was in too low a state of charge and once it got charged up the screen would self correct (I had it hooked up to AC at the time). After dinking with resolution and appearance settings for a while to no avail, I decided there was a problem and called Lenovo Tech Support and that is where this surreal odyssey began. Note that I didn’t begin my log until about the third phone call, so the first few times are approximate.

8:00 am – Tech Support (1-877-453-6686). I spoke with a very helpful person in Tec Support who informed me that since it was a “brand new out of the box machine” I needed to call Sales. They gave me the number to call.

8:10 am – Sales (1-866-428-4465) I spent a few minutes on waiting to get to speak to a human. After explaining my problem to them, they informed me that I needed to call Tech Support…. I explained that Tech Support had just sent me to them and they explained that I needed a case #.

8:20am – Tech Support (1-877-453-6686). No waiting and a very helpful guy said yes I can get you a case # and dutifully gave me case #WN033531. I thought I was getting warm….HAH!

8:35 am – Sales (1-866-428-4465). Spent a few more minutes waiting to get a human. After I gave case # the person at the other end said he would need to put me on hold for “3 to 7 minutes”. Twenty minutes later he came back and tells me I need to call Tech Support because there are no notes on the case #. I inquired about just shipping the machine back to them for a credit and was told I would have to pay a 15% restocking charge. I am pretty sure I yelled at this point something like “I have to pay you guys $150 to take back a machine that doesn’t work!”.

9:10 am – Tech Support (1-877-453-6686). Kelly (I was starting to take names at this point). She was quite helpful and apologetic and made an offer that I thought was “we’ll send you a rebuilt one from here if you send us the broken one” – I later found out I had misunderstood her. I stated that I had spent $1000 for a “new” machine and expected to have a functioning – and new – machine. She “put in lots of notes” on my case number and said that should get me set up with Sales. I listened to her type for quite a while. She sent me off with what we thought would be sufficient info to get the problem resolved at Sales.

9:15 am – Sales (1-866-428-4465). Got right in this time. The person at the other end brought up my case number and then said that he would have to put me on hold for “2 minutes”. A few minutes later he came back and said he would figure out what I needed to do and call me back. I inquired about how long I would have to wait and he said “within an hour”.

9:45 – Sales called me back. The rep on the other end stated that he had spoken to a Michael Shefield in Tech Support and that there “was no such case number”. Needless to say, I blew up at this point. When I asked him to confirm the number of the folks he spoke to (1-877-453-6686) he said that “wasn’t the right number”. I pointed out that indeed I had spoken to Tech Support already several times this morning at that number. He seemed confused and offered to conference call with Tech Support. What he actually did was transfer me to Tech Support to a very helpful guy named Fredrick/Fred.

10:00am – Tech Support (transfer from Sales). Fred offered to send a box to return ship the damaged machine and they would fix it (this is apparently the offer that Kelly was trying to make earlier but I didn’t understand that they would just fix my machine and send me back the same one – not a used or rebuilt one). However, Fred wanted to figure out how to make it clear that I didn’t cause the damage – it came out of the box that way. So he put me on hold for a few minutes. He came back and very apologetically said that he wanted to try Sales one more time….. He did offer to conference call with me to make sure I got taken care of.

10:10 am – Tech Support (Fred) and Sales (Farros) – Fred conferenced us in to Sales. This took a few more minutes of hold music….The first question I got from Farros in Sales was “had I talked to Tech Support?”. Since I had Fred right there on the line, I was able to clear that up quickly enough. He asked to put us on hold for “1 to 2 minutes”. Fred dutifully stayed on hold with me for what turned out to be more like 10 minutes. While on hold, Fred & I even bonded a little joking about the bad classical music and how they had little stutters in the music to taunt you that someone might actually be coming back on the line. We joked about whether this was a bad Saturday Night Live skit or a Twilight Zone episode. I asked him if “Sales” was just a company in India hired to not send machines to customers and he said “I don’t know”… and then stuttered “wait – I mean I am sure they weren’t hired for that, but I don’t know who they are”.

10:25am – Tech Support (Fred) and Sales (Farros) – Farros finally came back from hold and offered to let me return it without a restocking charge and then they would forward me on to Sales and they would let me reorder a new machine. It was starting to sound promising. Farros put us on hold for a few more minutes and connected me to a woman in Sales. He explained to her what he had said he was going to do (return, reorder) and we thought we were on our way. She explained how she was going to send a return authorization label via email and I could ship it UPS. The label would allow for free shipping. At this point Fred left because it looked as though everything was in order. The woman put me on hold again for just a few minutes but came back apologizing that she had given me bad information. The new plan was that they were going to file a damage claim with UPS and that would take four business days. I was livid. I pointed out that they could get denied from UPS and that after four business days I would be right back where I started. She said “we would not do that”. I am not holding my breath.

So here I sit with a dead computer and no resolution after almost three hours on the phone. I was bounced back and forth eight times between Tech Support (apparently onshore somewhere with what seems to be helpful folks who have limited options to help me) and Sales (apparently offshore somewhere staffed with folks that talk to their supervisors for everything and give a different answer every time they come back off hold). I can tell you when I was given the option of what the resolution would be after they filed a claim with UPS I emphatically said refund vs. replace computer. Frankly I will never give another dime to a company who thinks this joke of a system can be called “support”.

Stay tuned I may have a few more chapters to write…

NOTE: Like most PC’s this came double boxed. Because of a dent in the outside box, they unwrapped it at UPS and determined that the inside Lenovo box was in perfect shape. This is NOT a shipping problem and if it was it’s a problem between Lenovo and UPS, and should not be affecting my sister.

We Don’t Publish Words, We Publish Ideas – Get Over It

This is about writing, not .NET so if that is all you care about, you can stop reading.

I just received a compliment from my editor that I’m easy to work with on review. I realize this is a process many people don’t understand. I’ve worked with some great editors (including Patrick Meader at Visual Studio Magazine), so I thought I’d take a minute to explain the process. If you hope to write this is likely to help you, and if you already write you might have to apologize to an editor. Regardless you might learn something.

Now, I’m assuming you have a good editor. Honest to goodness, I had an editor once insert into my piece “now that we’ve got the bun let’s look at the meat” and yes it was much closer to the “where’s the meat” ads on TV than we are now. As you can guess, I blew my top and didn’t work with that editor again. I wish him well in his creative endeavors; my article just wasn’t his creative endeavor.

Few editors are like that. Almost all editors are good. If you want to write, I think Stephen King’s book “On Writing” is worth a read. King says “the editor is always right.” This is really hard for writers to hear and believe, so let’s back up and look at the process I’ve experienced, and then explain what I think King’s comment means.

For a magazine, I write an article and submit it. The editor sits on it for up to six weeks because his schedule is at least as demanding as mine. He edits it, sometimes in crises mode, and sends it back to me shortly before the issue goes to layout. Now, every editor in the world is going to say “I try not to do that” but reality is reality. Once I get the editors changes for my review, I need to turn them around in a very short period of time, generally less than 72 hours, occasionally less than 24.

What I get back is a Word document with a lot of red ink – I think my editor’s review is set to blue which is slightly less depressing. Remember, I write about 15 articles a year that are edited by the same person and about 1/4 of what I see is mark up. That’s a lot of red ink. You’re job is to write a great technical article. The editor’s job is to supply proper grammar and consistent voice to a magazine. All that red ink is the editor doing their job to make you look good.

Here’s what really important: The editor is always correct that he made a change, but NOT always correct in the change he made. It is a huge mistake to just say “yeah, go with it.” The editor’s main job is to find problems – their job is NOT to solve problems in your article. The easiest way for the editor to communicate the problem is to offer an alternative. Nine times out ten, well at least eight times out of ten, their fix is good. I’m terrible about “backing into sentences” although I’ve finally gotten better about passive voice. I’m very careless with tense and everyone struggles with ambiguity in “it,” “this,” etc. This the majority of fixes – along with formatting details specific to the magazine that you’re unlikely to ever care a lot about (Listing references are in parentheses, for example).

It’s your job to read the article review and look at every change the editor made. That means you turn on Final With Markup and turn it off when you need to ensure the final flow. You should have a mechanism for asking questions like “why did you change this” for the purpose of learning, but rarely for the purpose of this article. Discussions for resolution of this particular article are almost never worthwhile. If the editor thinks your way is wrong, and you think the editor’s way is wrong, there is always a third way, a fourth way, or a fifth way. It’s your idea, rephrase it to make it more clear.

If you look at a particular spot of red ink that you hate, you’re first question should be “what was I trying to say?” This generally points directly to a better way of saying it. It should never be about whether what you wrote was correct. It’s a collaboration, not a contest. What you wrote may be correct, but it tripped up the editor and there’s a better way to say it. Occasionally, ask so you learn for the next article – for this one, just fix it. You have Track Changes on and can change what you need to. Do not accept or reject anything, just change it again. If you really believe you have to say it the initial way, find a way to prefix or postfix it for clarity, often with another sentence.

At least a few of the edits in nearly every article of mine is because I go out on a correct, but non-critical side case or tangent (anyone who has heard me speak just giggled as it is one of my lifelong sins). This “or …” is confusing because there’s no context. If it’s important, such as a landmine in the process, I expand it to a full sentence or two explanation. If it’s not important I drop it.

When you get a review, you check it make potentially a number of changes and send it back – quickly. The process is not going well if you see the article again. I hate this, but I do understand. Every time I read it I will see something else to fix. The editor and the magazine (and you) need to get the issue to press and go on. The quality of response you send back is every bit as important as the effort you put into the original article. And remember, you’re article is part of a greater whole. Things like how code is displayed, figure captioning, and page count are decisions beyond the scope of what you’re doing. Getting the article ready for initial submission is a solo effort, but within the process of placing that article into the magazine in the best possible shape – you’re a team player.

You’re role on that team cannot be replaced. I like to imagine that an editor can improve my work by x%. Let’s say they can make it 25% better. Now if it begins as pure crap, well, they will make it 25% better crap. At the same time, I’m a technical person. I never match Stephen King’s prose or Rowling’s descriptions. There’s always room for improvement. If I take an extra day to self-edit, maybe have a friend read something over, what the editor starts with is good, add 25%, and I look pretty snazzy!

With respect, this is especially an issue for writing in a language other than your native tongue, generally that means non-native English speakers writing for an English language magazine. It’s not fair, and I am a total moron who can’t even read the work I’ve had translated into other languages, so who am I to talk? But your final article will be better – remember the editor can only do x% – if you have someone else edit and you review those edits for clarity before submitting the article.

It astounds me when I hear that people forget getting an article into a magazine is a team sport. If someone either feels protective of their words or they don’t bother to spend time in the review cycle to get things right, they are not thinking through the big picture. We don’t publish words, we publish ideas – get over the protective thing. If an editor says to me “this isn’t clear,” or “did you screw this up?” they save my butt and I totally appreciate it. They’ve found technical inconsistencies, and places my grammar was so bad I wound up saying something different than what I meant, and today even someplace where I mistyped a class name!

What I think King meant in his comment is this: Editors are not always right in what they suggest. But they are always right in showing what needs a second look and what can probably be better.

Writing this post has me thinking about some significant mentors in regards to writing – Claude Len Bullard who helped me understand while I was still in high school that communication matters, Robert Scoble who encouraged me to write my first articles, Deborah Kurata for putting me on the other side of the fence (I tech edited her first book and no editor has ever been as hard on me as I was on her), Don Kiely who explained the process, helped me remember what it meant to be a novice, and was there for me in tough times, Bill McCarthy for sometimes going over the exact wording of a difficult point in the guts of a language or CLR (OK, and sometimes actually explaining that point to me), Dan Appleman who encouraged me to write my book and step into my own light, and Patrick Meader who has been an awesome partner through years of writing, my kids for reminding me the most important things I write may not be about .NET, and of course, my parents and the Academy.