- Consulting / Coaching
- Jeff’s Blog
Q. What’s “unnecessary complexity?”
A. Any code that doesn’t need to be there, or that is more difficult to understand than necessary.
Your system might exhibit unnecessary complexity if it contains duplicate code, abstractions that aren’t needed, or convoluted algorithms. Unnecessary complexity permanently increases the cost to understand and maintain code. We create it for various reasons, most of which we can begin to eliminate.
Time pressure. “We just have to ship and move on–we don’t have time to make it look nice!” You’ll regret this sadly typical choice later (not even that much later) when everything takes longer. Learn to push back when you know short-term time-saving measures will cost everyone dearly later.
Lack of education. To create quality designs that you can maintain at low cost, you have to know what that looks like. Most novices have little clue about how they are degrading their system. The concepts of cohesion and coupling (or SRP and DIP) are essential, but most everything you can do to learn about good design will pay off. Consider start by learning and living the concepts of Simple Design.
Existing complexity. The uglier your system is, the more likely that the average programmer will force-fit a solution into it and move on to the next thing. Long methods beget longer methods, and over-coupled systems beget more coupling. Incremental application of simple techniques (such as those in WELC) to get the codebase under control will ultimately pay off.
Premature Conjecture. “We might need a many-to-many relationship between customers and users down the road… let’s build it now.” Sometimes you never need to travel down that road. Even if you do, you pay for the complexity in the interim. Deferring the introduction of complexity usually increases the cost only marginally at the time when it’s actually required. When you choose the wrong unnecessary abstractions, it can significantly increase the cost to change to the right ones down the road.
Fear of changing code. “If it ain’t broke, don’t fix it.” Maybe we have the education we need, but we often resist using it. Why? Imagine you must add a new feature. You’ve found a similar feature implemented in a 200-line method. The new feature must be a little bit different–five lines worth of different code. The right thing would of course be to reuse the 195 lines of code that aren’t different.
But most developers blanch at the thought–that would mean making changes to the code that supports an existing feature, code that many feel they shouldn’t touch. “If I break it, I’ll be asked why I was mucking with something that was already working.”
Good tests, of course, provide a means to minimize fear. In the absence of good tests, however, we tend to do the wrong things in the code. We duplicate the 200 lines and change the 5 we need, and make life a bit worse for everybody over time.
I posted a response to a blog post entitled “Why I hate SCRUM daily standup meetings,” but it’s still awaiting moderation after a couple days. I’m impatient, so here’s my comment:
====== From: @jlangr ======
“On top of this, they need to setup a meeting to learn what my collegues are working on feels so wrong to me.”
Agreed. If you are a good team that already finds ways to get together and talk about what’s important, a formal meeting is a waste of time. Sitting in a common area where this can happen throughout the day can make it even less useful.
Having said that, it’s great starter discipline, and can be useful in environments where it’s not easy to get people together (I’ve been in places where I wasted way too much time trying to track people down or when my attempts to discuss things were rebuffed by people who were “too busy”). I’d start a new team on daily standups, but would push the team to find ways to eliminate the need for them once they got better at working together.
Also, most shops that run daily scrums and don’t get much out of them aren’t collaborating enough. It becomes one person reporting status, while the others worry about what they’re going to say when it’s their turn (because “that stuff” has little to do with what they’re doing). If that’s the case, you may as well revert to people sending an email with their status to the project manager, who gathers and emails a summary of what’s important to the team.
But…that’s not what works best in agile (or lean). See Stories and the Tedium of Daily Standups: What works best is real collaboration, which in turn makes the stand-ups far more useful and engaging. There’s also an Agile in a Flash card for that!
I’d love to hear more positive stories about stand-ups, given that most of the time I hear from people who’ve learned to detest them. Good or bad, how’s your stand-up meeting working for you?
I delivered a talk on “The Only Agile Tools You’ll Ever Need” at Agile 2011, and had a great time doing so. Most of the written feedback from the session indicated that people were very happy with the talk. Negative feedback, received from a handful or so of the ~60 attendees: It didn’t necessarily meet expectations based on what the session summary said. I apologize for that–I’d prepared the summary months before putting together the talk, and what I’d felt important to say changed during that time.
I also muffed a bit–I made a forward reference to the notion that task tracking is a smell, but didn’t quite fully close that thought out as I talked about limiting work in process. If it wasn’t clear, the key point was: if you minimize work in process, the need for tracking tasks in a software tool diminishes significantly.
I handed out index cards at the outset of the session, with the intent of gathering names so I could give out a couple copies of Agile in a Flash. But that’s boring! What else could I have people do with the cards (to bolster my contention that they’re wonderful tools)?
Aha. I gave the following instructions:
“I’m looking to get live feedback during my session. On one side of the index card, draw a big fat smiley face. If you’re happy with what I’m saying, or you think I’m making an astute point, hold up the smiley face. On the other side, let’s see. If you think the believability of what I’m saying is suspect, put something down to represent that. Hmm. Believability Suspect, just abbreviate that, and write down ‘BS‘ in big fat letters. Finally, put your name below the smiley face for the drawing.”
I got a number of smiley faces throughout, but no BS cards. One guy looked like he was about to hold up a BS sign, but changed his mind–probably the one guy who hated the talk. So, my takeaway is that the silly mechanism worked in terms of getting positive feedback–but I suspect that it’s probably a bit too intimidating for most people to challenge a speaker with negative feedback.
I recently responded to a poster at JavaRanch who was asking about how stories are used in agile. I think a lot of people use the word “story” improperly–they use it in the sense that a story is a feature. “I built 10 stories into the product.” No, a story is a discussion around a feature. A story is also not a card.
While this may seem like a nit that I’m picking, I believe misuse of the word “story” has led to unfortunate insistences, such as rigid formats for cards that capture feature conversations (and I’m going to stop calling these cards “story cards,” which isn’t quite as bad a term, but it does help reinforce the wrong things).
(Most of the rest of this post is taken directly from the exchange on JavaRanch.)
“Story cards” are simply placeholders, or tools. The word “story” is the important thing here. A story is something we tell people; the card is simply a reminder, a summary of that oral storytelling. A card is a convenient medium. I suppose I’m thankful I don’t hear about “story whiteboards.”
Story cards (I tried… it’s not easy!) are not artifacts! Once you complete work on building a feature, the card is meaningless. You might think you could use it to track what had been done in a given iteration, but a 5-word summary of a several-day conversation (between customer and developers and other folks) scribbled on a card will not likely be meaningful to anyone six months down the road.
Instead, we get rid of the conversation piece, and replace it with something that documents how the system behaves once that new feature is in place. The best form for that document is a series of well-designed acceptance tests that anyone can easily read and understand. (See our Agile in a Flash card on Acceptance Test Design Principles for a definition of well-designed.)
Acceptance tests are the closest analogs to use cases (a tool popularized almost 20 years ago now), but with slightly differing granularities. The name of an acceptance test can map to the goal, or name, of a use case; it can also map to a much smaller slice of functionality. This is because features in agile are intended to be very small, taking only a day or so to complete. So someone might tell a story: “allow users to filter sort results by age.” That’s likely not an entire use case, it’s an alternate path on a larger use case.
Otherwise, the focus is the same: Jacobson said you could produce user guides and documentation from well-written use cases. The same can hold true for acceptance tests (with a little assembly work), which have the vastly superior quality of eternal accuracy: As long as all your acceptance tests pass, you know that they describe how the system works.
Stories, on the other hand, are just conversations, and the memory of all conversations eventually fades from memory. The cards act as great tools while the story is in progress–they help us track things and remind us what we were talking about, but other than that, we should just recycle the cards once we deliver the corresponding features.