Degrees of Breaking Changes: Optional Parameters in C# 4.0
Some members of the C# community were discussing optional parameters and the implications for future versions when optional parameter values change. In short, you need to realize that changing the value of optional parameters in a public API is a change that is observable at client code. The ramifications vary greatly, from “no big” to “stop the world”. I’ll give a brief explanation of how the feature works, and what you need to watch for and how to separate reasonable caution from irrational fear from using a feature.
Let’s review the feature first.
Optional Parameters lets you define default values for parameters that a caller does not specify. You can write:
public static Point Scale(this Point src, double scale = 1.0)
{
return new Point
{
X = src.X * scale,
Y = src.Y * scale
};
}
Let’s ignore the fact that there is already a fine method in the BCL that scales points. This is meant to show syntax and language features.
Callers could omit the second parameter, and the operations scales a point by the factor of 1 (the identity transform):
var pt = new Point { X = 5, Y = 10 };
var pt2 = pt.Scale();
The behavior is the same as if you had placed ‘1’ in for the missing parameter:
var pt = new Point { X = 5, Y = 10 };
var pt2 = pt.Scale(1);
That fact illustrates the important concept to understand on optional parameters:
The compiler inserts the value of the default parameter at every callsite where the caller did not explicitly set a value.
Changing in the future
That concept helps us understand and define what we mean by a breaking change to an API. Let’s suppose at some later time, you (as the library designer) decide that Scale() should move any point to the origin, instead of being the identity transform. The change to the API is a simple matter of changing the value of the default parameter:
public static Point Scale(this Point src, double scale = 0.0)
{
return new Point
{
X = src.X * scale,
Y = src.Y * scale
};
}
Let’s look at what happens to the call site when this change is made. There are two cases to consider
- The caller does not recompile (a binary in-place upgrade to the assembly containing Scale).
- The caller does recompile (either it’s in the same assembly, or the caller decides to recompile)
In the first case, it’s one kind of breaking change. If the caller does not recompile, the call to Scale() still performs the identity transform. It no longer performs “the default behavior for scale”. However, it sti
ll does exactly what it did before. That’s good, because it means that applications that were tested with the old behavior will still do exactly the same thing.
In the second case, the breaking change is a different one: Calling code that has been recompiled still performs “the default scale behavior”. However, now the default scale behavior is to move the point to the origin. This is a different kind of breaking change. Code now does ‘the default thing' but the default behavior is different. It’s still correct, because we can safely assume that since you did recompile, you wanted the to upgrade to the new behavior, and you are prepared to test those changes.
Ok, So now what?
We’ve learned that changing the default value for parameters causes problems for callers. The language rules and the implementation of the feature minimizes the pain, but it still hurts.
Changing anything public is a breaking change
This phenomena is not unique to Optional Parameters. If you change any code that has public access, you need to understand that you probably broke some client code. If you change the observable behavior, that’s a breaking change. Change the number of parameters, order of parameters, types of parameters, or return type, you probably broke code.
Rule: Optional Parameters in public methods should receive the same consideration as anything else declared with public access.
Optional parameters are no more evil than any other language feature. They just require reasonable forethought when used as part of a public interface. That makes them just like any other language feature you would use in a public method.
Created on 8/23/2010 7:17:20 PM
Filed in: .NET General, Software Engineering, DevCenterPosts, Technology,
Book Review: The Jazz Process
If you are running a software development group, you should read The Jazz Process. You may not agree with everything, but it will make you think. Adrian Cho uses a jazz combo as a metaphor for a high-functioning software development group. Throughout the book, he suggests themes from his experience as a jazz bassist to describe what high-functioning teams look like:
In Part I, “Working”, he discusses such concepts as “Use Just Enough Rules”, “Employ Top Talent”, “Put the Team First”, “Build Trust and Respect”, and “Commit with Passion”. Of course, these concepts are not new. What is unique about Adrian’s treatment is that as examples he often uses famous jazz combos. You will think long and hard about your team once Adrian compares a software development team to one of Miles Davis’ famous quintets.
In Part II, “Collaborating”, he discusses concepts such as “Essentials of Execution”, “Listen for Change”, “Lead on Demand”, “Act Transparently”, and “Make Contributions Count”. Once again, he uses analogies from the jazz world: You must have strong individual chops if you want to play in an improvisational combo. You must listen to your peers in order for your work to blend properly and contribute to the greater whole. You must lead when necessary, and follow when necessary. My favorite part of this section was “Make Contributions Count”. When you ‘solo’ in your team, does your contribution make the whole better? Or is it just about highlighting your individual skills? Adrian points to several Miles Davis pieces where his solo was quite sparse, but made for a great piece.
Part III, “Executing” talks about continuing the momentum you’ve built. How is friction useful to a group? What happens when there is too much friction? How about too little friction? He also talks about maintaining momentum, and staying healthy.
The final section “Innovating” discusses exchanging ideas and taking measured risks. “Taking Measured Risks” is the perfect ending to a book on this topic. Adrian goes through every one of his earlier recommendations and discusses the risks of overdoing it. What happens if you go too far with any of his recommendations?
I’ve mentioned the jazz analogies because those resonated the most with me. However, Adrian uses other analogies throughout the book: Military leaders feature prominently in some sections. He also uses examples from the business world and specifically the software business world.
You may be tempted to discount some of Adrian’s advice because he is involved with IBM and their Jazz suite of tools. That sells this book short. Adrian provides examples of any number of tools that can support the process, some from IBM and their jazz suite, some from Microsoft’s TFS, and some from Open Source tools.
The Jazz Process will open your eyes to a different way of thinking about teams, business, and software development. It’s a huge payback for the time invested in reading it.
Created on 8/3/2010 5:33:01 PM
Filed in: BookReviews, Software Engineering,
People, Process, or Models?
After reading "The Myth of ‘Good People" last week, I felt compelled to offer a different view of people versus process.
Are you in a Factory?
The "Software Factory" presented in last week’s article is a great model for some things: You want economies of scale, repeatable results, small (if any) deviation from process or specification. The Factory model for business minimizes the importance of people: people are interchangeable. Follow the process, and any one person can be replaced by another person.
I don’t want to work in a factory, or in a business that is governed by the factory model. Factory models are most effective in situations where you build the same type of thing multiple times, and can gain economies of scale from that repetition. It also depends on a consistent set of tools and techniques, in use over an extended period of time, with that same objective in mind.
A Different Vision
I want to spend every day producing something new, unique, and innovative. I want to take advantages of advancements in our field, which allow us to write less code but deliver software that reflects the state of the art in our industry today. The software industry moves quickly. Rich internet applications, the cloud, new languages, and interactive experiences have emerged in the last few years, and taking advantage of these opportunities (and even knowing when they don't fit!) requires adaptability in our tools, techniques, and approach. So we don't structure our teams as a factory.
The model we use for our project teams is a jazz ensemble. A great jazz ensemble produces a different composition every time they play. Every piece is different; every night is different. In a great jazz ensemble, every night produces something not only new, but valuable.
That kind of environment does depend on great people, but not just great people. At times, I’ve said that I want to model our teams on Miles Davis’s ‘great quintets’. Miles’ first great quintet (1955-1958) consisted of Miles Davis, John Coltrane, Red Garland, Paul Chambers and Philly Joe Jones. All 5 were brilliant, if unknown, individual musicians when they joined Miles. They had the qualities that made for a great jazz ensemble:
- Great individual musicianship: If you can’t trust the chops of the player next to you, you can’t create something new and great.
- Great listening skills: Composition in real time requires listening. Really listening.
- Great collaboration skills: All five musicians were more concerned with the finished work than with their own solos.
Miles’ second great quintet (1964-1968) was similar in makeup. In consisted of Miles, Wayne Shorter, Herbie Hancock, Ron Carter, and Tony Williams. Once again, they were largely unknown, but full of raw talent. They also had those same qualities of listening, and collaborating together.
Jazz is cool, but so what?
In our company, I want to capture and replicate some qualities of great jazz ensembles:
- A jazz ensembles can create great music on their first time playing together. It can do this because they have a very strong trust in every other musician in the combo. Equally important, that trust is earned.
- A new jazz ensemble can form at any time, players can move between ensembles at any time. They'll produce something different, but they'll produce something worthwhile.
- Jazz form enables a great mix of process and individuality (more on this below).
A Culture based on a Jazz Model
That last point is the most important for me: Jazz ensembles have ‘just enough rules’. There are rules to jazz form, but they are limited. No rules lead to chaos. Musicians would create ill-sounding noise if everyone picked their own key, their own tempo, their own chord progressions, and so on. However, strict rules and a focus on following them exactly leads to a different musical space. That’s more like what an orchestra creates. There’s a single maestro that directs everyone to exactly play all the notes on the page, exactly as written.
Jazz provides much less of a process, enabling each musician to influence the direction of the music. Of course, other musicians must agree with the direction of the music, or they can pull the piece in a different direction. For Jazz to work, all the musicians must agree on the direction (or come close enough that the tension produces something great).
Back to “Great People”
If you want the factory model, you have one bar for quality people. If you want a Jazz Ensemble Model, you have a different bar. We search for those people that will thrive in that jazz ensemble model. You have to have strong individual skills. You have to want to collaborate and let others share the limelight. Most importantly, you have to have the potential to create something unique, innovative, and great. And you have to want to do that everyday.
Different people thrive in different situations and it’s important to hire and nurture those talented people that are the best fit for your model.
Created on 6/30/2010 8:39:31 PM
Filed in: Software Engineering, SRT Solutions,
Nested Using Statements: A Belt and Suspenders kind of thing
A friend sent me the following question last week:
WIth the following code:
Is the second using statement really needed here as the underlying StringReader should be disposed of at the end of it’s using?using(StringReader sr = new StringReader(someXmlString))
{
using (XmlReader reader = XmlReader.Create(sr))
{
// Do Something.
}
}
The answer is that the second using is redundant, but it has minimal cost, and it is guaranteed to work. One of the rules of IDisposable is that clients can call Dispose() multiple times and the effect must be the same as if it was called exactly once. (See Item 17 in Effective C#, 2nd edition for more details). The above code snippet will dispose twice, which is fine.
If I’m faced with a choice where my error is possibly disposing of a resource twice, versus some chance that a resource doesn’t get disposed at all, I’ll always choose the former. I’d leave this code exactly as it is written above.
Created on 6/28/2010 11:43:01 AM
Filed in: C#, C# General, DevCenterPosts, Effective C#,
geekSpeak on Dynamic programming in C#
I was interviewed by Glen Gordon and Jennifer Marsman on the subject of C# dynamic programming. The show is roughly one hour long, and it’s all demo and discussion.
You can view it on Channel 9 here.
Created on 6/17/2010 6:47:13 PM
Filed in: C#, C# General,
The only way to improve process is to sell the business benefits
A recent email conversation about TDD and its costs and benefits reminded me that our industry is incredibly bad about selling concepts to our customers. The thesis of the email was that the author considered testing very important, and had invested in testing activities, but had not received the ROI he expected from adopting these activities.
The bulk of the pro-testing guidance available makes it very easy to fall into this situation. We often take sound practices and distill them into provocative slogans. These slogans are easy to remember, but can lose the justification for why we use these practices. Even worse, they can lead decision makers to wonder if we have their interests in mind. I don’t want to spend lots of space giving examples of arguments that don’t work, so instead I’m going to look at some of the critiques I’ve heard against TDD and related development ideas, and my counter-arguments.
Your application architecture gets overly complicated due to testing. This makes it more expensive to add people to the project, and very hard to transfer ownership of a project.
It is true that designing for automated tests does have a complicating effect on an application’s architecture. You will program to interfaces more often. You’ll have multiple paths to create objects and connect them to other objects. You add those paths so that it’s easier to create and use some kind of fakes, whether Mocks or Stubs. However, there are many benefits to following this architecture regardless of your testing strategy. You’re more likely to minimize coupling, and much more likely to following the Single Responsibility Principle. These benefits provide you flexibility in the future. It’s easier to replace one piece of your application with another if it’s decoupled. Change databases? Not quite as hard. Use a new UI framework? Much easier than it might have been otherwise. The ROI can be hard to measure because it’s in the future. But every manager I’ve talked to gets it when I say “How often have your developers told you that some request that seems simple requires a major rewrite?” They nod. We discuss why that happened and it’s almost always because whatever they want to replace has become integrated throughout the application. A by-product of architecting for testability is that this doesn’t happen nearly as much.
Tests aren’t maintained over time. It’s just like out of date documentation.
The only answer I have here is that this is a case of broken window syndrome. If, as an organization, failing tests are acceptable, then you’ll have plenty of them. The number will grow over time. Failing tests mean something. They may mean code is broken. They may mean that assumptions about functionality are no longer valid and some tests should be removed. In either case, failing tests indicate there is work. If failing tests are allowed to remain for any appreciable amount of time, you’ve failed. I learned this lesson very painfully at a company I worked for in the early 90’s. A key senior developer left for vacation, and a crash bug in his low level library surfaced. For the next two weeks, every check in had the test comment “It crashed on exit before I started the change, and it still crashes on exit.” Three weeks later, the bug was fixed, and we had more than 20 new crash bugs. If your organization allows backsliding, you will backslide very far.
People just run unit tests and never run the actual application.
This one bites me sometimes too. I think this is part of learning, and I don’t believe I have all the answers. And, the right answer, sometimes is “It depends.” I’ll describe three different scenarios on projects I’ve been on within the last 6 months. All used testing somewhat differently because of the differences in the projects.
In one project, I was responsible for a series of libraries that were part of tens of different departmental levels of applications. Unit tests were, and are, critically important. They are often more important than application level testing. The tests on the public API represent the contract expected from the library. If I change the library behavior, I need to be sure that I’ve preserved the behavior in all applications, not just one. The unit tests represent that guarantee. Fixing one application but breaking even one unit tests likely means breaking other applications. That alerts me to find a different solution to the original problem. I also make sure I write new unit tests to cover new or modified behavior so that my work doesn’t regress in future changes.
The second project was my first attempt at learning WPF. I like WPF (more on this in future blog posts), but I don’t know it very well yet. Oftentimes, my assumptions ran counter to what WPF expects from underlying business logic. It didn’t make sense to write unit tests that ensured my code obeyed my flawed assumptions about what would work in a WPF application. It was completely backwards. In this case, I prototyped functionality in WPF, testing the application. Once I understood how to make my other classes work with WPF, I stopped working with the application and created unit tests for my core classes. I knew how I wanted them to behave, and automated tests are re-executed much more quickly.
The third project was an Azure project. I am really excited about the vision of Azure. I have projects in development running there. However, deploying a new build takes a few minutes. I’m not surprised, there’s a fair amount of work that must be done to deploy a new application in Azure. Starting the Developer Fabric also takes time. I have a much faster cycle time if I don’t have to spin up the azure environment to validate core algorithms. A great thing about the Azure story is that in many ways, it’s just .NET: core algorithms can be easily tested outside of the azure cloud environment. I try and do as much as I can in unit tests around my core algorithms. There are some differences that only manifest themselves in the cloud, so application level testing is important, but I want to minimize those occurrences.
The theme that runs through all these scenarios is that running automated tests is easy, and you can do it often. That practice greatly decreases the likelihood of any regressions in functionality. We know that code will change over time. Running a thorough suite of automated tests means those changes can be made with more confidence. However, counter that with a thorough understanding of what functionality needs to be built so that your tests actually cover real expectations, not assumptions that have yet to be validated.
[Really paraphrasing] Our developers get and understand unit tests well, but when we integrate all the working pieces, the application fails at the integration points.
We’ve experienced this as well. I think it can be very hard to separate ‘the right tool for the job’ from ‘the job’. I tried to be very careful above to use the term ‘automated tests’ when I mean any kind of test that does not require humans running the application. I use ‘unit test’ when I mean something that tests the core logic for an algorithm. They are different, even if you use the same tool for both jobs. (Another blog post coming on this topic).
Chris Marinos started a practice where one set of unit tests is the 'guide’ for usage of a library. This was a great idea. It means one set of tests serves to show how to use a library, and validate that those critical success scenarios work. Wonder of wonders, most developers using a library would copy the tests and modify them in their production code. That really minimized integration errors.
Another practice is to write some integration tests: write some tests (in any tool) that validates some of the critical integration points between some components. The goal is automation, not writing tests.
And that, I think is where I want to close this post (which is already too long):
The goal of all this work is not to ‘write tests’. It’s not to create more work. Instead, it’s to develop work practices that enable you to move faster, with more safety. Don’t try to sell testing by explaining the work. Explain that you are using tools to automate every part of the development process that you can. It enables the expensive humans to do more thinking and less grunt work. There will still be human executed testing. There will still be integration testing (some automated, some at the application level).
In general, I’d counsel that you should automate any task you find yourself doing more than once. That saves you time. I’d expect that most organizations want to run a battery of tests more than once. There’s a large ROI in automating those tests. There’s no ROI in writing tests that don’t increase quality, or whose failures don’t tell you anything. Write tests that help you produce high quality software faster.
Created on 6/10/2010 7:39:25 PM
Filed in: .NET General, Software Engineering,
Upcoming Events: I'm on geekSpeak June 9th
I’ll be discussing dynamic features in C# with Glen Gordon and Jennifer Marsman on this episode.
geekSpeak is a talk radio format. I’ll have some demos prepared to start discussions, but my goal is to spend as much time as possible answering your questions. You’ll learn about dynamic in C#: when to use it, when to avoid it, and how dynamic and static typing interact in your programs.
You can learn more, and sign up here.
Created on 6/2/2010 4:12:30 PM
Filed in: upcoming attractions, C#, C# General,
Anonymous Function Conversion to Delegates and similar signatures.
I was asked a question recently about function signatures and why the language does not view functions as equivalent.
In particular, he wanted to know why EventHandler<SomeArgs> is not the same as Action<object, SomeArgs>.
For example, this does not compile:
public class EventSource
{
public event EventHandler<SomethingHappenedEventArgs>
OnSomethingHappened;
}
Action<object, SomethingHappenedEventArgs>
handler1 = (_, __) => Console.WriteLine("happenings");
var evSource = new EventSource();
evSource.OnSomethingHappened += handler1;
The compiler tells you that you cannot implicitly convert between the event handler and the Action<> type. You can fix by constructing the event handler of the correct type:
evSource.OnSomethingHappened += new EventHandler<SomethingHappenedEventArgs>(handler1);Or, you can create the right type of variables in the first place:
EventHandler<SomethingHappenedEventArgs> handler2 = (_, __) => Console.WriteLine("More");The compiler doesn’t try to understand if two different ways of expressing the same method signature are actually the same.
You can see this even in simpler examples. Predicate<int> and Func<int, bool> are not the same:
Predicate<int> small = (val) => val < 10;
// Does not compile: No implicit conversion
// from Predicate<int> to Func<int, bool>
Func<int, bool> anotherSmall = small;
So? Why should anyone care?
We write code to communicate to other developers what we mean. In both of the two examples above, another developer will reach conclusions based on the signature you give.
The event handler signatures should be used if and only if your method will be used when handling events. If you are using the method as a lambda expression in any other way, use the Action<> signature.
The same is true in the second example above: Use the predicate signature when you are creating a method that will be used as a test in some from of predicate logic. Use Func<> as the signatures when the method (or lambda) will be used in a different fashion.
And, of course, remember this trick so you can be the cool developer at cocktail parties.
Created on 6/1/2010 3:20:38 PM
Filed in: C#, C# General, DevCenterPosts,
Sometimes tools can be overly pedantic
I received a mail from a reader of Effective C# asking about a possible error in one of my samples. He pointed out that my example for the Dispose pattern (Item 17) triggers an FX Cop (MS Code Analysis) warning:
// Have its own disposed flag.
private bool disposed = false;
protected override void Dispose(bool isDisposing)
{
// Don't dispose more than once.
if (disposed)
return;
if (isDisposing)
{
// TODO: free managed resources here.
}
// TODO: free unmanaged resources here.
// Let the base class free its resources.
// Base class is responsible for calling
// GC.SuppressFinalize( )
base.Dispose(isDisposing);
// Set derived class disposed flag:
disposed = true;
}
The warning says this code does not ensure that base.Dispose() is always called. I suppose if you examined the entire class, and somewhere else a piece of code sets the disposed flag to true, it’s possible. But that seems to be a very unlikely occurrence.
The lesson (to me) is that the tools are there to help us, not control us.
Created on 5/24/2010 2:02:17 PM
Filed in: C#, Effective C#, C# General, DevCenterPosts,
Write Contracts to minimize throwing exceptions
I received a great question that relates to using exceptions to indicate contract failures. I thought it would be of general interest, so I am sharing the answer and discussion here:
I am reading your book More Effective C# and just finished Ch3, Item25, Use Exceptions to Report Method Contract Failures. It all makes good sense but I'm left wondering what to do in the case of a Data Access Object. Supposing I have the following class:
public class OrderDao
{
public Order GetOrder(int id)
{
// Query database
return order;
}
public bool OrderExists(int id)
{
// Query database
return orderExists;
}
}
What happens if the order is not in the database? Should the GetOrder method return null or throw an exception? We can call the OrderExists method before calling GetOrder but then that would involve up to two database queries, which could be more expensive than just calling GetOrder and handling the exception. What do you think is the best strategy for this?
He correctly realizes that he does not want to make two round trips to the database. Of course, you don’t want to use exceptions as a general flow control mechanism either.
I don’t have enough context to give a definitive answer on this sample. However, that gives me the chance to discuss why you’d make different design decisions.
It may be that this class is correct exactly as it is shown. Suppose the data model is such that any code searching for an Order does so through some other table, and that a missing id would indicate a data integrity error. If that is the scenarios for this application, the correct behavior is in the class above. A query for an order when the order ID does not exist is a data integrity error. When you encounter a data integrity error, you almost certainly want to stop stop processing more requests. Something should trigger a full check and recovery of the database.
Of course, because you asked the question, this likely isn’t your scenario. It’s easy to come up with a scenario that requires a different contract. Suppose your application is a customer service app. Customers call, and give you their order number. A customer service rep keys in the order number, and your code queries that database to find that order. There’s lots of ways that can fail without being too exceptional: a customer may give the wrong ID, a customer may hear it wrong, type it wrong, and so on. There are a lot of ways that searching for an order could fail in this scenario.
The answer is to change the contract so that one method will check the database and correctly return the record, or tell you that it doesn’t exists. Suppose that instead of GetOrder() you followed the LINQ convention and wrote GetOrderOrDefault(). Now your class (in pseudocode) looks like this:
public class OrderDao
{
public Order GetOrderOrDefault(int id)
{
Order order = null;
// Query database
// if order is found, set order = returned value.
// else order remains null
return order;
}
public bool OrderExists(int id)
{
// Query database
return orderExists;
}
}
You are still doing only one database query, and you can translate that into a single result that returns the answer, if it is found, and completes its contract even when the sought record is not found.
What’s important about this answer is that you, as a class designer, create the contracts your class adheres to. You can write those contracts in such a way that under any reasonable condition, your methods can fulfill their contracts. In this instance, the important concern is that you do not want your users paying for extra database trips. You need to create a contract that enables your users to call your methods in the way they want, and still performs the way you want internally.
Created on 5/6/2010 12:46:44 AM
Filed in: C#, C# General, Effective C#, .NET General,
Book Review: Poppendieck "Leading Lean Software Development"
Mary and Tom Poppendieck’s latest book on Lean Software is aimed not at a development audience, but rather at the people that lead development projects. It answers two questions for leaders of Development organizations: Should you adopt a lean software process? How do I succeed with a lean process in my organization?
If you are a front-line developer on a lean or agile team, this book is not for you. If you want Lean to succeed, and you don’t think it is currently, you should get this book in front of your leaders. It will help them adopt lean more successfully.
In this book, Mary and Tom Poppendieck frame the Software Development Process using 24 “Frames” divided into six chapters. Each of the six chapters give you a point of view, or a goal toward building a world class organization.
In “System Thinking”, you’ll learn why looking at your organization from view of an outside will help you see how to optimize the whole system, rather than implementing a series of micro-optimizations that actually hurt the whole. Poppendieck’s give case studies from a variety of industries that show why thinking about the whole leads to better decisions.
In “Technical Excellence”, you’ll take a short trip through the the history of Software Engineering as a field, with special emphasis on those concepts that have stood the test of time, and will help you build an organization with true technical excellence.
In “Reliable Delivery”, you’ll see techniques that improve you’re ability to deliver reliably and often. I really enjoyed the case study of building the Empire State Building. It’s hard to believe that the Empire State Building was constructed in one year. Consider that it was build in 1930, without many of the modern techniques and tools we take for granted, and it’s even more amazing. Throughout this chapter, you’ll see how to build an organization and a plan that is optimized for fast delivery.
“Relentless Improvement” teaches you that there is no finish line for great organizations: If you want to be a great organization, you must create a team structure that continues to look for opportunities to improve anything. I especially like the frame “Visualize Perfection”. It’s a great way to think about how to search for ways to improve.
“Great People” talks about a variety of techniques and ideas around motivating people. There are a number of different ideas in this chapter, so you may want to consider which specific techniques will work best in your organization. The most important key from this chapter is that managing knowledge workers require different techniques than traditional management theory discusses. Another area discusses how different cultures will imbue different goals and interpersonal styles in people. It will help you see how different regions in the world have different ways of solving problems.
“Aligned Leaders” is a great closing chapter. It will give you some very concrete suggestions on how to motivate your entire team to adopt lean thinking. The goal for you is to get your entire team functioning as leaders. You want everyone to take responsibility for the success of the entire organization. There is no better way to succeed than to get your entire organization looking for ways to improve the entire system.
Overall, I really enjoyed “Leading Lean Software Development”. There are quite a few techniques that I want to put into place in our organization. There are as many or more that I’d like to help our customers adopt as they try to be more responsive to future demands.
Created on 5/3/2010 5:39:02 PM
Filed in: BookReviews, books, Software Engineering,
C# Language Proposes Parity Changes for Handedness Discrimination
As part of the ongoing goal of toward language parity, the C# team has quietly started a program to change some of the keywords and reserved tokens to provide better typing hand parity.
You see, Visual Basic has better parity in its most common keywords:
Sub: 2 keys with the left hand, 1 with the right
Begin: 3 keys with the left hand, 2 with the right
End: 2 keys with the the left hand, 1 with the right
Dim: 1 key with the left hand, 2 with the right
C# is overwhelming right handed:
{ and } are both right hand characters.
( ) right hand.
< > right hand.
the most egregious offender of them all: ; is a right hand character.
Well, the C# team is addressing this. But of course, this was a bit of challenge, and the team rejected some initial proposals.
Alpha and Omega were considered as replacements for { and } respectively. They did achieve better handedness parity, but they were rejected by the community because of wordiness. After all C# is the language where the following is legal, and in some circles considered great form:
var label = (value == 1) ? "one" : (value == 2) ? "two" : (value == 3) ? "three" : (value == 4) ? "four" : "unknown";
Obviously, this community would not take to something as verbose as Alpha and Omega as keywords. One letter replacements were considered. “A” and “O” were rejected because “O” was too close in style to the “0”. (see, you’re not sure if that zero is just another O, are you?)
That’s when the team settled on the “A” and “Z” characters. Both are typed with the left hand, and they preserve that single-letter terseness embodied today in { and }.
Of course, all this hard work would not address the principal concerns if the ; weren’t addressed. That was the hardest of all. Most of the symbol characters are typed with the right hand. Some characters are already used in the C# language: @, !, # and ~. (Hey, it’s not like the language designers weren’t trying to avoid this handedness problem.)
Finally, after much debate, the team settled on $ as the end of statement character.
That makes the typical HelloWorld program look like this:
using System$
namespace LeftHanded
A
public static class Program
A
public static void Main()
A
Console.WriteLine(“Hello World”)$
B
B
B
Admittedly, this takes some getting used to. But, in the interest of fairness to lefties everywhere, it’s worth the sacrifice.
Now, before you write comments, look carefully at your calendar.
Created on 4/1/2010 11:52:28 AM
Windows Azure Boot Camp Experience
I spent the last couple days speaking and coaching at the Windows Azure Boot Camp in Southfield MI. I was privileged to have Jason Follas, Dennis Burton, and Jennifer Marsman as my fellow trainers and presenters. They all have a great deal of knowledge on the different areas of the Azure platform. The two days were a mix of hands on labs, and discussion around Azure and when you should consider Azure as a platform for your solutions. Throughout those discussions, several misconceptions came up again and again. Your journey into Azure will be much easier if you keep these points in mind.
Azure is a platform, not a hosting service
This is the misconception that causes the most problems for developers. We as developers currently have to concern ourselves with how we scale out to multiple CPUs, and distributed storage. We start with our code running on a computer (server, desktop, laptop, etc) then we have to think about running our code on a web farm, or a grid, or what have you.
Azure changes that model: you are writing an application that runs on the Azure platform. When you write code against the Azure platform, you’re writing code to run on multiple machines. (OK, multiple VMs, but that’s another abstraction anyway). The architecture, the design, the pricing model, and the entire environment is built around this idea that the platform is a grid of servers. Your code does not run on one server (in the classic sense of the idea). The more you think about affinity for a physical (or virtual) server, the harder it will be to understand why Azure works the way does. This affects just about everything: the communication between data storage and processes, what happens to volatile storage, why it’s volatile in the first place, how instance failure is handled, and so on.
Azure has a Service Level Agreement
You have guarantees from Microsoft of uptime for your application. Those SLAs define three nines of uptime per month. In order to provide that guarantee, the team defined the steps and processes around deploying your application to staging, and through to production.
You push bits into the cloud, and use cloud APIs to move those bits back and forth between staging and production. It also provides you with a staging environment that’s exactly like the production environment.
Azure is designed for world wide scale
Your service might run “anywhere”. (OK, there’s a bit of affinity, but this is illustrative). Your application may have hosted services and storage accounts. Those may not be on the same VM. They may not be in the same datacenter. The locations of parts or your application, and the relation with the locations of your customers has an affect on the latency of your application. If you have customers in many locations, you can use affinity to geo locate your services and data storage accounts.
The data storage platform shows this thought toward world wide scale as well: The table storage model points toward dealing with massive scale.
Azure is ala carte
There are many pieces to Azure: Web roles, worker roles, storage endpoints, SQL azure, local file storage. You don’t need to use all of them. You almost certainly won’t use all of them on any given application. That’s ok.
Embrace the Change, Embrace the Familiarity
Once you get past the big changes that are part of the Azure platform, the programming APIs have a great deal of familiarity. You’ll feel very productive very quickly. Just remember that it’s a different environment, and the architecture and design of the development and deployment models match that shift. The more you think this should be a hosting environment, the more you’ll struggle. The more you think this is a new execution environment, the easier the transition will be.
Created on 3/31/2010 6:39:36 PM
Filed in: Azure, C#, DevCenterPosts, Software Engineering, SrtInsights,
Why no Finalizer example in Effective C# 2nd Edition?
I received this feedback on the Safari site about an earlier draft of the 2nd Edition of Effective C#:
Text says: “You’ll notice that neither MyResourceHog nor DerivedResourceHog contain a finalizer. The example code I wrote does not directly contain any unmanaged resources. Therefore, a finalizer is not needed. That means the example code never calls Dispose(false). That’s the correct pattern. I take this to mean all I need is (assuming I need a finalizer):
~MyResourceHog()
{
Dispose(false);
} “Is that it? What should be done in dervied classes? Please elaborate on this just a bit more and also include the finalizer in the code, just comment it out, so we can see the full pattern for the base and dervied classes. Thanks!
I intentionally did not include an example where you included a finalizer. In the vast majority of cases, you won’t include a finalizer. If you types do not include unmanaged resources, you don’t ever need to add a finalizer. This is also explained in “Framework Design Guidelines”, pp319-322. The important reason for not including a finalizer (when you don’t need one) is that the presence of a finalizer (even if you call GC.SuppressFinalization()) affects performance. If it’s not needed, its presence is a needless performance robber.
And, if you do need a finalizer, you always need to implement IDisposable. Then, your finalizer is always as simple is shown above.
I chose not to include the expanded sample because I didn’t want to create and show a sample that would lead to a bad practice.
Created on 3/22/2010 5:54:48 PM
Filed in: Effective C#, C#, GC,
This blog is moving
And it seems that Feedburner can't figure it out.
We switched blog engines, which changes a few things around (blog post coming on that soon). My hope was that this would be transparent to all my blog readers, but as this page points out, there are some problems with Feedburner these days when it comes to moving a blog address. Try though I might, Feedburner would not believe me when I said my blog was moving.
You, dear reader, are smarter than Feedburner. The new blog address is here: http://srtsolutions.com/public/blog/243888 and the associated RSS feed is here: http://srtsolutions.com/public/rss/243888.
Please update your readers. I'll keep trying to get Feedburner to understand.
Created on 3/22/2010 5:40:00 PM
Filed in: Me,
Categories
Archives
June, 2010 (2)
May, 2010 (1)
March, 2010 (1)
January, 2010 (2)
November, 2009 (1)
October, 2009 (1)
September, 2009 (1)
July, 2009 (1)
June, 2009 (4)
May, 2009 (1)
February, 2009 (2)
January, 2009 (3)
December, 2008 (1)
November, 2008 (6)
October, 2008 (4)
September, 2008 (3)
August, 2008 (2)
July, 2008 (5)
June, 2008 (3)
April, 2008 (3)
March, 2008 (3)
February, 2008 (2)
January, 2008 (4)
December, 2007 (6)
November, 2007 (3)
October, 2007 (1)
September, 2007 (4)
August, 2007 (3)
July, 2007 (5)
June, 2007 (3)
May, 2007 (4)
April, 2007 (3)
March, 2007 (7)
February, 2007 (5)
January, 2007 (7)
December, 2006 (1)
November, 2006 (5)
October, 2006 (7)
September, 2006 (5)
August, 2006 (3)
July, 2006 (4)
June, 2006 (5)
May, 2006 (5)
April, 2006 (6)
March, 2006 (7)
February, 2006 (6)
January, 2006 (5)
December, 2005 (1)
November, 2005 (4)
October, 2005 (7)
September, 2005 (7)
August, 2005 (8)
July, 2005 (2)
June, 2005 (4)
May, 2005 (3)
April, 2005 (1)
March, 2005 (6)
February, 2005 (3)
January, 2005 (3)
December, 2004 (6)
November, 2004 (5)
October, 2004 (3)
August, 2004 (1)
June, 2004 (1)
May, 2004 (2)
April, 2004 (2)
March, 2004 (2)
January, 2004 (1)
About Me
@billwagner on twitter
- »writing developer docs this afternoon. The challenge: what is obvious, and what needs explanation.
- »some days, there are twitter conversations I will not participate in.
- »Finished the tournament with a 165.
- »I think we've all worked with companies that follow the halfarsed Agile manifesto http://bit.ly/cfgI8I
- »@dburton Great pic of the launch.