Our team has decided to take a step back towards scrum and away from our previous semi-Kanban approach. I think that it's a good plan at this time, although I also suspect that many of the benefits of our earlier approach will continue to show through.
Why did we do this? Here's some of my thoughts. They do not at all reflect the thoughts of anybody else on my team or in my company.
- We were unable to fully realize the benefits of Kanban. For example, we had a visual mapping of our value stream, but we never made the transition to using that visualization to improve how the team communicates within itself or to the outside.
- We lacked the process maturity to accurately forecast release dates for specific features based on lead times and SLA. I believe this was in large part due to the ongoing issues we've had with controlling batch size (both too large and inconsistently sized). I think we'll be able to better do this in the future, but the current failures did not go a long way to building trust in our approaches with stakeholders.
- We had early success with Scrum before we changed product targets. Scrum has been highly effective for our management team in planning features at a high level. I believe that ordering and allowing the dev group to choose the amount of focus on each one would be more productive overall; however, we've had issues in determining a good order, and we've struggled to structure a good focus across roles within the group.
I anticipate that our "outward facing" status and planning will be Sprint-based, while our internal approach will remain somewhat Kanban. The sprint backlog will serve as our feeding buffer, while we'll manage how much work we allow to be active amongst the team during a sprint the same way that we are now. The biggest difference is that our in-process lead time is artificially fixed at 30 days and our overall response time to external requests will average around 45 days.
In the beginning, there is no resume, only an application.
Then, there is the resume.
Later, the resume becomes an afterthought, used to round out the paperwork.
Until, eventually, there is no resume, only trust.
Thanks Dan, I don't have time for this, but you went and called me out.
Here is the trace of how this request eventually got to me:
Michael Eaton (post) -> Sarah Dutkiewicz (post) -> Jeff Blankenburg (post) -> Josh Holmes (post) –> Larry Clarkin (post) –> Dan Rigsby (Post) -> me
1. How old were you when you started programming?
I was a bit of a late bloomer. Other than playing around with Commodore BASIC and Q-Basic when I was five, I probably didn't do any "real" programming until I was in college.
2. How did you get started in programming?
I graduated college, arrived for my first day on the job for Embedded development, and was handed this big book on COM to go with the C++ I had already learned in college. I never did get to do any hardware work.
3. What was your first language?
Commodore BASIC when I was a wee one, then C++/ATL/WTL for the real world
4. What was the first real program you wrote?
I wrote a C++ program for a local company during my first summer off school. It modeled heat flow dynamics in a washing machine. I'm still not entirely sure WHY they wrote it, since it didn't seem to match the stated goals of the program, but it was the result of multiple generations of interns working away at it.
5. What languages have you used since you started programming?
BASIC, C++, C#, Java, VB, VB.NET, and unofficially, BF.
6. What was your first professional programming gig?
An intern after my first year of college. After that, I went to SEP, Inc. right out of school and stayed there for seven years.
7. If you knew then what you know now, would you have started programming?
I think I would have. I probably would have planned ahead a bit more on how I'd integrate other aspects than just coding, but definitely would write code.
8. If there is one thing you learned along the way that you would tell new developers, what would it be?
- Read. Write. Share. Talk.
- Essentially, see Dan's, because he pretty much nailed it. It all comes down to partaking of the experience of others so you don't have to make the same mistakes.
9. What’s the most fun you’ve ever had … programming?
Honestly, it's been this last push where I've been able to take a brand new technology and bend it to my will, producing a VERY sexy consumer app in the process.
10. Who are you calling out? Sorry, the line stops here, otherwise I'd have to call out my team, and they're all WAY to busy.
Lots of little things with various results. The breaking changes list got me through 99% of them, here's some of the others, and I'll probably update now and then with more.
1 - Image.Source property. Before, I could use this to find out if I've already initialized an image (in a hover-popup in this case). Now, it returns a valid BitmapImage, even if it's empty. Good, but not what I expected and it failed silently until I realized my previews weren't showing.
if ( PreviewImage.Source == null )
{
....
}
2 - ActualHeight and ActualWidth seem to be getting set later in the first layout pass than they were before. This led to some issues in setting a ScaleTransform during the first layout pass.
The concepts surrounding batch size have been floating around my head again in recent days. My current assignment is a rather large batch of work with Silverlight 2.0, but it's one that I've been able to subdivide into a number of small batches that rapidly build on each other. Thus, each one of my check ins to my private branch are able to show continual improvement in what I've made available. Unfortunately, from a throughput perspective, the value of this is exactly _zero_. Why? Because until Silverlight 2.0 Beta 2 is released, we don't have a GoLive license from Microsoft. Thus, this environmental constraint has forced me into a situation where I have a very large batch that can't be released until a specific point.
What does this mean? For starters, it means that our board has a VERY large balloon of work in the middle, and that overall we have near-zero flow. Our work in progress is artificially limited to three requirements, but the actual size of one of those is 10x the other two.
What are the implications of a large, all or nothing batch of work? Probably 90% of the features within the requirement would apply as MMF's, so they can't really be dropped out. I can't do partial releases due to policy constraints (although, we'll be bending that a bit since it's not RTW). I'm going to think about this, and I'll try to remember to post what comes out of this. For now, I've got more code to write. Mixing methodologies a bit, I should be able to trickle out a couple more inch-pebbles tonight ;)
Effective _now_, we are hiring a single experienced individual into an architect or senior developer role. If you have a desire to work with an incredible team, have great .NET coding skills, and have a desire to see your work become a real product in the marketplace, contact me ASAP. (eric dot willeke at gmail dot com)
If you already have Silverlight 2.0 or WPF skills, place yourself at the front of the line and contact me ASAP. We are looking at filling this position immediately, potentially as early as Wednesday, so don't delay expressing your interest.
http://IndyGeekBeer.org
Just a bunch of nerds and geeks gathering at the moon dog to have a couple beers and chat about what's what in the world. Probably [can't be] too much tech, but we'll see ;)
I've finally been pulled in by the twitter-mass in the Indy dev community (I blame you, Larry). I'm at erwilleke
I'm sitting at the after-party for today's CodeCamp. I wasn't going to come, but I was asked yesterday if I could speak, so I ran my Branch Management speech for four people (double last time!) that were still around the last session. The good thing is that the people really wanted to hear it if they showed up. Three guys looking to adopt TFS and one that recently had adopted it and had quesitons. So far, so good.. The talk went as well as it did before, but it isn't a "great" subject for conference talks... more of an academic session environment.
Now, I'm sitting at Champps, surrounded by a bunch of other geeks. Everybody was invited, but it turns out that everybody at the table spoke today and almost all of them have technical blogs going. Good gathering for meeting people doing the same stuff as me (or doing better stuff - yay for learning!)
Burger-time... later.
Oh, and Aaron FINALLY shows... still wearing his tag, even.
I've managed to get past the random issues that seem to plague me when adopting new technologies, and I'm digging into the meat of Silverlight 2.0 (Beta 1). This is GREAT! Blend is a great tool, and they've made using resources SO MUCH BETTER! The visual studio XAML editor works VERY well. (Intellisense bonuses: clr-namespace tags are descriptive and work well. Event handler creation was so smooth I wasn't sure it was working at first)
Layout went well for the main preview screen, and I'm looking forward to digging into wiring up behavior now. Databinding's not entirely there, yet, but I've got high hopes that it'll smooth out quickly, I only spent a few minutes on it yesterday.
or silverlight, or visual studio, or something.
Anyway, my work is in the Silverlight.net installation forum under a post titled "Silverlight startup error with resources - Summary of fix"
The corrected file is attached here, and I hate wasting a full day (and some of the evening) on things like this.
[EDIT] the full link of the post is http://silverlight.net/forums/p/14264/46863.aspx#46863. A distributed transaction letting me know what my link would be on both ends BEFORE i published either could have made this a bit easier.
Attachment(s): Microsoft.Common.targets
Thursday, after the main IndyNDA event, I performed my first public presentation. I've presented to teams, classrooms, and my company before, but this is the first time I've had the opportunity to present to an uncontrolled group of my professional peers. It turned out that I only had three people there, but I can't complain since it's very hard to get nervous in front of three people. I think it went well, and I was very happy with my slide deck, pacing, speech, and the quality of questions and answers that came out of it. I'm attempting to attach the final version of the presentation here, so feel free to take a look. If anybody out there's interested in talking more about branch management with team foundation server 2008, by all means get in touch.
Attachment(s): Rich Branch Management.ppt
I've never done this before... I'm sitting in the IndyNDA event for this month, and since there's wireless, and I've got my computer, and IndyNDA's got tables, I thought I'd actually give live posting a try. Expect a stream of thought as I (partially) listen to the presentations.
Tonight's presentation is by Paul Hacker talking about what's in Windows Server 2008 and Dan Rigsby talking about new features in VS 2008. I'm hoping they're going to be going into much more detail than they did at the Heroes Happen {here} event.
Windows Server 2008
Lots of new stuff here, but it's looking like another wave of specialists is needed. I'm interested, but getting it into production is a scary proposition since there are no "experts". Half my team knows what to go in and try to tweak if we've got issues on production [note: this can be bad], which can save the night sometimes. If all the rules have changed, tough... now what? Windows Server Core, clustering, and firewalls do look good, though. "If somebody stole your domain controller"... there are so many things I've never really had to think about.
I like the look of the new admin tool. The current one's a pain. Hypervisor - neat - I'll have to look at this one. Now I know what "System Center" is... kind of...
Aside: Listening to Paul present is somewhat intimidating. He's done this a billion times, and tonight's my first time. Soon after I typed this, he gave me an excellent plug to get people to my presentation afterwards.
SQL Server 2008
Sounds like Dan's going to expand on the launch event with some details: Top 10 SQL Server features (for developers), Visual Studio features for different types of developers. Lots of 'neat' helpers to represent difficult types of data. More time types, more hierarchies, and some spatial/geographic data types. Data Change Tracking would have saved a LOT of effort on several tables for auditing. Modes for "event audit" and mode for "history". Is this something that maintains row-level or just table-level? I'll have to ask! Time type can go out to nanoseconds, but can anything meaningful come out of servers, or only specific applications storing eternal data in that format.
I like the output of the node management and the ability to .ToString() it into a meaningful representation. More interesting is the .NET syntax in the SQL. I'm seeing quite a lot of potential as SQL and (as an example) C# come together. Does VB.NET have a future? I asked if the tracking goes to the row level, but nobody's sure yet. He mentioned a new "Sync" server which reminds me of replication services, but hopefully faster.
I need to remember to set up the Source code symbol server sometime soon, just in case I ever need to climb in (instead of reflecting the linq framework)
He's mentioning the framework versioning targets, but the templates don't work well for generators. Annoying. I forgot about that.
Visual Studio 2008
Less of interest here - I've used most of the features he's going over already, and the new stuff is about manifests, deployment, etc... stuff that's a bit beyond my ken at the moment since I"m living in a server world. He's doing a bit of WPF, but I already put my time in on that (although, I did get a chance to pull the TFSStickyBuddy project down from codeproject and take a look at it. This could be fun if I get to it over the next month at all... maybe in NC next month.. heh - maybe I should try and set up a day trip to the MS office in Raleigh to meet the dev team. Back to focus, though. Dan asked who's using 3.5 currently - maybe a double-handful out of the 100+ in the room.
Ok - Stickybuddy just got a lot less fun... VB.NET... ARGH! Seems well-factored, though... time to dig in. ... and, thus ends my attention span for the presentation...
After a delay, and a bit of heckling of Dan for using Twitter like a high school girl (and Paul, and Larry), it's time for me to get prepped for my presentation.
Back to tech, for now.
I like Linq to SQL. A LOT. However, there have been a handful of things that have annoyed me, and one of them is the story around serialization and disconnected entities. They've built a nice engine for it (DataContract-based), and really optimized it for the case where you're getting a data set from a disconnected client and storing the changes to the server. Except, annoyingly, there's no good way to tell if an entity is already attached to a specific context. And, you can't call .Attach() on something unless it's currently floating. Did I mention there's no .Detach? The only way I know of for it to be detached is to have just been Deserialized.
Well, we're storing entities across calls. In one case, it's in the session. In another, it's in memcached. Either way, there are cases were we don't know if our object that needs updating to the DB has been loaded fresh during the current call or not. Well, it's not a documented approach, but by looking at the code, I can find out that doing this will work:
// HACK: This will prevent a reattachment by identifying that the
// provided project was already available in this context.
Project originalProject = db.Projects.GetOriginalEntityState(project);
if ( originalProject == null )
{
db.Projects.Attach(project);
}
My wife and I, as instructors and directors at Dan Shi Martial Arts Club, would use it to make a huge difference in the lives of our students. We currently pick up 12 children in inner-city Indianapolis every Saturday, Monday, and Wednesday. For the past five years, we've done this using our two personal vehicles and at least one volunteer driver & vehicle each trip. The visible rewards of adding stability to these children's lives has been amazing. Unfortunately, as the program grows we have been forced to progressively cut back the frequency we pick up certain students. On weekends when one or more of the volunteer drivers are unavailable, we're forced to cancel the ride for many of the kids. The only way we've been able to continue picking up all of the children on Saturdays is through a donor allowing us to use her minivan for four hours every Saturday.
One of the major goals for our program has been to acquire a van to bring these kids to the studio.
This Monday, we discovered that we are able to purchase a business van from a local software engineering company for the very reasonable price of $5300. Insurance and the other logistical details fell quickly into place and fit within the budget. The only problem was buying the van. $5300 represents a great deal of money for an organization with no paid employees using donated space. $5300 represents three tournaments that our students would have to skip. $5300 represents far, far more than Dan Shi's current account balance having just paid for two spring tournaments. So, we reached out to our donors.
By the end of the night Monday, we had $1200 pledged. By the end of Tuesday we were up to $2200.
We expect to have until Monday, March 17th to come up with the money. We've talked to our best donors. They've responded happily and quickly in spite of having just sponsored the spring tournaments. We're still short, and it's time to reach outside our normal community.
How can you help?
If you are able to donate $1000, $500, or even $100 towards helping us to realize this opportunity, you have made a difference in a child's life. You have helped to bring a little bit more light into the lives of children living in one of the poorest areas of Indianapolis. You have helped a child learn the discipline and focus required to make a difference in their own lives. If you will support this effort, contact me as soon as possible: eric.willeke@gmail.com.
What difference will you make?
Following the meme...
I Am A: Neutral Good Human Sorcerer (5th Level)
Ability Scores:
Strength-14
Dexterity-14
Constitution-16
Intelligence-16
Wisdom-10
Charisma-13
Alignment:
Neutral Good A neutral good character does the best that a good person can do. He is devoted to helping others. He works with kings and magistrates but does not feel beholden to them. Neutral good is the best alignment you can be because it means doing what is good without bias for or against order. However, neutral good can be a dangerous alignment because because it advances mediocrity by limiting the actions of the truly capable.
Race:
Humans are the most adaptable of the common races. Short generations and a penchant for migration and conquest have made them physically diverse as well. Humans are often unorthodox in their dress, sporting unusual hairstyles, fanciful clothes, tattoos, and the like.
Class:
Sorcerers are arcane spellcasters who manipulate magic energy with imagination and talent rather than studious discipline. They have no books, no mentors, no theories just raw power that they direct at will. Sorcerers know fewer spells than wizards do and acquire them more slowly, but they can cast individual spells more often and have no need to prepare their incantations ahead of time. Also unlike wizards, sorcerers cannot specialize in a school of magic. Since sorcerers gain their powers without undergoing the years of rigorous study that wizards go through, they have more time to learn fighting skills and are proficient with simple weapons. Charisma is very important for sorcerers; the higher their value in this ability, the higher the spell level they can cast.
Find out What Kind of Dungeons and Dragons Character Would You Be?, courtesy of Easydamus (e-mail)
Yesterday I spent six hours helping a friend strip wallpaper throughout his new home. So did about ten other people. It was really great to watch a group come together around a single person's needs. It was also very rewarding to work with my hands again, as I spend far too much of my life sitting in front of the keyboard.
Afterwards, I went with my family to the park and enjoyed walking in the 68 degree weather (it had been 41 when I started working that morning). Last night a group of us went out to enjoy a nice dinner at Sullivan's. All in all a very nice, rewarding day. I need more of those... how do I structure my career and life to attain this sort of goal?
It's been years since a new technology actually got me to the point of being "excited". .NET 2.0 almost did it, but I think the day I finally 'got' .NET 1.0 was the last time I was truly excited about a new technology for its own sake. I think I feel it happening again. Between the sheer joy LINQ is inspiring into my daily work ("the data, it just is, it's just there, it's... wow!") and my newfound love of the web that's arriving through studying the concepts of the semantic web (Check out "Microformats" by John Allsopp) it's been getting better and better. Earlier this year I was able to spend a lot of time working with WPF and had a GREAT time with that. Now, I see Scott's two posts on Silverlight 2 and get more and more excited about the potential for the web.
It's a good time to be coding, that's for sure. And, I have to say, I wouldn't be using _ANY_ of this if I didn't have the focus for ongoing learning like I have had for the last few years. If I wasn't learning, I'd be sitting somewhere doing .NET 1.1 maintenance work and being excited that I'm learning a bit of .NET 2.0 from the architects.
If you're curious how the XNamespace works, just do a "Go to Definition" in VS and you'll see the declarations, the key aspects are:
public static bool operator !=(XNamespace left, XNamespace right);
public static XName operator +(XNamespace ns, string localName);
public static bool operator ==(XNamespace left, XNamespace right);
public static implicit operator XNamespace(string namespaceName);
The last one is what allows me to write code like this and have it compile... note the lack of a constructor:
XNamespace ns = "http://schemas.microsoft.com/winfx/2006/xaml";
Namespace handling is much improved! Yay for easy namespaces!
Anybody who has worked with XML in .NET 1.x or 2.0 knows how much of a pain XML namespaces can be in extracting data, yet they fill a very important part of the XML technology. Now, for linq.
Let's say you've got a document on disk and you need to pull out the namespace of the root element. I'm messing with XAML, and here's the code to open the file and extract the namespace.
XElement xamlCanvas;
using( StreamReader sr = new StreamReader( path ) )
{
xamlCanvas = XElement.Load(sr);
}
XNamespace ns = xamlCanvas.Name.Namespace;
The next thing I want to do is pull out a List<XElement> all of the child elements with an element name of "Canvas" and a "Tag" attribute of "Text". Easy!
IList< XElement > matchingElements =
xamlCanvas.Descendants( ns + "Canvas")
.Where<XElement>(xe => xe.HasAttributeWithValue( "Tag", "Text"))
.ToList<XElement>();
templateContentMap.Add(ct, matchingElements );
The key element to notice is the one in bold - I just ADDED the tag name to the name of the element! How does that work? Well, first, "Canvas" is actually being implicitly converted to an XName instance, and XNamespace + XName is a perfectly valid expression of a node's XName (can I XUse any more X's?) This implicit conversion is making life easier throughout Linq to Xml, to the point it's happening without me evening needing to be aware of it most of the time. Also, for completeness, that same thing could have been xamlCanvas.Descendants( "{http://schemas.microsoft.com/client/2007}Canvas" ) just as correctly, but I wanted to limit what was hard coded.
As an aside, HasAttributeWithValue is an extension method I wrote to clean up the lambda - it's implemented as such:
public static class XElementExtensions
{
public static bool HasAttributeWithValue(this XElement element, string name, string value)
{
if ( element.Attribute(name) == null )
return false;
return element.Attribute(name).Value == value;
}
}
A caution - you probably want to turn off the IIS logging on your TFS services if it happens to be on. Our server has all the data on the D drive, so the C drive is rather small. It causes some problems when the 5 gigs of logs for access to the version control service maxes out the available drive space. Our 20 person team was generating around 100MB of logs every day. (I could tell when people worked the weekends, too, because the build server's periodic pings only account for about 500K per day, so I could see activity levels as a graph of log size )
I rarely repost, but this single, fairly short article seems to hit many of the high points in a very condensed format. If I were in a southern church hearing this read i would expect a constant stream of "Amen" echoing around me. Read it. Think about it. Read it again. Then, compare this to what you're doing.
http://epistemologic.com/2008/02/23/a-project-delivery-sanity-test/
What's the difference between these two lines?
scriptInit.InnerHtml = string.Format(creationFormat, outerDiv.ClientID, someOtherString);
scriptInit.InnerText = string.Format(creationFormat, outerDiv.ClientID, someOtherString);
Answer: The first one doesn't do special character escaping, the second one does.
With a format string that looks like "createSilverlight('{0}', '/{1}.xaml?x=233&y=300&m=1\' );" it got a bit ugly with the &'s coming out as &, especially when it came back around to the server with the query string mangled.
http://blogs.msdn.com/jmeier/archive/2008/02/19/5-keys-to-improving-your-reading-speed.aspx
I like it - I use a lot of these techniques when I'm reading technical books for specifics... less so when I'm looking for an overall introduction to a new technology, since I don't know what all the questions are when I start. I do tend to shift half-way through to the question-based approach.
This is just a specialization of defining success criteria, and then executing a repeatable (yet flexible) procedure to fulfill those criteria. Thus, Test Driven Development Book Reading (not to be confused with what I did right before taking my MCPD exam, which was read the chapters that correlated to what I failed in the sample test, which again could be considered Test Driven Book Reading)
Freaking amazing.
Scenario: I need to load the contents of a table into a dictionary of objects keyed by one of the fields.
Before: Write the ORM code to load the entire table. (3 lines) Initialize the dictionary (1 line). Write the for each loop to move each instance from the ORM's collection type into the dictionary (3 lines).
After: Write the link query to get the day, then use an extension method + lambda to build the keyed dictionary and assign the result to the dictionary field (1 line).
Wow!
myDictionary = db.UsageTypes.ToDictionary<UsageType, int>( t => t.UsageTypeID);
The only thing I can't find is the basic extension method that would serve as essentially a foreach. All of the ones I've investigated on the IList<> extension list seem to be filtering and grouping... the .All<> seems like it SHOULD work, but it still expects a boolean return for filtering. I want something where I can do an operation with a simple side effect, like call add on another list (I know there's better ways, but I'm trying to generalize a bit). I want something like:
myListOfT.Apply<T>( t => otherThing.SomeMethod(t));
[EDIT]
The concept I'm looking for is myListOfT.Action<T>( lambda ), but I still don't see it in the library... it's just implied from some things I was reading on the Parallel Development forums on MSDN.
[EDIT2]
DUH! List.ForEach<T>(Action<T>()). Just only exists on the list, not on the interface.