Sunday, December 2, 2007
Wednesday, November 21, 2007
Mass Effect or Rock Band?
Decisions, decisions...
I started with Rock Band -- we had a full band waiting to play (myself, husband, sister and brother-in-law). I needed to set everything up before they came over. (i.e. I wanted the drums all to myself)
Having 4 friends rocking out is really a blast! My sister thinks we should dress up and do a show on Thanksgiving for our family. I'm not sure, will they appreciate our musical talent?
Can someone tell me how to stop playing the same songs over and over again? If I have to sing In Bloom one more time...
My sister and her husband went home after a few hours of rocking and it was on to Mass Effect. It looks great! Only problem... How do I play? KOTOR is one of my favorite games of all time and so far this game feels more like Halo than role playing... Need to work on using powers better... I figured out the equipment screen though!
I couldn't agree with Penny Arcade more :P (read all 3)
Whatever happened to sustainable pace?
Development is an art. Its a mental challenge (emotion if you pair). As a day goes by, an individuals definition of quality changes depending on their mood and energy.
Over short periods of time a team can keep up long hours; especially if there is positive momentum or results in sight.
But permanent hours to get more out the door? Does this really work with out sacrificing quality and practices?
How many times are corners cut to meet a deadline? Was it ever too much to write that test first? Was code copied without refactoring to remove duplication? Is there spike code in production cause it worked?
Is that our risk to take?
Can a person control burnout or realize the compromises they make? People have an amazing ability to adapt to any situation. In a bad situation, we forget, we lie (mostly to ourselves), we ignore and we accept things we shouldn't.
Tuesday, November 20, 2007
the joy of pair programming
Sometimes I still don't.
But, I admit this:
Pairing is a great practice.
Great, but surprisingly difficult.
The ideal pairing situation requires both people to be expert developers. They need to be open to the other person's idea. And in this case (expert developers with good, strong opinions), its likely to bring pain.
If the pair is not parallel in skill (which is often the case), the stronger person must slow down and take on a mentoring role. Being a mentor when you want to be as productive as possible is frustrating. Many developers are poor teachers, but communication and discussing ideas is key to creating a great solution.
Every person you work with is different and you create a unique pair. You will go at different speeds, create different designs, even make different jokes.
Pairing is a good mechanism for teaching, but the real strength is in design and code. I have seen no other practice keep every team member familiar with every project, design and decision.
The whiteboard is rarely used because the pairing session isn't about code, its about creating. The design decisions are made when the pair needs to make them. Any previous design or decision may not be the best solution when (and if) its needed.
If discussion can be avoided, don't do it. The best way to be productive is to keep coding and evolving. Focus on small steps to deliver functionality quickly and ensures CI success.
With pairing every moment is a code review. If the team switches pairs and owns the code, everyone is familiar with everything. No reviews, no whiteboards, no documentation.
Imagine the possibilities.
Wednesday, November 7, 2007
Working remotely
I love working from home, however, it takes a lot of discipline -- and not just for me. My teammates need to be aware that they need to speak a little louder or stand by a camera and I need to stay away from halo during the day :P
Personally, I find it easy to stay in a work mode while I'm at home. Pairing is quite effective remotely. I tend to keep better focus while I'm remoting with a pair than in person.
Meetings are a lot more challenging. Good microphones and video feeds are a must if you are to have any chance of "being" in the meeting. When I first started working from home, I wasn't able to participate in meetings at all, but with help of some additional media equipment, I can go to every meeting in my pajamas :)
If you are working from home, here is some advice:
- Have space dedicated to work. This helps you stay focused and keeps you from working too much. If I setup shop in my den, chances of me working extra hours while my husband plays xbox is dramatically increased.
- Be honest and open about communication limitations. Its better to interrupt if your call drops off or someone is too far from the microphone than miss something.
- Respect your coworkers during meetings and while they're talking. Just because they can't see you surfing the web while they are talking about some deployment doesn't make it okay.
- Take breaks, walk the dog, get some exercise. Believe it or not, its easier to sit on the computer during lunch than in the office. Its just as important to walk around when you are at home. And stay away from the snacks in the kitchen!!
- Get a really good espresso machine.
- Visit the office. Even if you don't have to come in, its good to keep the bonds strong with teammates. If you are too far to come in on a whim, try to work something out with your company that lets you come in not just when you have to, but when you want as well.
Friday, October 26, 2007
Inspiration
Gerry is leaving Oxygen at the end of the year. The idea of creating software at Oxygen without Gerry seems unimaginable. But like any change, sometimes you don't think you're ready until you take the next step.
I hope to one day inspire someone the way Gerry has inspired me.
Wednesday, October 24, 2007
Fairfield/Westchester code camp
Register here
The session is a shortened version of the tutorial Oksana and I are giving at the Agile Development Practices conference in December.
Hope to see you there!
Wednesday, October 10, 2007
Saturday, September 29, 2007
Skulls are fun!
I can't play without the grunt birthday blast. How else can I be sure I'm getting head shots?
Did you know bungie keeps a detailed record of all your games? If achievements weren't enough to keep me going...
Friday, September 28, 2007
Good practices are beyond testing
When I started using TDD I loved is how it enforced these principles. I couldn't maintain or write tests without them. Testing even forced the need for dependency injection and inversion of control containers.
The tests started to validate and enforce important behaviors. Behaviors some people don't appreciate. Sometimes these had been a hard sell.
TDD became an easy justification for best practices. How awesome!
Enter mocking libraries that don't require DI. You can mock everything from constructors to static methods. Mocking methods on the CUT is as easy as creating a new class for that responsibility.
With this, its easier to make a large class and use static utils and real constructors. Now you can test without adding those pesky things that add to the confusion of object oriented code... you know stuff like interfaces, polymorphism, encapsulation...
If we don't need DI or interfaces for testing, then why do we need them? If testing can happen without it, then that behavior isn't driven, right? Why can't I make a big class if its testable?
But these design principles have been around for a long time and for good reason. DI, single responsibility and separation of concerns were not born from testing.
Tuesday, September 25, 2007
Does Intuitive == Maintainable?
My coding standards and styles change constantly.
I have yet to return to a project after a hiatus and understand it without some investigation -- no matter how intuitive it originally seemed.
If this is so, how can something be maintainable? If a project can be written in a few weeks and then not touched for several months, is there any chance you'd automatically understand or agree with the design?
There are very few solutions that cannot be figured out. Sometimes it takes minutes. Other times a bit longer. A lot of times it involves grimacing, cursing and questioning the sanity of the original developer(s).
But no matter how "awful" a solution may be, at one point it made sense to someone, so with some detective work it can be understood.
Something common of software that is easier to maintain is single responsibility and separation of concerns. These principles are not subjective. They don't change with time, mood or business domain.
If a project follows these principles understanding the entire system isn't necessary, just the part that needs to change. It may take some time to find it, but once found, the solution is simple.
Sunday, September 23, 2007
Countdown to Halo 3...
Eternal Sonata is keeping me busy in the mean time (I highly recommend it for all you JRPG fans!)
So many games (Halo, Rock Band, Guitar Hero 3, Mass Effect, Beautiful Katamari...), so little time... I don't think I'll be blogging much this fall :P
And I still didn't beat Bioshock on hard...
Tuesday, September 11, 2007
Too many mocks?
At what point can you push too far?
With TDD, its all about your tests, so anything that helps you write a test is the right thing to do. I am confident the tests drive a good design.
However, sometimes there are border cases. You may wonder if another class is excessive.
In this case ask a simple question: is this behavior the single responsibility of this class?
Usually the answer is no. The behavior I'm testing is combination of responsibilities and so, yeah, a mock is a good choice.
Monday, August 27, 2007
Alt.Net Registration...
Thursday, August 16, 2007
Last day of Agile 2007
I'd like to thank everyone who was at our tutorial on pair programming. You were all great and I hope you had as much fun as I did!
Taylor the Sailor found me after the session and asked the question you were all dying to know... "Do you really know what an NPC is?" Of course I do!
For all of you wanting to know why we were talking about D&D, I'd usually say you'll have to come to our next session. However, I don't think it would be as fun a metaphor without Oksana saying, "I have no idea what she is talking about, but I know it has something to do with video games." It is probably the last (and first) time I use it as an example activity that's best to do with someone else.
Today, Ken and Ilio's presented their experience report on Ript. They did a really great job. It was fun to be in the audience of another team members' session!
I'm really glad the whole team was at the conference. I'm really lucky to work with people I admire and enjoy so much!
With all this great team spirit its hard for something to compare. However, on the first night, they had a balloon guy at the ice breaker and he made me a bicycle! He didn't even call me a hyena for asking :P
Tuesday, August 14, 2007
Ript
One of them, Ript, is something completely different.
Until yesterday, I had to be pretty quiet about the details, but now that I can talk, I'd rather you try it for yourself.
Thursday, August 9, 2007
Disney, here I come...
We will have a 1/2 day tutorial on Mock Objects and a session on The Gentle Art of Pair Programming.
Hope to see you there!
Friday, August 3, 2007
A changing community...
If there is agile, why is there ALT.NET?
The development environment of many institutions is molded to the vision of software provided by people with no insight.
Pushing irrelevant solutions and deadlines.
Traveling a rote technology line.
Where does that leave the rest of us?
We go with the flow.
We find a place that embraces agile.
We work to change our environment.
It takes a great deal of energy to foster change in your environment.
It takes time, effort, trust and many other qualities that make going with the flow look better and better as time goes by.
You are not alone.
Your company software policies were not created by your company.
They are the practices of the community.
A community that conforms to business and technology providers' desires and not the interest of creating the best solutions.
What is ALT.NET? It is a community that will not conform to these principles. It is a group that is working together to foster change beyond our individual environments.
What is the ALT.NET Open Space? It is for people who want change. It is for people who want to share. It is for people who want to learn.
Everyone will be someone who wants to do something for the community. They will come with something they know and leave with something to share.
Tuesday, July 31, 2007
At last something that makes sense...
Why they ever did, I'm not sure. You would have thought people experiencing problems that required a "hotfix" should get it as quickly as possible...
Monday, July 23, 2007
Harry Potter
Tuesday, July 10, 2007
Remembering the future
Six months from now is January...
Its cold and snowing. I'm drinking a latte, writing this entry and expecting a call for the morning stand up since I'm working from home. I can hardly believe just 6 months ago I missed this weather during a heat wave in July.
As I write, I reflect on the last six months, its crazy how much has happened on my quest to become a better developer.
The summer was hectic, both professionally and personally. We released the Beta version of Ript, it was awesome. We celebrated at the Brass Monkey with a few rounds of beer and great smiles. We all love the application and we learned everyone else does too!
Shortly after the release of Ript, Oksana and I presented The Gentle Art of Pair Programming at Agile 2007. It was awesome! We played lots of games and having the whole team there was a great demonstration of agile team spirit.
While all this was going on, I was on my way to becoming a Rails guru with the help of an expert mentor and a small Oxygen web app.
Aside from my professional adventures this summer, there was a lot going on personally. Somehow with all the chaos, Oksana and I took up surfing with the help of a coworker, Lee. It was definitely an adventure! I also got serious about the gym and yoga after slacking off all year. My husband and I started kitchen renovations (they're finally done!) and we took a trip to Bermuda with my sister and her husband.
Of course I can't forget, I read Harry Potter and the Deathly Hallows in one night. I'm gonna miss Harry and his friends' adventures...
The low point of the summer was Jury Duty. That's all to say on that subject.
Once fall began, things picked up even more. The release of the Rails application was successful and I sadly said goodbye to my mentor. I then spread my new knowledge to the rest of the team, which Robert was absolutely loving!
We had several new team members join our team at Oxygen and they were totally rockin'. They quickly came up to speed on all our projects (so many projects...).
I spent a lot of time in the fall working on our upgrade to high definition, a domain reminding me of my past experience in broadcast software. I also spent a great deal of time preparing for my DevTeach sessions in Vancouver (Thanks Scott and everyone for the great memories!). Of course I spent plenty of hours blogging, reading various books, blogs and anything else to help my projects and presentations.
On the personal side, my husband and I created a web site for our consulting company, making our business a little more official feeling. Since then he's created several applications and I've been coaching agile practices every so often. I keep telling him to leave his job and work for our company full time so he can be a full time daddy if we ever have kids :P
By far, the most frustrating and exciting project was my kitchen renovation. It was quite an undertaking, but well worth the investment -- I love to cook! Its amazing how agile practices help home designs, renovations and working with contractors :)
Once December came, things slowed down. I love Christmas time. My husband and I took time off and relaxed, prepared for the holidays and enjoyed life.
I took the time to do some counting:
Blog entries -- 63
Emails to Ayende -- just over 50 questions about rhino mocks and other things (with a few reminders to get some sleep :P)
Movies watched -- 73
Series watched -- Smallville, FullMetal Alchemist, FruitsBasket, Berserk!, Invader Zim (again), Samurai Champloo, thats all I can remember at the moment...
Books read (fiction) -- 18
Books read (development) -- 5
After New Year's, work started again. New projects and interest in Ript 2.0, which is super exciting! Our HD release is just a few months away. Broadcast deadlines are absolute, so we have little time to lose.
I'm now awaiting the spring and looking forward to what the future holds...
Thank James Kovacs for the details of my future.
I'd like the following people to reflect on their past 6 months from now:
Roy Osherove
Hammett
Lee Bankewitz
Scott Bellware
If you are wondering, this is called remember the future. Its a great exercise to use with stakeholders to help determine the long and short term goals of a project. Also a fun personal exercise too! I learned this exercise in a class with Luke Hohmann and he has a book with this and other games called Innovation Games: Creating Breakthrough Products Through Collaborative Play.
Monday, July 9, 2007
An odd sense of humor
I recommend these:
Sun Love
Suicide Train
Monkey Photographer
Enjoy :)
Thursday, June 21, 2007
It’s more than a catchy term
Every person is different. They have different experiences, backgrounds and interests.
As we work on a team, we learn to compromise and appreciate other people’s opinions. We change and evolve our practices and create ideas together.
On an agile team this keeps improving. On a dysfunctional team, it plateaus or degrades.
We change based on our experiences and dedication to continually improve. This drives our best practices, interaction with stakeholders, technologies and tools.
We improve by changing. We rely on team retrospectives and personal introspection to guide us.
We buy into our efforts. We enjoy progress. We admit failure and move on.
In our world, stakeholders change their minds (or just don’t know), technologies emerge and practices evolve.
Change is an absolute. Adapting to it is agile.
It is not an easy path, just a possibility for success.
Sunday, June 17, 2007
A rose by any other name
When I first began TDD, my names looked something like this:
public void MethodATest()
Look familiar? What does this test? Well, it gives me a new method. It tells me I have to test all the functions of this method in one test. It does not give business value and does not give any clues when it fails.
This methodology did not last long -- my tests were too large, too complex and tested too many things. When I had a failing test, I had some idea what was wrong because I remembered the method, but my tests did not evolve with my code.
Eventually, my next naming convention looked a little more like this:
public void MethodADoesThis()
or
public void MethodADoesThisWithThat()
or
public void MethodADoesThisWithThatWhenThisIsTrue()
(sometimes this was: public void WhenThisIsTrueMethodADoesThisWithThat())
Although this naming was more descriptive, it was slightly ambiguious, drove too much design in a single test and was not easily read.
The anatomy of a test is basic, there is a setup of preconditions (context), execution of the code (call method), and then verification process (Assert or Verify).
What if our name told us what to put in each part. Would you know how to write it? Would you know what its testing?
Back in February, Aaron made a post about loosly coupled mocks. His naming convention is great. Its simple, has clear rules and forces you to think about what you are testing. It not only follows the anatomy of the test, but puts you in your test before you write it.
What it looks like:
public void Method_Context_Expectation()
So, for the simple hello world test:
public void GreetTheWorld_Always_CallsConsoleWriteLine
Always is a weird context right? Well, its true and writing it helps understand what you are designing.
Now, what if we want to add a condition to calling GreetTheWorld?
Say we only greet the world, if the world exists:
public void GreetTheWorld_WorldExists_CallsConsoleWriteLine
public void GreetTheWorld_WorldDoesNotExist_DoesNotCallConsoleWriteLine
This naming convention also helps us understand when to use SetupResult instead of expectations. In the methods above, we are using the world as context, and the console as verification so we would say SetupResult.For(theWorld.Exists) instead of expecting it -- we don't want our test to fail from context, only when our expectations are not met.
Another nice thing about this convention is detecting smells in my design. If I have 10 methods for GreetTheWorld, because there are many contexts or expectations, I'd know GreetTheWorld had too many responsibilities.
Who would have thought a simple naming convention could have helped so much, thanks Aaron -- or rather the unnamed person Aaron stole this from :P
Thursday, June 14, 2007
Oxygen is Hiring!
Tuesday, June 12, 2007
Boo
He recently pointed out some very nice xml support.
For a whole lot of documentation (and introductions) about Boo go here
It has a really great name too :)
Saturday, June 9, 2007
I taught my husband TDD today
In less time than it took me to write this post. Can you believe that?? He learned to drive design. He got it!
We started our lesson when I was writing another post about TDD (big surprise, right?). He said I should post some examples. I said that my examples wouldn't be useful without the reactions of the audience. Everyone learns differently.
He gave me a simple example to do, test drive a class that writes "Hello World" to the console. I started explaining what makes this simple problem not so easy to test and we decided to try out the example together.
Asking questions is a great tool to help someone learn, it makes the learner realize conclusions. Figuring out the right questions is always difficult and this morning was no different.
I asked lots of questions. They were focused on one thing: How can I make the introduction of a mock organic?
Eventually he suggested we put Console.Writeline in our CUT, then we refactor it to be testable.
This made me realize my questions were not right.
I needed to teach him how to think in the test. I knew this was a major key how I learned TDD, but I thought it was an evolution.
I was wrong.
In this moment, I realized that learning TDD isn't about writing tests. Its about leveraging polymorphism to verify responsibilities and interactions.
Once I realized this, I only needed to ask one question:
Is there a way we can put something between our CUT and the System.Console to verify the right method was called?
In a few minutes we had an IConsole and a MockConsole implementation. A few minutes later we had a working test, a minute after that we had a console application that wrote hello world.
During his implementation of MockConsole, he found many limitations. After we had a working application, we went back in the test and replaced MockConsole with a RhinoMock.
In the end, he understood how the test drove his design, why it did, why he used a mock and appreciated a mocking framework.
It was awesome.
I'll let his reflection on his learning speak for itself:
I really like TDD. The code you end up with is really good. Its the minimum amount of code to write to make your code testable. The difficulty between just programming and test drivent development is very different...
On the first day of college, you write hello world straight to the console without any understanding of coding, its the real basics.
On your first day of TDD it takes a few layers in between to do it right, its geometrically more complicated, but its only adding a some subtle difference, like IConsole. It gives you the round trip of object oriented programming with simple examples that really illustrate why you do the things you do with object oriented programming. It really takes a great understanding of OOD to appreciate TDD and do it right.
Deciding what tests to write and how you write them are hard, harder than writing the code.
Thank you, that was nice.
Friday, June 8, 2007
Agile 2007
Ken, our VP of development and Ilio, our client proxy, will discuss the team's collaboration and experience with our product owner and CEO, Gerry Laybourne.
Agile 2006 was a great conference. With our contributions, Agile 2007 is sure to be a blast!
Wednesday, June 6, 2007
My take on the Joel Test
We said this is a great environment for pairing and development and someone said, that's not what Joel said. Jeremy Miller's response was, "Joel's wrong," and until I read Jeremy's recap I didn't he was talking about joelonsoftware Joel. I assumed the person who spoke went to another session at DevTeach where someone was talking about the ideal development environment.
After reading Jeremy's recap and thoughts, I gave the test some thought. Like Jeremy, I like the questions. Who doesn't? But if you are a strong developer in the right position and environment, couldn't you make those things happen? Sure, they're great to walk into, but if you're walking into an environment that is ridgid and has issues beyond your control, you have a much larger problem then setting up a build environment or proving sufficient qa costs less than lacking qa.
Yes or no questions give me pause as well -- I find it easier not to disclose information or to even lie to myself if asked a yes or no question. I'm sure other people do too. Do you have a QA department? Well, Joe the summer intern and Rita and junior developer did a bit of testing before our last release so, yes. When asked to describe my QA environment, they don't seem to hold up well.
Now Joel says in his description of the big 12 that these are just guidelines and there are great teams that don't have any and poor teams with all -- he has a lot of good things to say and the popularity of his blog demonstrates that. However, some people take his list as absolute and that is a bit of a smell.
So, how do you determine if a company is right for you?
Every person is different and has different goals and needs -- are you up for a challenge, do you need a mentor, do you want to work on a team, do you want to be agile, can you promote change, do you want to promote change, what technology do you want to work with, what type of projects interest you, what type of people do you like, what scares you, what risks are you willing to take, what kind of responsibility do you want, what motivates you, what satisfies you, why have you left jobs in the past, what failures have you encountered and why, what successes, where were you most happy and why.
Wow, that is a lot of questions! There are a lot more, because self realization and goal determination is really, really difficult. You need to be honest with yourself. Many people do not like their jobs. For some it doesn't matter because its just something that makes their home life possible. For others it lingers with them long after they leave the office.
If you change jobs when at a time of desparation, try not to lie to yourself. Finding a job that is a perfect match is probably not an option, but if you understand your goals, you can determine your best questions to ask and an environment that will keep you satisfied.
Thursday, May 31, 2007
But how could a test drive design??
Actually, I asked myself during my long a** commute, which gave me a lot of time to reflect.
The weird thing about TDD is that there is no design.
You don't design tests. You write them, one at a time.
This is something that makes TDD difficult. Even after I understood the basics, it was still a challenge to stay with it. I had to stop thinking about how to solve the problem and focus only on how to test the solution.
It's not that I don't think about designs at all, but I'll only design up until the point I know I'll be able to start my first test. This design is focused on high level interactions and the goals of my solution.
When the TDD light bulb went off above my head, my thinking changed to this:
What can I do to make this test as easy as possible to write?
Thats it. Kinda lame looking at it now, but really, thats it. When I focused on testing and that alone, that's all that remained.
If you have difficulty dispelling design noise, pretend you are Harry Potter and have your very own pensieve (that would be pretty cool, no?). Put the thoughts in the pensive. They will be there when you have the focus they deserve (In real life this works well with index cards)
Unless it is a new user story, I throw it out. I don't worry about it, because if I need it, it will happen.
But what if I forget? Are my user stories satisfied? Are my acceptance tests passing? I guess I don't need it.
But I need to refactor my code! Well, I should be doing this all the time! If I didn't have a chance for whatever reason, next time I am in the test, it will be so painful, I'll refactor. I trust myself and my team. When this happens a lot, I need to think about what done means (this is another topic)
How do I make tests easier to write?
When I can't make a test without getting frustrated or overwhelmed with what-ifs or setups, I introduce a mock and encapsulate the behavior. Using that mock just made my life a whole lot easier.
Did I just drive the creation of a new interface? Is there a new interaction that didn't exist because it was the easiest thing? Will my class be more simple because its not doing something too complicated? Will the new class be cohesive because it was created for a specific purpose?
Wow, not only am I creating a new design as I go, but all other things happen because I'm trying to make my life easier.
Anyone else see the beauty here?
Or the power?
When I have a very complicated problem, I break it up organically by test driving. Each part not only makes sense, but is easier to implement because I am able to focus on small pieces. I have instant gratification that each worked on its own, as it was created, without any integration.
Sweet bonus, the solution doesn't do anything extra and I didn't go on any tangents because I didn't want to write extra tests.
Extra sweet -- I spoke to coworkers, took a lunch break, wrote a blog post and had NO fear my momentum or focus would be lost.
Writing tests is more difficult than writing code, but when I focus on making my tests as easy as possible to write, it keeps me in the test, drives my design and simplifies my thinking.
Tuesday, May 29, 2007
Xna Feature Request
(i.e. Make GetService support Generics!)
Follow the link and click "vote now".
Use your MSDN/Live credentials to log in.
If you get a page not found error, you need to complete registration for Microsoft Connect -- go to the "My Participation" link in the left menu.
Monday, May 28, 2007
Pair programming, team ownership and collaboration -- Oh crap!
I never needed to talk out a design, it would just happen. I loved creating software and I was quite good at it. In a few short years I went from code monkey to architect and project engineer.
In all this time, I never developed a sense of team, community or sharing. I had a hard time communicating my designs; I never thought about them, I just did them. I had difficulty listening.
When I first got to Oxygen, with only pair programming, I was completely frustrated. I was use to excelling and being the hero of the team.
At pairing and communicating I, well, let's just say it didn't come so naturally.
For me, the most difficult part of pairing and code ownership is giving up what's best for you and substituting it with what is best for the team. This is a concept that is very important for the entire team's productivity and happiness.
In our world we have a lot of brilliant developers, with a lot of brilliant ideas. Our designs are more of an art than a science and with any art, it is a personal expression. This is why collaboration, sharing and pairing is so difficult -- in our minds our design is always really good.
And for each individual that is true.
But for someone else, a solution that brings you great success may bring them great frustration and pain.
What is the solution? How can we all agree? In what ways can we share our knowledge?
I'm not sure... but I think about it a lot.
While differing opinions can bring the best ideas, spending an entire pairing session (or worse days, weeks, forever) bickering about differing opinions is much worse than not bringing your ideas to the next level.
In pairing, when you have two opinions, the best option is to choose an opinion and run with it. If its not the right solution, it will be obvious right away.
However, sometimes its not a wrong decision, its just not the better solution and the pain of the decision may not be felt at that moment.
Will the frustration of the person be felt in the group? Probably not if they are sometimes heard. If your environment has a few people who are more stubborn than others, you may have some frustrated developers who need to get their way more often.
On any team, with each pair, you will eventually find a groove. How long it takes and the style of your solutions with depend on the individuals of the team. And the style you find may be completely different than what you do on your own.
Whatever gives your team the ability to keep their velocity, happiness and quality high is the best practice.
Sunday, May 27, 2007
TDD, What a bitch
Nobody mentioned this to me before I started. Everyone spoke of TDD like magic -- it changes your design, its the best thing ever, its so simple, all you need to do is write your tests before your class, you'll love it... (Ignore the man behind the curtain!)
After a few days of trying, I began to think something was very wrong. I wasn't quite the developing genius I thought...
That couldn't be true!
Like any reasonable person in my situation -- overstressed, too many responsibilities, tight deadlines, stakeholders bothering you, etc... I continued to pound my head against what seemed to be a steel wall of TDD that just wouldn't fit.
My head (now bleeding and bruised) was focused on how to solve the problem instead of how to test the solution. I didn't know it at the time, but until I changed this behavior, I would always be fighting my instincts and not gaining the benefits.
Fast forward two months and I was still, well, sucking, but not as bad. I had some test coverage, I wrote some classes test first, but I did not test drive every class, it seemed like too much work. I also didn't understand mocks, at all, and gave up on writing my own mock classes after about a day, so no interaction testing and lots of coupling.
It was very frustrating to have 1/3 of my tests fail if I was working on a common entity or if a bug showed up. Also, because I was coupling all my classes together I wasn't seeing the full benefits of test driving.
My focus was just as bad as coding before. If I needed a new behavior, I'd have to code. This meant testing the other class, which may cascade into other tests. Thinking about it, I think my focus was worse. Sometimes I could write a stub for the new behavior, but say I was creating a method that returned a boolean that had different responses that I needed to test... And there is the setup to get it into each state. And thats just a boolean assuming there's no interactions...
My thinking was in the same place it was a few months earlier. The only difference was I could write a unit test before I wrote code. But I wasn't test driving design. I had the design in my head. I was writing the unit tests for the classes and interactions I already decided I needed.
Fast forward two months: New job, new project, fresh start, woo hoo!
With this project, I was determined to understand TDD. A lot of bright people that I respected were saying great stuff and I was going to get it.
My first step was to understand nMock.
I knew using real classes in my tests was killing my focus, but I didn't yet know how much it affected my design. I read the nMock web page, explaining the api, about 500 times... "Okay," I said to myself. "You can use an interface before its implemented and verify its been called."
It sounded so simple, it read so simple, yet it made NO sense to me.
My delight in using mocks (once I figured out how to use them) was focused on several things -- I could focus on the test I was writing, my tests weren't failing because of another class and my tests were a lot simpler because I didn't need to put in knowledge about other classes to verify or assert behavior in the CUT. Implementations of interfaces used in tests didn't affect the tests anymore.
After a few weeks of nMock, what I began to notice was that my design, code, thinking, and mind was changing.
A lot.
I only made a class after it was being used as an interface in another class. That class' only public methods were in that interface. I never debugged my application. I almost never debugged my tests. My test coverage was over 90%. My design evolved through the tests.
I was test driving. Finally!
Making tests was so focused and had immediate results I was addicted. At some point, something happened in my brain and this great thing called TDD finally came in. I didn't want to write in the CUT first, because it wasn't how I was thinking. It seemed like more work.
I was in the test.
Friday, May 18, 2007
Hot Agilista Update
Things I learned at devteach:
- Oksana and I are Boffers, not Speakers
- Ayende's mind never stops. Its not surprising, but its been great to spend so much time with him here. He could probably fill a book
- Scott Bellware likes to torture people by taking them to questionable restaurants.
- JP Boodhoo is very disciplined and plays Gears of War!
- ActiveNick and I are going to have fun playing Gears of War with JP!
- Oksana rocks (I already knew that, but its still true)
- Carl Franklin is quite the musician
- Udi Dahan is surprisingly easy to talk to
- Beth Massi is very cool
- Roy Osherove is very funny.
PS although not documented by our paparazzi, our BoF was everyone's devteach highlight!
Thursday, May 17, 2007
Xbox back online
An update:
As of two weeks ago it was fixed and until I left for DevTeach I was spending most of my time playing Guitar Hero. What a great game!!
I was so proud of myself for getting through medium with mostly 5 stars (still have a few to go), I decided to try hard... and well, it was freakin' hard!
Much to my surprise I was able to beat several songs. My energy was high and my pride was higher.
Then it happened... Woman on Hard... WTF.
I tried to practice, but those pull offs totally kill me... and even when I get past the initial crazy part, that solo??? Really, they did that to knock you down a bit, let you know hard is hard...
When I get home, I'll return to medium until I have all 5 stars, then I'll try hard again.
Wednesday, May 16, 2007
The Gentle Art of Pair Programming -- the Short, Short Version
The audience was excellent and enthusiastic. Thank you for your questions and interest!
For those of you who didn't get enough of us, we'll be presenting a full tutorial at Agile 2007 in August -- more details to follow.
Hello from DevTeach
While the presentations are good, the best part of any conference is the conversations. DevTeach is no exception.
Session Highlights:
1. JP Boodhoo's sessions on refactoring and enterprise patterns -- JP is an enthusiastic speaker and I like his style. Longer sessions would have been great for both these classes. JP even tolerated all my questions, which takes great patience.
2. Jerry Miller's session on Rules of Agile Design -- I agree with everything he had to say (except calling them laws :P)
3. Scott Bellware's session on Behavioral Driven Development -- do we need to rethink our naming conventions again? I really enjoyed how Scott took us through the evolution of an interesting, but understandable example.
There are a few sessions I would have liked:
1. Analysis Services in Sql Server or something about MDX
2. Introduction to Inversion of Control
3. Commands and Bindings in Xaml
4. The Gentle Art of Pair Programming (the full thing!)
Oksana and I are buying Ayende, the creator of Rhino Mocks, for a beer later, so that should be fun!
Friday, April 27, 2007
Mentoring
Peter and I set off on a mission. It seemed impossible. The deadline was an x on the calendar, less than 4 months from my start date, and even one day late was failure. The software was going to be used for broadcast graphics -- the systems would be running 24/7.
Even with a bare list of requirements, the application required the ability to be remotely controlled and have remote distribution of uncompressed high definition video assets. All these operations had to have fast response times.
On my first day, we started developing and the application grew fast, with technologies and patterns I had never used. By the due date, the application was shipped and delivered, the customer reported 2 bugs over a 3 month period.
Every morning we would get together and discuss what I was doing and what he was doing. We'd talk about designs. We'd talk about how things were going. He introduced me to design patterns and authors like Bob Martin, Scott Ambler and many others.
Peter was more than my manager, he was different than a friend.
I was the sole coder on the project, but if I was alone, the project would have failed.
Peter kept me on track, helped me find solutions, patterns and improved my designs. He trusted me.
He let me grow.
Thank you Peter.
Thursday, April 26, 2007
Vista drag and drop
Application A runs with medium security permissions on Vista.
Application B runs as a Browser Plugin in IE on the same machine.
IE runs with low security permissions on Vista.
Application A will not accept "drags" from application B because Vista prevents lower security applications from giving data (and potentially hurting) higher level applications. In theory this is a nice thing to do.
If you add some registry settings, A can accept "drags" from IE -- woo hoo.
Here is the problem: B sometimes starts its own "drags" and A won't accept them (even though A accepts drags that IE started)
Any ideas? (disabling protected mode does work, but is not really a solution)
Monday, April 16, 2007
Xbox broken
And I finally ordered Guitar Hero :(
Hopefully it will be back by the end of next week. Customer support was fast to respond and very helpful. Since this is our third repair, they assigned a supervisor to track its progress.
Its only been a day and I'm already experiencing withdrawal :(
Wednesday, April 11, 2007
The value of user testing
Here's a great demonstration:
Halo 3 Documentary (I recommend downloading the HD version onto your 360 from the marketplace)
Did anyone else notice the dual monitors with multiple keyboards? Are they pairing over there?
I'm drooling over here :P
The developers responsibility
1. Build the best solution
2. Maintain visibility
3. Uncompromising ethics
4. Continuous learning and sharing
We are an engineering discipline, but at an early stage, there is much to discover, too much reinvention, vast (differing) opinions of best practices, poor adoption of quality, little understanding of our art by outsiders and too much competition and stubbornness within the community.
While, I write passionately, I have an ethical dilemma of building the best solution, while experimenting with new technology and keeping my stakeholders aware of my risk taking. How do we justify using unknown technologies to solve problems that have known solutions? How do we share our experiences with our competitors in a way that is valuable to the community? Is it possible to fulfill all my responsibilities? I think so. We're making progress, but we have a long way to go.
Thanks for the inspiration!
Thursday, April 5, 2007
Thanks for the Scrum Training
I highly recommend taking the class, even if you have read a lot about scrum or are working in a scrum organization. Ken had very good insights, was thoughtful in answering questions and sent me home reflecting many things.
As for my fellow classmates, I'd like to thank everyone who supported the leukemia and lymphoma society with your tardiness! For those who are curious, $47 was the total penitance; though the number of late resources was quite less -- quite a generous group :)
Slightly off topic, if you are in Boston and are looking for an Italian restaurant, you must try Giacomo's (Ken, you really missed out!). The new law that lets you bring your bottle of wine home, makes the affordable wine menu great even for the designated driver, who happened to be me.
Speaking of driving in Boston... hmm... its too late to get started on that one.
Wednesday, April 4, 2007
Scrum and the product owner
One thing that I kept reflecting on during the class, is the true value of the product owner.
Before Oxygen, I always lacked the single wringable neck. I met with stakeholders, had iterations, backlogs, daily meetings -- everything, but the true product owner. Most times, I would have buy in from users and developers to participate in meetings and monthly reviews, but I never had what I have at Oxygen and it was a flawed way of working.
There is a conflict of interest between the product owner and a developer. Yes, you share a goal, however, its the developers job to expose risk and estimate effort and the product owners job to evaluate the information to make decisions that will decide the fate of the project.
It wasn't until training today and working with people that didn't have the luxury of the product owner that I remembered the pain lacking one. I've been trying to write about this and I have no words...
Luckily, Ken did a few weeks ago, this is what I want to say. I really loved reading it when Ken wrote it; today I appreciated how lucky I am (once again).
Tuesday, April 3, 2007
A call to women developers
I think its great; if you're out there, you should let her know!
Monday, April 2, 2007
Empty Interfaces
Why you ask? Generics!
I love generics, they've added a whole new world to my design, but when it comes to using a generic interface, I find it best to wrap it in another interface, even if that interface is empty.
Here are some reasons:
1. The name is longer and intellisense isn't smart enough to fill in the types -- more typing (on the keyboard) is never fun (though visual assist does guess pretty well)
2. The name does not imply its responsibilities. Sometimes the generic interface is all you need, but the type of the interface is too generic to understand its responsibilities and behaviors.
3. If you need to add something extra to the interface, it will be quite painful to replace usages with an explicit interface.
4. A generic type name is an ugly type as a string -- I can never remember how to put a generic in the application configuration.
5. Less encapsulation -- if you have a generic interface that has two types, one type is implementation specific (like its used to consume another generic interface) and one type is consumer specific, consumers need to have more knowledge about implementation than they should, just to use the interface.
Here is a reason not to:
1. FxCop -- it gives you a warning... Here is what I think -- FxCop is great at giving warnings, but thats its job, it doesn't understand context, FxCop is not a reason on its own not to do something :)
Saturday, March 31, 2007
The shield of YAGNI
Yagni is a tool to keep us on track, to help us make decisions and guide us in our development. Like any other practice, it does not stand on its own without logic and reason. Sometimes its thrown around like my parents used the phrase, "because I said so." And while that works well for a crying three year old who wants to stay up late, any catch all phrase is dangerous.
When I am writing code, I add abstractions I don't need. You can argue this goes against yagni, because you don't need it (and you ain't gonna).
These abstractions are not there to support behavior that may exist in the future. They are added because, when things change (and they always do), it has ALWAYS been a lot more painful when they did not exist.
There is a very distinct difference between this and adding extra functionality or abstractions to enable change you think will happen.
This is an important difference.
Next time you are having a discussion and yagni is brought up, think about which one is driving what you supposedly don't need.
Tuesday, March 27, 2007
Xbox is Down!
What timing... not like I'd be playing anyway, being that I'm at work and have to paint my living room when I get home :(
Bonus Session
Friday, March 23, 2007
I am no electrician...
This couldn't be more wrong.
1. My dexterity skill is low, maybe a 9. I'm a klutz, have poor motor skills, my hand writing is illegible, the list goes on. This does not work well for wire manipulation. Actually this does not work well for manual labor in general.
2. Theoretical knowledge of electricity doesn't help much; it may even hinder you (it hinders me). In general, I like to explain everything, my husband calls this phenomena, Wendy's wack a** theories. I think coming up with connections and reasoning (more like randoming) is a lot of fun. With electricity, my theories are convoluted, usually involve Ohm's law, and are ALWAYS wrong.
3. I lack patience and after failing at wiring a circuit I start hacking away at it, just trying to make anything work... Constantly running back and forth to and from the circuit breaker. Like hacking code, this just wastes time and leads to poor quality. Not the best sacrifice when it comes to electricity in your home.
Recently, I've spent a great many hours changing a light fixture, outlets and switches around the house recently and I've come away with this knowledge:
1. A voltage tester is a worthwhile investment. I don't own one, but I really, really should. Its like coding without a debugger and with no TDD, a debugger would be quite useful.
2. Before you replace existing circuitry, study the current setup carefully before taking it apart. Otherwise, you will be confused by the 8 wires available when you only need 2.
3. Like working with other peoples code, working with others peoples circuits is scary, and things built a long time ago were built, well, oddly. Keep this in mind.
4. Refactor existing circuitry one switch, outlet, etc at a time. Its annoying, because you need to return to the circuit breaker a lot (unless you live on the edge), but at least you are always in a working state and you know when you broke your circuit.
5. If you are replacing an outlet with two pairs of wires, it is either powered by separate circuits or powering something else. You can check the hot side of the circuit to see if the bridge connecting the top and bottom is there -- if it is, then the bottom wires are being powered by this outlet, and you don't need to remove the bridge on the new outlet. If its not, remove the bridge on the new outlet. If you get this wrong, things will break.
6. Having a pair working with you is priceless. They can call 911 for you. And I was told this afternoon that your dog doesn't count (unless it knew how to call for help).
7. No matter how annoyed and frustrated you are, its never a good idea to do one more quick "test" without turning off power at the circuit breaker.
If I approached circuitry like I approached software, I would be a much better electrician! I suspect applying agile and xp methodologies work very well for all home improvements. I hope I remember this tomorrow morning!
Wednesday, March 21, 2007
DevTeach here we come!
Scott Bellware put together an excellent Agile track, and its going to be a great event.
If its not on your schedule, you're not thinking about missing a conference that features speakers as exciting as Oksana and me, are you?
Tuesday, March 20, 2007
I'm an abstract thinker
I see connections and patterns in everything, and I spent a lot of my early development days building frameworks. This was fun. At one of my previous jobs, I built so many frameworks, they created an unrelated (successful) product leveraging the frameworks from the original (also successful) product. There was a third, but I wouldn't call that as successful; its scope and complexity were too large and initial requirements were unrealistic (though I do think a poor developer is working on it and cursing me at this moment, sorry Eli).
I digress...
At Oxygen, we don't build frameworks, we use other peoples. In the beginning of my career I used many c++ libraries and frameworks that made my life more difficult than if I wrote the code myself and I stayed away from using other people's code -- it never did exactly what I wanted, it was buggy, and I had to take time to learn how to use it.
However, Kris and Luke are really good at finding the right frameworks and learning how to use them. This makes using other people's code a lot more approachable and I've grown to love some, like Castle.
Here are just a few reasons to use other people's frameworks:
1. The code evolves for you
2. Luke and Kris will figure out how to use it*
3. Respect from peers who use the framework (oh, you use castle, you must be extra cool and smart! -- I don't know if this happens in real life, but you never know)
4. Common language between developers
5. Global reduction of rebuilding of the wheel (wouldn't it be great if we shared all our code?)
6. You don't have to rewrite it when you change jobs
Here are some reasons to write your own:
1. It works exactly how you want to and you can change whatever you want (yeah, you can do this with open source, but I'm lazy and don't want to work in other peoples stuff :P)
2. You don't need to learn how to use it
3. Its fun
4. Pride of writing something cool (this can be misinterpreted as stubbornness or vanity so I would leave this one on the down low)
5. You could contribute it to open source and be super nice and cool :)
6. It doesn't exist
*You don't necessarily need someone named Luke and/or Kris on your team, just someone who's patient and interested in learning how to use other people's work :)
Whats in a name?
As developers, we put the definition of a class in its name. Its a good practice. It enhances readability. Its a difficult skill to master, but important.
While a good tool for readability, it is not a substitute for documentation or a complete way of understanding a class' responsibilities or interactions (tests work great here). Even if a class is named well, it can still be misinterpreted and we enter a dangerous path when we rely on names alone.
English can't be taken too literally and what means something to someone means something completely different to someone else. I'm not sure English will ever be enough context to understand a class... With resharper, I'm a big fan of ctrl-b (go to definition), ctrl-alt-b (go to inheritor) and ctrl-alt-f7 (find usages), this is a quite a useful and quick way to explore code and can take even less time than analyzing a name!
The other day I read some bizarre, but entertaining and artistic naming conventions and I found readable and more enjoyable... interesting idea; I wonder if it would ever catch on :)
Monday, March 19, 2007
Depressing blog?
I understand why they feel that way.
In the spirit of agile, I write openly about our shortcomings. In many companies people are reprimanded or even fired for pointing out issues internally, forget about posting them publicly.
I would not show weakness in our agile group if I were not confident in our teams spirit, devotion, intelligence and adaptability. We all love and appreciate the agile practices and I feel very lucky to work with such a talented group.
Agile is a great tool, but its difficult. It takes effort. Its frustrating. Like anything worth doing, you have to work at it. And like anything you love, sometimes you write about why its so great and sometimes you need to write about why its so difficult.
Wednesday, March 14, 2007
where do the bugs go?
We're all excited about Ript and want to share it with our friends and family. This gives us extra drive to complete the list of stories left for release!
This drive coupled with the lack of time has become evident in a recent spike in bugs and refactoring cards. The goal of the current sprint is stabilize the application, because we ended our last sprint with an unreleasable application. So, our burndown for the sprint included every known bug in application.
Our burndown looks something like this:
Sprint goal: Stabilize application -- fix 18 open issues
Bugs fixed so far: 26
Bugs left: 16 (I told you that last release was unreleasable!)
Because our goal is stabilize the application, we're treating the bugs as stories and adding stories to the sprint as bugs are found.
How did we get here? We are all profession, strong developers who are very committed to quality...
What went wrong?
Well... we've been "finishing" stories when they aren't really "done."
This isn't happening because we are lazy or over worked or don't understand the requirements, but because we are so desperate to move forward in the project.
When you have a 2 week iteration, even if you don't spend all 2 weeks on the project, you want to finish 2 weeks of work. Especially after a few weeks of enterprise work that take up more than 55%...
Enough explaining why we have bugs...
What was this post about anyway? Oh yeah... making bugs stories...
I had an ah ha moment the other day when I was thinking about where bugs belong in the sprint backlog. As a developer and a user of an application, I don't want any bugs. Our customer proxy may want features before bugs are fixed, but we may want to fix bugs before adding new features, because the bug could be a smell of a bad design or some needed refactoring... basically prioritizing bugs difficult!
Have you seen this bug rating system before (or something similar)?
Priority 1: Application crashes, no work around, data corrupted/lost
Priority 2: Application crashes, work around OR bug, data corrupted/lost, no work around
Priority 3: bug, no data corrupted/lost, no work around
Priority 4: bug, data corrupted/lost, work around
Priority 5: UI interaction, nuisance, no loss of data or work
This makes prioritizing bugs easy, but there are a lot of times a priority 5 issue, which is usually considered releasable, could be the downfall of an application. Meanwhile there could be a random crashing issue that occurs on one machine that gets fixed first because it is priority 1... not to mention, its so random it takes days to track down (there goes an entire sprint!)
Not only do these make little sense for prioritizing your sprint, they also offer no help when it comes to quantifying the impact of bugs on the teams velocity...
Introducing my new system of bugs:
Rules:
1. All bugs are stories
2. Like other stories, they are prioritized by the client and estimated by the team
3. If a bug appears as a direct result of a story completed in the sprint, it is added to the sprint and impacts velocity
4. Every sprint there is a small timebox to fixing/investigating bugs that the client hasn't included in the sprint (this doesn't affect velocity and the sprint should be planned accordingly)
5. Although the client prioritizes the backlog, the developers should feel confident about their codebase and may request bugs get fixed ahead of higher priority stories
What do you think?
The main idea is that bugs, like anything else, need to be user facing and should impact your velocity and sprint planning.
Like some other things, bugs happen :)
Tuesday, March 13, 2007
xkcd
Some of my favorites:
fun with resistors
sometimes math is useless
pair tactics
Thanks Robert!!
Monday, March 12, 2007
Continuous Integration, revisited...
Oxygen was setup for continuous integration before I started, so I know the "how" it works, but not the "why."
Before I started, I never had continuous integration setup (wow, I didn't know what I was missing!), so I don't know if my previous organizing methods would have worked so well... (even if I did really like them)
On to the point...
We use subversion for source control and have a build server running CruiseControl. We try to keep the build machine clean, so we're confident we have the project dependencies under control. The build machine does not even have Visual Studio installed -- just the .NET SDK so our projects can be built on the command line.
As for the development tree, its pretty simple:
1. Project Root
a. lib (Oxygen libraries)
b. tools (3rd party libraries) -- references like mbunit or rhinomocks and tools needed to build (like nant, msbuild...)
c. src (project source code)
There are some other folders in the root, but they are specific to the project, like documents or media... All references are to assemblies in lib or tools, never the GAC, this minimizes dependencies that need to be installed on the build server.
The only other file of note in the project root is our build file, which is a NAnt script. This script has several targets, like compile, unit-test, setup-dev-environment, install, cruiseconrol, etc (such a pain to write, but well worth the effort!) The cruisecontrol target, compiles, runs tests, builds installers, deploys installers, runs metrics, sends us result emails and has our bunny tell us updates.
So, "D", I hope this satisfies your curiosity about our development tree! If you have more specific questions, please let me know :)
Wednesday, March 7, 2007
Sprint Planning
During sprint planning we review the user stories in our backlog. For our enterprise projects, Salim, our SCRUM master, keeps track of the stories and priorities and the rest of the developers usually know whats going on too. For the new product development our client proxy, Ilio, manages the backlog, which is always well thought out and organized.
Before the review, the developer's knowledge of the stories is anywhere from nothing to very familiar. The more unfamiliar we are with the stories, the more painful our meeting.
Makes sense, because unfamiliarity and uncertainty go very well together, and uncertainty, while unavoidable, makes for long conversations and design talk. Too many unknowns during one sprint review makes us desperate to end the meeting.
The meeting is suppose to go like this:
1. Salim reads a story card
2. On the count of 3 we hold up an estimation card (very easy, easy, medium, hard, very hard and unknown)
3. Salim writes down the estimation
4. repeat
This process repeats until we've estimated more than an iteration of work.
Seems pretty simple, right?
Except, it only happens that smoothly when:
1. The story and solutions are well known
2. Everyone is focused
Sometimes the process is more like this:
1. Salim reads the story card
2. Ilio is asked to explain what it means
3. Ilio explains the story
4. Someone disagrees with Ilio about some behavior on the card
5. Ilio explains the logic again (he's so calm its amazing) and if necessary goes to Bob, our user interaction guru
6. Salim asks if people are ready to estimate
7. Someone answers, "what story are we doing?"
8. The card is re-read
9. On the count of 3 we hold up an estimation card
10. There are only 2 estimations that match, the others range from easy to question
11. The highest estimation explains their reasoning
12. The lowest estimation explains theirs (unless they changed their minds)
13. Salim asks if we want to re-estimate
14. On the count of 3 we hold up an estimation card
15. Kris or Luke make a final decision if we don't agree
16. Salim writes down the estimation
17. repeat
That took a lot longer to read, no? Believe me it makes the meeting take a lot longer too!
Does this make you think we're disfunctional? I think we'd be disfuctional if it always went perfectly... That may sound odd, but its conversations like these that bring interesting design discussions, find issues we missed, discuss user interactions we don't like, etc. These are important conversations to have.
When planning gets filled with unknown stories, we'll have 15 minute meetings each day to discuss stories for the next sprint. This helps, but is difficult too, because its another meeting to fit in during non-war room hours and there is very little time as it is...
I think we all decided that we'd rather have one long day of meetings (which we're having anyway) and a slightly more painful sprint planning than think about sprint planning every day of the week.
At the end of it all, we just want to code :)
Tuesday, March 6, 2007
Development tress and continuous integration...
Well, its war room hours and I haven't had a chance to respond, so this post serves as a reminder, that yes Oksana, I will respond... back to coding :)
InternalsVisibleTo
Testing internal methods comes in handy quite a bit:
1. Testing things that you don't want other assemblies accessing
2. Testing state machines or some other context of a class that you wouldn't otherwise expose
3. Using partial mocks
So, how do you let your test assembly access you internal methods?
Its quite easy, first you'll need your test assembly to have a strong name. Once thats done, you need to add one line to your CUT's AssemblyInfo.cs file.
[assembly: InternalsVisibleTo("TestAssembly, PublicKey=yourpublickey")]
For those of you used to 2003, you give your assemblies key files in the properties of the project and not in the assembly info :)
Saturday, March 3, 2007
Failing at TDD
But I was thinking about this statement on the way home and this isn't true. Even after I understood how to test, my classes under test would outgrow their test fixtures because I wasn't in the habit of writing tests first or the tests were too rigid to change or I just wanted to get something to work really quick without having to write a test... a little extra code here and there eventually leads to a lot of failing tests, ignored tests, ignored assemblies and then total failure...
A few years ago I was lucky enough to have lunch with Bob Martin and we had a long talk about discipline. I would argue that this is the most important attribute for test development (he really knew what he was talking about, how little I knew then).
I finally considered myself successful in TDD when I had several projects that were test driven, and continued to evolve test driven as well... i.e. I was finally successful when my tests were refactored with the rest of my code, my tests continued to drive change and it wasn't painful.
Hope you had fun at code camp
Thursday, March 1, 2007
Killswitch Engaged tonight!
The show comes during a tough week because I'm still adjusting to my training schedule for team in training and Oksana and I have been working late for our Code Camp presentations. I'm still looking forward to it though!
Tuesday, February 27, 2007
Targeting 1.1 with VS 2005
Now setting up only 1.1 references is one thing, but enforcing 2.0 supported features, such as generics, to cause build errors, will only happen when you build with 1.1. This is not supported by default with 2005. However, a nice group of people have created a tool to do just that!
The tool is called MSBee and you can download it here
MSBee creates a new build target for the 1.1 framework. You need to add this target to your vs project file in an import node:
<Import Project="$(MSBuildBinPath)\MSBee\MSBuildExtras.FX1_1.CSharp.targets" Condition=" '$(BuildingInsideVisualStudio)' == '' AND '$(TargetFX1_1)'=='true'" />
You can easily edit your project files in visual studio from the right click menu -- unload the project, then edit the file.
Tada! You now have a 1.1 build target in VS 2005!
But you want to integrate this with your build server and your NANT script?
Here is a snipet to execute the msbuild target:
<exec program="${msbuildLocation}">
<arg value="${csprojFile}" />
<arg value="/t:Rebuild" />
<arg value="/p:OutputPath=${buildDir}\" />
<arg value="/p:Configuration=${build.solution.config}" />
<arg value="/p:TargetFX1_1=true" />
</exec>
Enjoy!
Sunday, February 25, 2007
First Group Ride Outside
I learned something new:
My fancy running sneakers that provide excellent air circulation aren't so good for cold weather biking... my feet were like bricks... I didn't fall off the bike, I fell when I got off the bike because my feet were so numb!
Otherwise, I was a little slow, but I finished and it was fun :)
If you didn't already know, I'm training for 2 century rides as a fundraiser for the leukemia and lymphoma society in the memory of my father, who I lost in 2004 to leukemia -- please help my campaign here
Wednesday, February 21, 2007
XNA Content Builder
You can get it here
Thank you!! And thanks Kris for sending me this link :)
Monday, February 19, 2007
losing to a girl
I'm not so good at multi-player gears (I must say I do rock the single player campaign though!), I don't completely suck, but I like to play, laugh and have fun.
Although most of the guys I play with are cool, a lot can't control themselves and eventually say "you sound cute" or ask "are you hot?" Its flattering, but a reminder that even in this faceless video game, I am different.
Being hot isn't so bad, right?
Tonight was different. I was playing with chicks who were kicking ass. The guys we were playing with got mean, and it was different than anything I'd encountered.
They were mad.
Their egos had been bruised.
They had the ultimate insult, they were beaten by a girl.
After a while, we mixed it up and I was on the team with the most outspoken guy.
When we started playing, he said that one of the other girls was an easy kill. I said "Considering its her first time playing, she's doing awesome."
He wasn't expecting that.
At the end of that round, he said "Hey this is your first time, you're doing really well, are you having fun?"
And she was really quiet and shy and said "ummm... yeah..."
When the game started he asked, "Why did she sound like this was the worst experience?"
My reply was simple, "because you're being so mean."
He was very surprised and asked how. I listed the insults he had been spitting for the past 30 minutes... and he said "I didn't say any of that."
But the conversation ended, the round was over.
Sunday, February 18, 2007
Oksana, where are you??
Getting all the achievements in Madden 06
Just to start -- you will not get game achievements until the game is completed, so don't get discouraged, they'll be there
Really freakin' easy:
Win the superbowl:
1. From main menu go to franchise mode, start a new franchise
2. Select every team
3. Simulate preseason
4. Simulate regular season
5. Simulate wildcard
6. Simulate superbowl
7. tada -- you won the superbowl!
Look at the history book
1. From the main menu, go to franchise mode
2. Select history book
3. Go to any page
4. tada -- you got an uber lame achievement!
In game achievements:
If you do the following, you will get all the game playing achievements, save win a franchise game Note, this will be the most cheesy video game experience of your life.
Notes:
a) At any time in the game, check your current status by pressing start, then clicking down on the right thumbstick, then pressing down on the right thumbstick -- this will give you passed and rushed yards. This gives you the activate RS card achievement.
b) Don't bother doing anything special or control players -- just select plays. The only exception is passing -- if you choose who to pass to, you'll complete passes better.
1. From the main menu, start a new regular game, make the quarters 9 minutes long to make sure you have enough time to get all the achievements. I had 5 minutes left in 4th quarter by the time they were done. Choose rookie difficulty.
2. Choose the Colts for your team -- they rock
3. Choose the Browns for your competitors -- they suck -- make sure the computer is driving or it doesn't count
4. Every time you are on defense, choose based on play type, man blitz -- any one, this will get you Four Sacks in One Game and it may take a while. Just keep at it.
5. In the beginning offense, choose based on play type, shotgun passes when you're far from the goal and then switch to quick pass. You will keep getting touch downs, very exciting. Do this until you reach 350 passing yards for the achievement.
6. After you get the 350 yards, now you need to focus on rushing. The colts aren't quite as good at rushing, but I found starting with Counter to get close to a down and getting the down with an inside hand off. worked most of the time. Since I was so far ahead in points, I never kicked on the forth down and just went for it, this worked most of the time. Do this until you reach 200 rushing yards in your stats and then you can spend the rest of the game loafing
7. Thats it, play until the clock runs out and you'll have 480 more achievements when its all done -- Enjoy.
More difficult:
30 Years of Franchise
This one is time consuming and basically you sit around and wait for simulation. You really only get this one if you have 3 hours to waste and an achievement whoring husband. I take full credit for the theory of getting this to work on simulation, but he gets credit for actually doing it...
1. Start a new franchise -- don't use the one from the superbowl -- it won't work for 30 years!!!
2. Select the worst team with the biggest cap -- he went with the Titans, but didn't look through the list that well. If you choose someone like the colts, after a few years, you'll have to start doing some manual labor cause salaries will get too high and it sucks.
3. put on some good music
4. get a laptop, ds, split screen tv, another xbox....
5. Simulate, repeat
6. Yay, you're done
Win a Franchise Game
1. Start a franchise, select the Colts
2. Simulate the franchise week by week until you play the Browns
3. Use coaches pick for defense and offense, but use passing plays for offense, unless you have less than 3 yards, then you can use a rush.
4. This will be a little more tricky cause franchise is Pro mode only
To completely cheese out, you can adjust the AI during the Pro game. Its under the game play settings when you press "start" during the game. Use the right trigger to select between offense and defense and between you and the computer. Bump your attributes up to 100 and the cpus down to 0. This will make you win the game easily -- doesn't matter what plays you use.
Good luck and don't get too bored!
Saturday, February 17, 2007
Back to training
I felt like I was speeding along, but it took exactly 28 minutes to complete the 10 miles. Not quite as fast as I wanted to go...
The last two minutes I slowed down and cooled off... but the bike was tricky... it seemed that in those 2 minutes, I went .7 miles... sneaky bike, moving just as far even though I was pedaling half as much.
I wonder how far I really went?
Xna, graphics and team edition, oh my
So, I needed to break my rules a little...
New rule:
Graphics can live in an Xna library, that is neither living in the main game solution or the GameShell exe assembly.
In Xna, graphics are just content loaded from disk built as "xnb" files, so they only need to be in the TitleLocation of the StorageContainer when your game is running (this is where the ContentManager Loads). If you look at a project containing pipeline content, you'll see an ItemGroup node:
<ItemGroup>
<Content Include="Image.jpg">
<XNAUseContentPipeline>true</XNAUseContentPipeline>
<Importer>TextureImporter</Importer>
<Processor>SpriteTextureProcessor</Processor>
<Name>spriteImage</Name>
</Content>
</ItemGroup>
So, if you wanted to, you could create an Xna library project and then just add content to it manually by copying images into a child directory and adding xml to the project file. Or, you can keep Express edition open for your graphics and build them as you need them.
So, now I have a graphics library with all my assets. Once it builds, I need to put these files in my debug directory if I want to use them, but as one of my stipulations, I didn't want to have any post build steps, so I made the following modifications to my Program.cs class in GameShell:
for (int i = argIndex; i < args.Length; i++)
{
string graphicsPath =
Path.Combine(args[i], @"bin\x86\Debug");
if (Path.IsPathRooted(graphicsPath) == false)
{
graphicsPath = Path.Combine(projectPath, graphicsPath);
}
foreach (string file in Directory.GetFiles(graphicsPath))
{
File.Copy(file, Path.Combine(debugDirectory,
Path.GetFileName(file)),
true);
}
}
Basically, I added the logic to the GameShell that any additional parameters to the application are graphic resources. If the resources aren't rooted, there are libraries inside the main project directory. So, this just goes through all those folders and copies all the files -- simple.
Still with me? This is a long one... BTW -- I have never even tried to run this on my xbox, I do all my coding on my laptop on my long ass ride home on the train so I take no responsibility for your boxes :P Also, if someone came up with a better solution, please tell me cause I'm without internet on this long ass train ride!
Yay, so now I have all the assets I need :)
Or so I thought...
I couldn't load any of these xnb resources. The content.Load was only working with resources in the bin directory GameShell :(
Reflector to the rescue...
I found this bit of code, used to determine where to find graphics:
public static string TitleLocation
{
get
{
string text1 = string.Empty;
Assembly assembly1 = Assembly.GetEntryAssembly();
if (assembly1 == null)
{
assembly1 = Assembly.GetCallingAssembly();
}
if (assembly1 != null)
{
text1 = Path.GetDirectoryName(
new Uri(assembly1.EscapedCodeBase).LocalPath);
}
return text1;
}
}
As you can see, its using the entry assembly (or calling assembly) to determine the location of content...
So, back to my original solution with the app domains... oooo I was being clever :P
A few minutes of hacking in some appdomain code and voila, the game will only execute in the main appdomain... d'oh -- wasn't being clever after all, but I think I got that out of my system.
Returning back to my graphics copying code, I decided the simplest approach is copying the assets into the TitleLocation in Program.cs. A slight modification to the file and finally, I'm debugging my Game in Team Edition with Graphics!!!
And there was much rejoicing... yay.
I think I've put off writing some games long enough :P