Thursday, July 31, 2008
The idea behind this article is that without communication, knowledge is lost. You say, "Duh!" I say "What are you doing about it? You say "Oh... ummm..."
So in the article, the monkeys soon find themselves doing an action without ever knowing the reason. What's to stop the next monkey from coming in and saying "You guys are stupid! I'm gonna just change this." Every developer has faced that situation, "What's this piece of code doing here? I'm going to change it!" and next thing you know you've got a bug in your product that got fixed a year ago (but not if you use unit tests to test your bug fixes and you run those unit tests every time you check in code!).
So you need to communicate the history of things. In code we can do it through comments, or unit tests as I suggest. But what about bigger decisions? Why'd we only go half way on this feature? Who don't we park in the spot next to the street? Why don't we come in to the office before 10AM? Maybe time got cut short because the market changed, maybe the street cleaner comes by on random days and Bob learned that the hard way, maybe if you come in before 10AM then your schedule doesn't overlap enough with the rest of the company to make you an effective developer (or maybe it overlaps too much and you can never get anything done).
So we have tools now that help us pass on knowledge. Some are software tools like a Wiki, or a version controlled document management system (which might be the definition of a Wiki) that help us with history that someone might search for. Stuff you don't expect people to remember the details of. We also have other tools that help us transfer knowledge so that we can go on vacation and know that our feature is in good hands. "What kind of tool does that?!?!" you say?
Pair Programming is just such a tool. You sit, she sits. You write code, she writes code. You talk, she talks - and it's not all about code. You learn from each others' experiences, both code related and otherwise. You figure out how to better communicate with your boss, and you learn that you should always use a finally statement to clean up your objects that implement IDisposeable.
Meanwhile, you stay on task instead of checking your GMail, or http://fark.com, or to go vote at http://stackoverflow.com, or to wander around to talk to people... you are talking to someone already. So you're more productive, and when you get stuck, chances are that your partner is ready with a solution. It also gives you some added confidence, now you have two people who think the code is good instead of just one. You'll know that confidence is well placed the moment your partner asks you "Hey what about this edge case here?" and you go and write code to handle it.
It's not something that comes naturally. It's hard to give up your privacy, and have someone "sitting over your shoulder" all the time. But when you try it, when you do it, and you experience the difference, you'll never want to go back.
Tuesday, July 29, 2008
Dan is the CEO of Widget Co, and was meeting Raphael for drinks one night. They got to talking business as they always do, and some guy slid over and said "You're the CEO of Widget Co? What do you guys make over there?" To which Dan, with a confused look on his face, because the answer seemed obvious, said "We make widgets at Widget Co, hence the name...", and returned to his conversation with Raphael. But the stranger persisted, "You see, my wife works for you, and all she talks about is the gizmos she has to make, not widgets." Dan was clearly upset now, "Why yes, gizmos are a feature of the widgets we make at Widget Co." Now the stranger had him, "So you make gizmos at Widget Co.? That doesn't make sense." Raphael at this point made a hasty exit with a woman he met earlier and Dan just stared at the bottom of his all-too-empty glass and replied simply by sighing.
It happens everywhere in all industries. The key is where your expertise lies. It may be a natural evolution for a stainless steel company that usually ships unfinished steel to start making finished goods. But is it a reasonable extension for a law office to also offer lawn mowing services? Probably not. At Passageways, when we saw that we had a need for a search engine we knew it was outside of our expertise, we were a web-based portal company, not a search algorithm company. It was time to get outside help, and we did.
Knowing what you do, and doing it can be two separate things. The cause for disparity is often listening to customers "too much" and letting them steer you on their individual needs while losing site of the company's goals. Don't get me wrong, customers should have a voice that does not fall on deaf ears, otherwise you can kiss your revenue goodbye, but those voices need to be reconciled with the overall vision so that healthy decisions can be made, such as asking Gizmo Inc if they'd be willing to sell us some gizmos so we can get on with the widget making.
Tuesday, July 8, 2008
I understand that this isn't a ground-breaking discovery, but it's something that all developers I know have learned the hard way. In fact, the Model-View-Controller Pattern (MVC) is the de facto design for the aforementioned solution. Unfortunately, the pattern doesn't spell out the class definitions and their interactions specifically. Instead it leaves those details to the developer. Hence, it's specification as a pattern. Not to mention the slight variations of it's definition a developer will find when typing "MVC" into the Google search box. I'd like to explore this pattern and describe a possible implementation in C#.
Before I do so, I feel it's appropriate to mention that the ASP.NET team has created a MVC Framework, which I will not be discussing in this blog.
First, let's define the problem. We have an application that doesn't have a clear design to it and we've been asked to implement a feature that adds, removes, and updates users and roles. Roles can contain many users as well as many roles. The users and roles will be used throughout the application and we know that maintenance will become an issue if we don't start thinking about the overall design.
The first step is easy: Define a User class and a Role class.
Now that we have the objects defined, we have to understand how interactions with these objects will take place. This is where the user interface comes into play. Several UI objects (windows, dialogs, etc...) need access to the objects.
Since the UI needs to display the users and roles as well as have an interface for adding, removing and updating them, we can certainly create instances of the objects all of the UI classes. If we do this, we soon realize that every time we add a user to a role, we have to call the appropriate methods elsewhere in the UI code to persist the changes. This becomes problematic because every time we add a UI object, we have to call methods on those objects as well as have references to them.
Example code in one of the UI objects:
private void OnAddRoleClick(object sender, EventArgs e)What if a third UI object is created that is interested in roles? That object will also have to maintain a role collection, pass it's instance passed to the two existing UI objects, and expose public method to add have roles added to it. In other words, for every UI object added, every existing UI object must be updated. This isn't going to be easy to manage in the long run.
Role newRole = new Role();
Now is a good time to separate the business logic from the UI. To do this, we will create one object that manages the user and role objects and pass an instance of it to the UI objects. Lets call that object "Application."
The Application object represents the Model of the MVC pattern. We already have the View of our application defined by the UI, so now we have to connect the two. This is where the Controller comes into play. The Controller is responsible for responding to events and invoking changes to the Model. In C#, this can be accomplished by raising events from the user and role classes and handling UI events to update the Model in the UI objects.
Here is what the Model will look like with the new Application class and the appropriate events exposed:
All we need to do now is pass an instance of the Application class to the UI objects, handle the UserAdded and RoleAdded events in the UI code, call into the Model from the UI when the user adds roles and users, and we're done! Well, not really. With most design solutions comes a number of smaller design problems. I'd like to explore some of those problems in my next post: Object Models and the Observer Pattern.
Tuesday, July 1, 2008
But what about when something happens that the team can't resolve internally? Say a personality conflict, or maybe team morale has dropped so low that no longer is "for the good of the team" good enough. That's when you need help.
In the case of a personality conflict, some suggest that the team can vote someone off the island. In that case, the team has the power to remove a person from the team who has become an impediment. But a team can't fire a person, only remove him from the team. So that person has to go somewhere, this is where management helps [or doesn't help]. If management can't provide him with a place to go, he's going to stay on your team and everyone suffers. If management forms a new healthy team, then you're all set, everyone wins.
In the case of low morale, where a team no longer functions well enough to solve even the smallest of impediments, an outside hand is needed. Sure, it is possible that the outside hand is part of the reason the morale is low, but who better to solve the problem? Everyone makes mistakes, and everyone gets the opportunity to fix them.
Keep in mind, that management shouldn't step in every time "for the good of the team" isn't good enough. The idea is that a team is self-organizing, and draws on the creative solutions of the creative people that make up the team. Their solutions of a four person team are expected to be better than the results of four individuals working on the same problem. Collaboration makes them better, and the struggles they overcome makes that bond stronger.
So when should management step in? The answer is simple, but sometimes hard to identify: When the team fails to identify a problem. Individuals may have identified a problem, but if the whole team doesn't agree that it needs solving, then this is when management needs to step in. We had a situation where there was clearly a conflict within the team. As usual, we were allowed to work it out, so after a sprint, we talked (and drew) it out. The result of this particular discussion was that the feature specification we made up front wasn't being followed, and two members viewed this as a problem, one was indifferent, and another thought that everything was fine. The team did not agree that there was a problem, and thus created a problem for two of the members (Matt and I) who felt that the feature spec needed to be adhered to, or revised as a group.
This is a perfect time for a manager to step in. His job at that point would be to determine if the problem did exist. He'd have to listen to both sides, and then make a call based on the company's history and goals. Chances are he was there when the feature spec was put in place, and knows the issues that arise when there is no documentation of discussions. But he might also say that the feature spec is antiquated, offering no value outside of the team, so something more valuable to the company might be suggested.
The bottom line: A team usually does an amazing job of solving problems that affect the whole team. The team struggles when a problem affects a part of the team in a negative way, but another part benefits from it. This is where management plays an important role, and their action or inaction can greatly affect the health of the team.
The problem compounds when part of your team is in a different timezone. Staying in the US with as much as a three hour gap is detrimental to an eight hour work day, but what if your company has paired you up with an off shore team in India? Sure, it seems great to have people working on a project nearly 24 hours a day, but the reality is that there's no reason four people can't do the same work in an eight hour window as two can in one window and another two in a second window. The detriment is when you need a question answered. For instance, let's say it's Friday morning, and you just checked out the latest code from source control (you do have source control, don't you?). You were all set to finish up a user story today before going home for the weekend, when you realize that your counterparts in India decided to refactor three classes. Nothing is where it was before, and they didn't send you any kind of help on how to use the new set up. You could:
- Call them. The company is more than willing to foot the international phone bill.
- Send an email. You can be a little more clear and concise to help the communication barrier.
- or you can spend the time yourself to figure out what the hell is going on.
You best option is surprisingly the third option (or you could work on something else). Because of the time change, team India has already gone home for the weekend. You'll get your response sometime on Sunday. It'll be Monday before you can get anything done.
So the question you have to ask yourself is this: If it takes that long for a team member to get work-related information, how in the world can I expect the team to develop the comaradarie and trust it needs to be highly effective? You simply can't.Occasionally, I was brought on to help interview candidates. I knew someone else had an interest in seeing if the candidate could write code, so I never asked many technical questions. I was always after the team fit. "Can I talk to this person?" "Does this person speak in a way that is constructive?" "Will this person be able to learn from and teach me?"
This often showed itself with a much simpler question: "Does this person laugh at my jokes?" If she didn't laugh, I knew right away that we'd have trouble communicating. It might have been a language barrier, or a subculture barrier? Sometimes my humor is lowbrow, but that's the way the team works on a daily basis. It happened more than once that I said a person was not a good match, "a 'No Hire' situation" as I now say in the hiring market, but I was told that culture fit isn't as important as I made it to be. In each case, the person hired was not successful in his/her job (and was usually let go or repositioned shortly after). I'd take someone eager to learn with a good team fit over a brainiac-thorn-in-my-side any day.
I've gotten slightly off topic but the point is that the team has to work together. In an Agile software environment, a team is not a group of people who meet once a week. It's a group of people who share the same work. We all own the same code, the same successes, the same failures. This isn't true in other departments where victories are the result of an individual's efforts. This is also why it's tough for management to understand why you need a big room with all of the team together all of the time. I'm not saying there can't be a side room for personal phone calls, but when you're working, you need instant access to the knowledge of the team. You need to be able to collaborate at any point in the day. You need to know these people, and know that you can trust them to do their job, and ask for help when they need it, and ask early.
The key is to have a physical presence in the same area as the rest of the team. The barrier to pop your head up and ask the guy on the other side of the table is insignificant to looking up a number, picking up the phone, dialing the number, waiting for the off-site guy to answer, and so on. A man in Waterloo worked around this disparity by getting a robot with a monitor, speakers, and web cam to drive around the office. He may not have been in the office himself, but all the components for people to interact with him quickly were there. If a time change is an obstacle, then consider shifting your office hours to match, devs love to sleep in, but families can throw a wrench in this work around. If all else fails, just split the team. The people that can work in the same space at the same time are one team, the people on a different schedule/location form a different team, or work solo. In the end, your teams need to be with their team mates, and they need to be able to leverage those team mates at the drop of a hat.