http://www.lostechies.com/blogs/
Last checked about 14 hours ago.
1 person has subscribed to this feed.
post frequency (last month)
PostRank™
From http://lostechies.com/blogs/, 2 days ago,
0 comments
A coworker just asked me this question - what's the point of delegates in .NET? My answer was very short and one that he had not found online: to delay execution of a method.
Consider this: if you pass a Method2 as a parameter to Method1, Method2 is evaluated immediately and the result is passed into Method1.
public class SomeObject
{public void Method1(int someValue)
{ //... code here}
}
...
someObject.Method1(anotherObject.Method2());
Additionally, Method2 must have a return value (not void) so that the value returned from Method2 can be passed as the parameter of Method1.
With a delegate, though, we get method pointers that can be used to delay the execution of the method in question until it's needed (if at all). We can also get rid of the requirement for a return value and we can pass values that were created by the host method, into the delegate method.
public class SomeObject
{public void Method1(Action<int> someAction)
{ //.. do some stuff here int aValue = GetTheValueFromSomeWhere();someAction(aValue);
//... do some more here}
}
public class AnotherObject
{public void Method2(int aValue)
{ //do something that is dependent on aValue, here.int i = aValue + 1; // or anything else that needs aValue.
}
}
FYI - Action (void return; with many parameterized variations) is a delegate that is build into .NET 3.5, along with Func<T> (return value of type T; with many parameterized variations). These are the two most common delegates that I use in my code.
Most .NET developers have used delegates without realizing it, too. The event system in .NET is nothing more than a multi-cast delegate - a delegate that points to more than one method - with a special signature and syntax (depending on the language being used).
There's a lot of good use for delegates. And like any other tools, there's a lot of bad uses. Take the time to learn what they are, how they work, and where they can be beneficial.
From http://lostechies.com/blogs/, 2 days ago,
0 comments
FYI - I'll be giving my S.O.L.I.D. Software Principles presentation at the Austin .NET User Group on Monday the 13th. This is the same presentation that I gave at Pablo's Day(s) of TDD last weekend, except I'll have the missing code in place and the slide errors fixed. :)
Here's the abstract that was posted via the ADNUG mailing list:
S.O.L.I.D. Software Development: Achieving Object Oriented Principles, One Step At A Time
Almost every professional software developer understands the academic definitions of Coupling, Cohesion, and Encapsulation. However, many of us do not understand how to actually achieve Low Coupling, High Cohesion, and strong Encapsulation, as prescribed. Fortunately, there are a set of stepping stones that we can use to reach these end goals, giving us a clear cut path to software that is easier to read, easier to understand, and easier to change. This presentation will define not only the three object oriented goals, but also the five S.O.L.I.D. principle that lead us there, while walking through a sample application.
At some point this week or next, I will have my slides and code posted for people to download. (I know I promised this at PDoTDD. I got busy. Sorry). And as usual, there will likely be a group of people heading to Rudy's after the meeting, for extended discussions and snappy banter.
From http://lostechies.com/blogs/, 3 days ago,
0 comments
I'm happy to say that we've just tied a bow around the latest release of MassTransit. Release 0.4 includes a number of new features and some tweaks to the internals as well. I'm going to describe a few of those features below, but you can grab the latest from the trunk or download the 0.4 release.
Building MassTransit
Since Visual Studio 2008 has been out for almost a year, it is now required to open the updated solution for MassTransit. In the main folder, the MassTransit-2008.sln is the one to use to build and run the unit tests. Many of the samples solutions are also 2008 solutions. The assemblies, however, are still targeting the .NET 2.0 framework, making them usable on both 2005 and 2008 projects. With only the .NET 3.5 framework installed, you should be able to run the build.bat to build the project without Visual Studio (our CI server does this).
Timeout Service
To enable automated support for timeouts in sagas, a new timeout service is available. This is a general service that can be used to schedule timeouts for whatever purpose may be needed. To schedule a timeout, the application should publish a ScheduleTimeout message with the duration or time when a response should be sent. The application/service can then consume the TimeoutExpired message, which will be published by the timeout service when the timeout period expires.
Message Deferral Service
One of the scenarios I often find in our systems is the need to poll a remote resource to determine if an operation has completed. To support this behavior without custom code in each instance, a new message deferral service has been added. This can be used to defer the delivery of a message until a period of time expires. The deferral services leverages the timeout service for scheduling and we republish a message after that timeout expires.
For example, we have a CheckRemoteResponseStatus message in one of our systems. This is initially published after a request is submitted to a remote system and a remote transaction id is returned. The first time the consumer gets the message, it checks the remote system for a response. In most cases, the response is immediately available and the saga continues. However, sometimes the remote system is too busy to respond and returns a pending status. In this case, the same CheckRemoteResponseStatus message is published within a DeferMessage. The deferred message service handles that message and will republish the original CheckRemoteResponseStatus message when the timeout expires. The saga will then handle the message to see if a response is now available. The saga keeps track of how many times the remote status has been checked and uses a sliding interval that increases as the retry count increases. Eventually, the final retry results in a failed transaction and is handle appropriately.
The nice thing about this is there was no custom retry logic required, and a common timeout and message deferral service were used. There are likely other cases within the application that will benefit from this shared functionality.
Transactional Queue Support
With 0.4, the entire method of reading from the endpoints has been redesigned. Previously, a single receive thread was used to receive from the endpoint which then dispatched the message handling to the dispatcher inside the service bus. This has been redesigned to use the dispatcher threads to perform the actual receive from the endpoint, using a transaction (ala System.Transactions) to handle the message reception. This keeps the transaction to a single thread while at the same time allowing concurrent message reception.
The transaction carries over into actions that are part of the message consumer. If a database update is part of the consumer, that database update can cause the entire message to rollback if it fails. If any exception is thrown, the entire reception of the message, any additional database operations, new messages sent, etc. will all be rolled back with the transaction.
Performance Improvements
Dru spent some time in NYC with Ayende Rahien reviewing the MT source code and Oren recommended changing from using locks to ReaderWriterLocks to improve concurrency. The changes in the threading system, along with the elimination of a lot of locking in favor of reader/writer locks has nearly doubled the throughput of messages when using a multi-core system using MSMQ. There have been a number of other internal tweaks as well to improve the concurrency of the bus dispatcher.
Control Bus
To enable competing consumer in a publish/subscribe environment, the control messages need to be on a separate bus from the data messages. To allow multiple services to compete against a single data channel (single MSMQ) in order to load balance and handle failure scenarios, the services cannot compete on the control messages such as subscriptions. The subscription client has been tweaked to allow it to operate on a separate bus from the data bus, at the same time notifying the subscription service of messages handled by the local endpoints of the service.
It's easy to setup a single service that consumes messages from multiple buses (which in turn each have a specific endpoint being serviced). When a component is created to consume a message, the specific bus/endpoint that received the message is injected into the component (via setter injection) so that any subsequent messages can be published to the appropriate bus.
Health Service
The health service has been added making it easy to monitor endpoints and identify when an endpoint goes down. Periodic heartbeats are sent to the service and when a heartbeat hasn't been received in a while, it marks that endpoint as down and attempts to directly ping it to get a response. The heartbeats can be subscribed, so a monitoring tool can keep track of which endpoints are there and what they are handling.
Configuration Model
To make it easier to use the bus in different containers, a new configuration model has been added to build and configure a service bus instance. This will ultimately result in moving a lot of the code used by build a service bus out of the container-specific facilities (such as the Windsor container).
Host Improvements
The ability to create and deploy Windows services has gotten easier with the updates to the Host assembly in MassTransit. With only a few files to define the lifecycle of a service, it is easy to get the ability to run, test, install and deploy a service. This includes services that are using the service bus. There is little to no coupling between the host and service bus, making it usable for a variety of purposes.
Learning MassTransit
A lot of requests have come for information on how to learn to use MassTransit. During Tulsa TechFest this week, we're going to record our presentation and make it available online within a few days. This should give at least some introduction on how to use MassTransit (the presentation is mainly on distributed architecture, but we're using MT for the demo bits). We're also talking about doing a couple of podcasts on how to use it as well. Depending upon how that goes, we'll try to do a couple of screencasts on "creating your first project with MT."
The best way to discover how to use the code is to review the samples. The WinFormSample gives an overall example of how a variety of features are used. The HeavyLoad shows how many of the pieces work as well. The samples folder has a few others that demonstrate how to use MT in other scenarios.
So, check out the new release and give us some feedback on how the new features are working. We've already got a few backlog items that we're slating for 0.5 based on some other contexts that have come up in our applications. Feel free to post on the message group or send either Dru or I an e-mail or tweet if you have any questions.
From http://lostechies.com/blogs/, 3 days ago,
0 comments
Why does visual studio make doing the right thing, so hard to do?
The background
This last weekend during the Pablo's Day of Test Driven Development workshop held in Austin, Tx I decided to solve a problem in visual studio that has bothered me for the last two years. In the process of following TDD using resharper I would normally create a test class. Than write a line that instantiates a class that has not been created yet. This would leave me with code that looks like this.
All of the classes and interfaces in red do not exist. Resharper is nice enough to highlight the non-existent definitions in red. The next step is to get this code to compile, which requires the classes to be created. Using the resharper quick fix menu, it is easy enough to generate the code for each of these types. This is where the problem starts. The resharper stubbed code is dropped into the end of the current file. Since I separate my UnitTest code from my production code using separate Visual Studio projects, I am now forced to move the type definitions into a separate project. The problem I have with moving the inline code into a new file in a different project is that this process takes a handful of steps, which although are very trivial, to complete. The process of cutting and pasting code into a new file gets in the way of what I want to do which is:
Design functionality by writing test code, Implement functionality by making my tests pass, & Make the implementation code easier to read by refactoring.
The last thing that I want to worry about is organizing my files and namespaces. I want visual studio to just do the right thing. To use the Microsoft mantra make me fall into the pit of success, rather than the dark hole of cluttered files and project folders. I understand that I am asking for a lot from visual studio…. I mean its name starts with Visual which means lots of mouse clicks and Drag & Drop development. The important point to remeber is that when practicing TDD it is much more important to be able to concentrate on good design rather than having some code auto generated with a few mouse movements.
My Solution
I decided to take advantage of the tools I have at my disposal to solve this problem. I first looked into somehow making a smart tag that would show up in visual studio. Although there is a SmartTag interface and a class in the visual studio sdk. The documentation on creating a smart tag is non-existent. I suppose I could email some people at Microsoft, but why? That would probably take forever to hear back from them and even get to someone who could actually point me in the right direction.
The next choice was to utilize resharper, it has a plugin model. Some partially usable samples and a little documentation. The documentation provided by Jetbrains although terribly lacking.. is much better than the non-existent samples for visual studio. The springboard that made this really work for me was being able to look through an existing open source resharper plugin. By looking through an existing (non trivial) plugin I was able to piece together what I want to do.
What does it do?
The plugin adds some additional menu items to the Context Action menu for classes that are located in a file with additional classes. The menus add an option to copy the class into a new file with a name of the type and than move it into a project that is referenced by the unit test project. While this solution realistically can only save 30-60 seconds of actual work, what it really does is eliminate the mental stress of doing the right thing and moving the class under test into the correct place in the solution so that you can keep focus on the test and design of the class under test.
Where can I get it?
The Resharper TDD Productivity plugin for resharper is located here: http://code.google.com/p/resharper-tdd-productivity-plugin/wiki/Features It is an open source project and I welcome comments on how to make this plugin better. To download the latest version (works with resharper 4.1) download and run the installer from here: http://resharper-tdd-productivity-plugin.googlecode.com/svn/trunk/LatestVersion/TddProductivity.Setup.msi
What are the little inefficiencies that bother you? Shoot me an email, send me a patch, or just comment on this post.
From http://lostechies.com/blogs/, 3 days ago,
0 comments
As predicted, I did forget a few “Thanks” from my previous post on this subject. I’d like to thank my own employer, Dovetail Software and, personally, the CEO, Stephen Lynn who generously granted me time to attend and help organize the event.
I’d also like to thank the employers of each attendee of the Friday afternoon session who granted them time to attend and supported them in their furthering their knowledge and community involvement.
Now, on to the point of this post…
Many of you asked for recordings of the sessions. Let me assure you, we tried, and it just didn’t turn out that well. The audio was OK, but you couldn’t see the screen. Also, we had some technical difficulties and so we didn’t get all the sessions. All in all the recordings were a failure and not worth trying to recover. We’re regrouping and updating the labs to fix various mistakes and inconsistencies. Once we get to a stabilization point, we’re planning on getting some screen casts together for those who weren’t able to attend (actually, for those who were also, everyone).
As I mentioned, the labs had some issues. We’re working on updating those and getting a milestone established so we can issue a ‘release’ in a ZIP file format. Please be patient. In the meantime, you can grab the current source directly from our Google Code project SVN.
Of course, you could go even further and help us update and perfect the labs. We could always use more help! :)
We’re currently kicking around ideas of how to keep in touch with the attendees and keep the learning happening. We’re also thinking about having smaller events, more frequent and during more convenient hours (lunchtime events? breakfasts? We’re open to suggestions here). If you’re interested in something like this, let us know.
We’re also trying to figure out how to cover the spread and disparity of experience and understanding we saw at the event. Several people were at the very beginning. Several people were more advanced. Everyone else was somewhere in between. It was hard to serve everyone in the best way they need to be served. One thought was to have the various events focused on “absolute beginner”, “I’ve done some unit testing before”, “I’ve tried TDD before, but struggled”, and “I’m doing TDD now, but it’s hard and I’m looking for more tricks and tips”, etc.
Do you have any suggestions? Constructive criticism? Do you have talents or skills that might be particularly useful to make this process go better?
Do you think we should set up a mailing list or something to further the discussion?
From http://lostechies.com/blogs/, 3 days ago,
0 comments
A few months ago, I posted some thoughts and questions on the proper use of Inversion of Control (IoC) containers and the Dependency Inversion (DI) principle. Since then, I've had the opportunity to do some additional study and teaching of DI, and I've had that light bulb moment for the proper use of an IoC container. I haven't talked about it or tried to present the info to my team(s) yet, because I had not verified my thoughts were on the right track - until recently. I got to spend a few hours at the Dovetail office with Chad, Jeremy, Josh, etc, and had the pleasure of being able to pick their brains on some of the questions and thoughts that I've had around DI and IoC. In the end, Chad confirmed some of my current thoughts and helped me put into a metaphor that I find to be very useful in understanding what Dependency Inversion really is - a cloud objects that can be strung together into the necessary hierarchy, at runtime.
Consider a set of classes that need to be instantiated into the correct hierarchy so that we can get the functionality needed. It's really easy to have the highest level class - the one that we really want to call method on - instantiate the class for next level down, and have that class instantiate it's next level down, and so-on, like this:
This creates the necessary hierarchy, but breaks the core object oriented principle of loose coupling. We would not be able to use ThisClass without bringing ThatClass along with it, and we would not be able to use ThatClass without bringing AnotherClass along with it.
By introducing a better abstraction for each class and putting Dependency Inversion into play, we can break the spaghetti mess apart and introduce the ability to use any of these individual classes without requiring the specific implementation of the dependent class.
For starters, let's introduce an interface for ThisClass to depend on and an interface for ThatClass to depend on.
Now that we have an interface that both of these classes can depend on, instead of the explicit implementation of the child object, we need to have the expected child object implement the interface in question. For example, we expect ThatClass to be used by ThisClass, so we will want ThatClass to implement the IDoSomething interface. By the same notion, we want AnotherClass to implement the IWhatever interface. This will allow us to provide AnotherClass as the dependency implementation for ThatClass. Our object model now looks like this:
What we have now is not just a set of classes that all depend on each other, but a "cloud" of objects with dependencies and interface implementations that will let us build the hierarchy we need, when we need it.
The real beauty of this is that we no longer have to care about the implementation specifics of IDoSomething from ThisClass. ThisClass can focus entirely on doing it's duty and calling into IDoSomething when it needs to. And, by passing in the dependency as an abstraction, we're able to replace the dependency implementation at any time - runtime, unit test time, etc. This also makes our system much easier to learn and understand, and most importantly - easier to change.
Now that we have our cloud of implementations and abstractions in place, we will need to reconstruct the hierarchy that we want so we can call into ThisClass and have it perform it's operations. Here's where Dependency Inversion meets up with Inversion of Control.
We end up with a hierarchy of objects that is instantiated in reverse order, like this:
We have now successfully inverted our system's construction - each implementation detail is created and passed into the the object that depends on it, re-creating our hierarchy from the bottom up. In the end, we have an instance of ThisClass that we can call into, with the same basic hierarchy of classes that we started with. The real difference is that now we can change this hierarchy at any time without worrying about breaking the functionality of the system.
Once we have our Dependency Inversion and Inversion of Control in place, we can start utilizing the existing IoC frameworks to automatically create our hierarchy of objects based on the advertised dependencies (an advertised dependency is a dependency that is specified as a constructor parameter of a class). Tools like StructureMap, Spring.net, Windsor, Ninject, and others, all provide automagic ways of creating each dependency of the object that is requested, all the way up/down the hierarchy. Utilizing one of these IoC containers can greatly simplify our code base and eliminate the many object instantiations that would start to liter our code. As I said in my previous post, I know all about what not to do with IoC containers. Good IoC usage, though, is another subject for another post.
From http://lostechies.com/blogs/, 4 days ago,
0 comments
Hola and (Insert standard "hello world" content, here).
Some of you may know me from my previous blogging effort over at AvocadoSoftware.com, or my more recent efforts at DerickBailey.com. I'll be continuing to post over at DerickBailey.com, where you can find my personal RSS feed, but will also be contributing my thoughts and ramblings to the Los Techies community now (once I figure out how to do cross-posting, anyway).
A huge thanks to Joe, Chad, and everyone else over here at Los Techies for thinking that I have something valuable to say and add to the community!
And per the "Los Techies N00B Ritual and Tattoo" requirement. Here's my "they're both full of crap" tattoo. :)
From http://lostechies.com/blogs/, 4 days ago,
0 comments
We would like to welcome Derick Bailey to the LosTechies blogging community!
Some of us had the opportunity to meet Derick at Pablo's Day of TDD and were impressed with his passion and commitment to modern day software development. He is able to take low level constructs and communicate at a high enough level to where ideas that appeared to be esoteric suddenly make sense.
We are pleased to have him on board and know his passion will help other developers to find answers to questions or figure out new technologies as all the LosTechies bloggers strive to do.
Welcome Derick!
From http://lostechies.com/blogs/, 5 days ago,
0 comments
In previous versions of Rhino Mocks, the Record/Replay model was the only way to create and verify mocks. You would have an area that set up expectations in a record mode, then the replay mode would verify your expectations. What was really strange about the Record/Replay model was that it didn’t vibe with the “Setup, Exercise, Verify” unit test pattern. It looked like you had verifications in the middle of your setup, and your verification was just one line of code, “VerifyAll”. In addition, you had to decide what kind of test double you wanted when you created it. Last time I checked, there were at least four choices, and I’ll never get any of them straight on what exactly they did differently.
With the new release of Rhino Mocks 3.5, which RTM’d today, the new Arrange, Act, Assert syntax makes it dirt simple to create test doubles for our unit tests. In fact, I only really abide by three rules for 99.99% of the mocking cases I run into. All I need to do is abide by three rules:
That’s it. I rarely, almost never, assert a method was called on a method that returns a value. The assumption is that indirect inputs should be used to alter the control flow in the application, or to be observed later in indirect or direct outputs. When I started using Rhino Mocks, I set expectations on every single method call. This led to brittle tests, where the body of the test matched almost exactly the implementation. It was ridiculous.
Here’s an example of snippet of code we want to test (yes it was test-driven the first time I wrote it):
public class OrderProcessor { private readonly ISmtpClient _client; private readonly IOrderSpec _spec; public OrderProcessor(ISmtpClient client, IOrderSpec spec) { _client = client; _spec = spec; } public void PlaceOrder(Order order) { if (_spec.IsMatch(order)) { string body = "Huge frickin' order alert!!!\r\nOrder #:" + order.OrderNumber; MailMessage message = new MailMessage("sender@email.com", "salesdude@email.com", "Order processed", body); _client.Send(message); } order.Status = OrderStatus.Submitted; } }
Let’s create a test that ensures that when the order specification is a match, we send a message to the SmtpClient:
[Test] public void Should_send_an_email_when_the_order_spec_matches() { // Arrange var client = MockRepository.GenerateMock<ISmtpClient>(); var spec = MockRepository.GenerateMock<IOrderSpec>(); var order = new Order {Status = OrderStatus.New, Total = 500m}; spec.Stub(x => x.IsMatch(order)).Return(true); var orderProcessor = new OrderProcessor(client, spec); // Act orderProcessor.PlaceOrder(order); // Assert client.AssertWasCalled(x => x.Send(null), opt => opt.IgnoreArguments()); order.Status.ShouldEqual(OrderStatus.Submitted); }
I set up the IOrderSpec to return true for IsMatch. After exercising the OrderProcessor, I ensure that the Send method was called, ignoring any arguments set. I could have asserted individual parameters, but that’s beyond the scope of this discussion. What I don’t assert is that the IsMatch method was called. I don’t care. If the IsMatch method isn’t called, the Send method won’t be called. I’ll have more tests to cover the other situations, which will cover all my behavioral specifications I want on the OrderProcessor.
I should also note that I could care less what the GenerateMock method was named. It could be called GenerateFloogle for all I care, all I’m interested in is how I use the Floogle. Or Test Double, it doesn’t matter. I just want a test double, I’ll decide how to use it. The nice thing about the Rhino Mocks AAA syntax is that I can explicitly setup and verify whatever I want, and the test will fail if I don’t. I don’t stub properties any more, as I don’t really have any interfaces with properties at this point. Interfaces are for the most part stateless services, so I don’t need any fancy auto-property behavior for stubs.
Sticking with these three rules for the 99% cases ensures I have good dependency interfaces that conform well to the command/query separation, that method should either perform an operation and return void, or query an object and not change anything. With the new AAA syntax and these rules, I’ve found my tests to be far less brittle, and much more expressive in describing the behavior I’m specifying.
From http://lostechies.com/blogs/, 5 days ago,
0 comments
On Saturday, we concluded our Pablo’s Days of TDD event here in sunny Austin, TX. Over all, I think it went really well. All the feedback I personally heard was positive and we asked people to fill out evaluation forms and, from what I saw, they all had good things to say and lots of good suggestions for making the next one (if we can ever manage it) even better.
Thank you everyone who attended. You made it worth doing and I hope you got a lot out of it and are able to take something back to your regular day-to-day routine and make it a little better somehow.
Just a reminder for everyone, all the materials are online at our Google Code project. You currently need Subversion to grab it. We’ll work this week on getting a ZIP’d up version of the repository so you can just download it without needing to install an SVN client.
In Part 2 of this post, I’ll recount what went down and talk about going forward. For right now, I want to get sentimental and drop a few thanks on some people:
I’d like to call out the sponsors and individuals who stepped up to make this thing happen.
I know I’m going to miss a few people here, so let me just first say “I’m sorry, I’m a heel” preemptively. Thank you to:
From http://lostechies.com/blogs/, 6 days ago,
0 comments
At Pablo's Day of TDD, we were discussing the Single-Responsibility Principle (SRP) while working through one of the labs and a question came up about a piece of code. The code in question looked something like the following (warning: this is over simplified code to show a point):
public bool Login(string username, string password) { var user = userRepo.GetUserByUsername(username); if(user == null) return false; if (loginValidator.IsValid(user, password)) return true; user.FailedLoginAttempts++; if (user.FailedLoginAttempts >= 3) user.LockedOut = true; return false; }
This was from the a LoginService class and this was its only method. The question was whether or not this violates SRP because it's in charge of incrementing FailLoginAttempts as well as locking the user out after 3 failed attempts. I believe we answered the question with a "depends", but it bothered me that we didn't have a better answer. Personally, I wouldn't have busted this up into another class, but I didn't have a good argument to stand on.
Today I went searching through Agile Principle, Patterns, and Practices in C# looking for a better answer. In the chapter on SRP, the book gives an example of an interface of a modem that can Dial/Hang-up and Send/Receive. The former is connection management and the later is data communication. The book asks the question as to whether or not these responsibilities should be separated. The answer is
"That depends on how the application is changing."
It then gives an example to how a change might violate SRP, but then states:
"If, on the other hand, the application is not changing in ways that cause the two responsibilities to change at different times, there is no need to separate them. Indeed, separating them would smell of needless complexity."
Ah, there's the backup wisdom that I needed to validate my gut feeling. Here's one final quote from the book:
"There is a corollary here. An axis of change is an axis of change only if the changes occur. It is not wise to apply SRP (or any other principle, for that matter) if there is no symptom."
I think applying SRP is about applying good judgement. You certainly don't want to wait until you have to make a change before you think about SRP, but you don't want to over do it either and end up with classes with one method with each having only a couple lines of code.
From http://lostechies.com/blogs/, 7 days ago,
0 comments
Starting at Headspring gave me the first opportunity in my career to do consulting work. I had previously worked in a startup, a product team and a large IT department. In each of those cases, I didn’t leave a job until I gave my two weeks. It was more than a little strange to leave a place after six months, and not from quitting. Transitioning between projects is an interesting spot, having to both forget the old domain and learn a new one, all in a small amount of time. Before I forget, I wanted to look back both at my first project and my first transition.
It’s easy during a project to get caught up in delivery and never stop to look at how processes and events can affect delivery. When I used to work in the test and manufacturing industry, both measurements and events were combined to try and glean the source of success and failures. For example, if the manufacturing line switched to a higher quality assembler, you should expect to see an immediate decrease of assembly defects.
During a software project, no one will notice the correlation between events, processes and quality/throughput, unless they’re specifically paying attention. I didn’t pay attention too closely, but these are some of the things I remember.
We brought on some great people in our project as the work started ramping up. It didn’t matter how great the person was, it takes time to learn not only the codebase, but the domain, the team and the process. While we practice fairly strict XP/Scrum practices here at Headspring, no two working environments are the same, and some variables need to change. New people will lower velocity, so it’s better to set expectations early before the new team members come on.
It’s also important not to blame the new team members for a lowered velocity. They have enough on their hands to be reminded, “hey thanks for slowing us down, jerk.” After one sprint/iteration, our velocity went higher than before, just as we expected.
I know it was wrong, but for some reason, I felt slightly resentful every time a new team member came on board. I don’t know anything about psychology, but conversations with other team members confirmed everyone felt about the same. An existing team gets comfortable not only with their predictable delivery, but also the personalities and dynamics of each team member. Adding a new team member rocks the boat, so to speak, and it can be difficult for the existing team to transition to a new dynamic that includes the new team members. It takes time to figure out where the new people fit, how the work will break down, how the new people interact with the existing team, the new team members likes/dislikes etc.
For the new team member, it’s also a stressful transition, as they have to be injected into an existing dynamic, where the existing team might work together very smoothly and you’re introducing an unknown. On top of that, you have a new domain, new codebase and new project to learn.
Organizations that treat people as resources/head count completely miss this issue, and never address the side effects of adding new team members. Teams are rarely static over the life of a project, but it’s important to understand how much new people have the potential for affecting velocity and delivery.
The last project had by far the most complex domain I’ve ever been involved with. Maybe it’s because I’m so familiar with the e-commerce space, that going outside that safety zone added complexity, but the last domain really trumped all in terms of complexity.
The early indications that it was complex was the amount of time it would take to get answers from the domain experts. Custom configurable pricing rules, different billing options, even product lists that changed per customer. It was still a system where a user would buy things, but without going into specifics, it wasn’t selling some simple widget. There were at least major product types, with prices coming from three different places. Prices could be affected in dozens of ways, and all had to match an existing legacy system.
In all of this, our team spent a great deal of time getting the model “right”. We didn’t try to design it perfectly up front, and we tried to design only as far as our current knowledge allowed. Guessing was not an option.
In the end, I think we worked on one of the best situations for domain-driven design, as our concepts and models needed to be representative of the complexity that was inherent in our domain. Our domain model was large, but simple. We worked diligently to ensure that our classes were highly cohesive, and concerns were clearly separated, each with a discernable business or domain concern. Product selection/entitlement was completely separate from pricing. Pricing complexity did not bleed into product-level concerns. Billing options (prorate, annual bills, prorate and annual bills) did not bleed in to pricing nor product entitlement concerns.
We wound up with a very rich domain model, flexible in the ways it needed to change, rigid in the core concerns of each class.
There were areas of our system that weren’t modeled as well as others. That was fine, our most important areas, where we spent the most time and had the most important domain logic, were modeled very carefully and evolved over time. This worked out naturally, as we only addressed modeling in an area that needed to change or grow. Places that changed more were modeled better, and places that didn’t change either were correct (according to our assumptions at the time) or didn’t matter as much.
When passing off to another team, it’s important to realize that all they see is the current iteration, not any previous iterations of the domain. They weren’t involved in the deep design and domain conversations with the domain experts, nor do they have any insight on where most of the work occurred. When explaining the model to new people, and something looked strange, we always had the excuse “well, we just don’t look at that part often.”
It’s not possible to spend equal amounts of time on the entire model. By spending time in places where we were actually working or interacting with, those areas naturally got better. Other areas we didn’t touch or look at much, weren’t changed that often, simply because they didn’t need to.
Along with the first big project ending, is the first transition to a new project with an existing team. Joining a team that’s already in progress gives me sympathy for those that joined the last project in the middle of development.
Along with a new project comes a new codebase, new domain, and in my case, a new laptop. We have fairly large list of items that need to be installed for a development machine to be ready to develop, including all of the other small add-ons like Fiddler, Firebug, etc. All of this takes about one working day, more if you need to install an operating system. There were still things I forgot to write down and transition from my old laptop, including my AutoHotKey scripts, R# live templates, and other transient files. Some folks I know use thumbdrives to keep all of these types of files, extensions and addons completely portable, and I think I’ll need to go down that route as well.
Joining an existing team dynamic can be frustrating for both the existing team members and new team members. New people will change how the team works, and that small pang of resentment I felt on my last team is surely being felt on the new team. I don’t believe it’s wrong to feel that, as it’s probably a natural reaction in a team environment. I will decrease velocity, or at least average velocity per team member. I’m comfortable with that, as it’s only the initial transition period where this problem occurs. Once we all get comfortable again, it won’t be a problem.
One of my own personal problems of joining a new team/project is that I’ve noticed I start out by pointing out all of the differences and perceived inefficiencies. It’s something I can tell definitely annoys people, as it’s probably the last thing anyone wants to hear from someone new to the team. Every person adds new knowledge, and everyone appreciates that new knowledge, but probably not all at once.
In my last project, we were housed in a bullpen and delivered in two week sprints. This is what the environment and team members allowed. In the new environment, developers and product owners are in one large room, delivering in one week iterations. Not all environments are exactly what we want, but eventually, we have to deliver software. We’ll create as an ideal environment as we can, but the time spent on environment change needs to be balanced against actually delivering value. We’re always watchful of areas of improvement and inefficiencies, but it can take a lot of work to create a completely new environment. As a consultant, I have to create the best environment I can and ensure that the environment is ready when we start the project. After the project starts, we can’t spend nearly as much time and money crafting a new environment.
The new project has great chairs. I’ve never sat in a great chair, but mostly decrepit hand-me-downs. If good chairs in your office are being fought over, it’s an organization smell. I don’t think I could ever go back to bad chair, especially if I have to sit in it eight hours a day.
Also, desk size is important. Bumping elbows a hundred times a day increases frustration and can ultimately cause friction and affect velocity. If I’m thinking about how close the person next to me has to sit, and not about the problem at hand, I’m wasting time.
One of the most enjoying experiences I had at my last project was diving in to the business and domain problems. It was technically challenging, but learning about a completely new domain was the most interesting for me. Trying to learn the existing business processes, and how the technical processes were intended to support it were a lot of fun.
From http://lostechies.com/blogs/, 7 days ago,
0 comments
After quite a bit of work, I’ve finally been able to post a blog entry with my new Windows 2008 Workstation machine. I recently switched laptops, and have been forced to go silent because of the issues of installing Windows Live Writer on Server 2008.
There isn’t really a Windows 2008 Workstation product you can buy. It’s really taking a Win 2008 Server installation and adding some of the Vista features back in. I really couldn’t stand to use Vista as either a home desktop or development machine OS, with all of the UAC and other garbage built in.
Instead of trying to turn things off until I got to a usable point, I started from a stable, clean OS and added what I needed. The best site I’ve found to create a Win 2008 Workstation machine is win2008workstation.com.
Unfortunately, not everything is wine and roses on Server 2008, let alone the 64-bit version of Server 2008. Most applications and drivers that support Vista 64-bit will work, as will most applications (but not drivers) that support 32-bit Server 2008/2003.
At the very bottom of the barrel are applications that don’t support Server 2008 or 64-bit, and prevent their installers from running. Google Desktop is one that provides the installer, but no support. Windows Live Writer, one of the especially heinous installers, has several very annoying aspects:
All of this for a simple blog posting application. For now, one of the only places I could find direct links to installers is here:
http://dotnetwizard.net/live/direct-links-for-windows-live-wave-3/
I’m sure Microsoft will find a way to self-destruct these applications for Workstation 2008, but until then, I’ll be happily posting away.
From http://lostechies.com/blogs/, 9 days ago,
0 comments
Those pesky string indexers.
I've worked on projects in the past where Microsoft has given developers more than enough rope to hang themselves, the rest of the team and any chance at easily maintaining the application. One common piece of rope is when they give developers a generic dictionary object to cram information into. ViewState, SessionState and recently in ASP.NET MVC, ViewData.
Giving developers these bucket-like objects is simply inviting people to make stuff up as they go. They get used as catch-alls, with people making up their own key-names ad hoc and rarely checking to see if someone else has used it. I've worked on several applications before where multiple developers decide to store the same value in something like SessionState with key names that are slightly different (userID vs userId, for example). This makes things hard to maintain as bugs creep up in a system and developers struggle to track them down. In the end, it is the fault of lazy or inobservant developers for doing it, but I lay some of the blame at a framework that makes it all too easy to do.
If things were strongly typed, it'd be easier. You'd be able to track code issues by examining uses of your interface. New "keys" would be introduced as properties to your interface, informing consumers as to what properties are already in use in the system, promoting better self-documentation. The tendancy of developers to use these objects as a catch-all for whatever piece of information they find convenient to cram inside would drop dramatically; It's harder to justify extending an interface for something that will be used once in an application than it is just to tuck it into one of these objects.
What I'm suggesting here isn't revolutionary at all but I'm constantly surprised at the number of shops that let this sort of behaviour go on.
Recently, I've been working a lot with the ASP.NET MVC framework. I love it, it's a very cool tool. But again you have a chance here to hang yourself if you're not careful by interaction with the form values and the viewdatadictionary. This has come up a handful of times with the team I'm working with, where typos have caused bugs to creep up, or people aren't aware of what information is being put into the viewdatadictionary simply because it's not very self-documenting.
Here's an example of how I'm handling this. It could be better, but it works for now.
public ViewResult AddUser() public ViewWrapper(string viewName, ViewDataDictionary viewData, NameValueCollection formData)
{
this.viewName = viewName;
this.viewData = viewData;
this.formData = new FormDataIndexer(formData);
}
public static implicit operator ViewResult(ViewWrapper wrapper)
{
ViewResult result = new ViewResult();
result.ViewName = wrapper.ViewName;
result.ViewData = wrapper.ViewData;
return result;
}
public string ViewName
{
get { return viewName; }
}
public ViewDataDictionary ViewData
{
get { return viewData; }
}
protected string GetData(string key)
{
return GetData<object, string>(key, formValue => formValue == null ? "" : formValue.ToString(), viewValue => viewValue);
}
protected TResult GetData<TInput, TResult>(string key, Func<TInput, TResult> formEvaluation)
{
if (formData.ContainsKey(key)) return formEvaluation.Invoke((TInput)formData[key]);
return (TResult)viewData[key];
}
protected TResult GetData<TInput, TResult>(string key, Func<TInput, TResult> formEvaluation, Func<TResult, TResult> viewEvaluation)
{
if (formData.ContainsKey(key)) return formEvaluation.Invoke((TInput)formData[key]);
return viewEvaluation.Invoke((TResult)viewData[key]);
}
}
internal interface IIndexer
{
object this[string index] { get; }
bool ContainsKey(string key);
}
internal class FormDataIndexer : IIndexer
{
private readonly NameValueCollection formData;
public FormDataIndexer(NameValueCollection formData)
{
this.formData = formData;
}
public object this[string index]
{
get { return this.formData[index]; }
}
public bool ContainsKey(string key)
{
foreach(string collectionKey in this.formData.AllKeys)
{
if (collectionKey == key) return true;
}
return false;
}
}
This example may be a little over the top, but I really do wish development shops would see more value in coding against interfaces instead of writing hard-to-maintain code against bucket objects like the above, or things like SessionState or ViewState. It doesn't take much effort to make a SessionWrapper and expose things as properties, and it would make life a lot easier for people trying to track down bugs.
Of course, just because you build it doesn't mean they can't ignore it and use the buckets anyway... but if that happens, then it's a different problem all together.
From http://lostechies.com/blogs/, 10 days ago,
0 comments
Derik Whittaker and his band of merry video elves over at DimeCasts.net have posted the 0th of about 5 parts to an NHibernate draft run-through presentation I did with a few of my colleagues.
It was part of a presentation I was preparing to give for the ill-fated Houston TechFest ‘08. I wanted to do a draft run-through for a sympathetic audience to get critical feedback. The quality isn’t that great and I wasn’t in full “presentation mode.”
After showing it to Derik, though he urged me to release it publicly saying that people will still get a lot of benefit from it.
If you’re interested in NHibernate, but haven’t really had the time to dig into it, I think these videos will at least give you the basics to understand what’s going on. Hopefully it helps someone!