Showing posts with label programming. Show all posts
Showing posts with label programming. Show all posts

Saturday, March 05, 2011

Book Review: Dependency Injection in .NET

This isn't so much a review as just a note that I read Dependency Injection in .NET by Mark Seemann and found it pretty helpful in clearing up some of my confusions about dependency injection frameworks.

I already was aware of the basics of constructor injection, but was experiencing some pain around problems like constructor over-injection and lots of 1-1 mapping between interfaces and implementations. This book explores ways to fix these issues and many others.

Here are some topics the book covered that I really appreciated:

  • DI patterns, including the different types of injection, and Ambient Context
  • DI antipatterns, including Service Locator
  • DI refactorings, including Abstract Factory and dealing with cyclic dependencies
  • Object composition, including implementing the composition root for common types of .NET applications
  • Interception

I particularly liked the way the Interception chapter went over Decorators and how to configure them, and then moved into how to implement and configure interception.

Tuesday, October 27, 2009

Misadventures in DDD With Not-So-Ubiquitous Language

Lots of people have been talking about DDD (Domain-Driven Design) lately, and my friend Tom just discussed it over on his blog in the article Refactoring Toward Deeper Insight. So, I thought I'd share one way not to do DDD.

Once upon a time, shortly after the big blue book was published, I saw it in the store and thought it looked interesting. I bought it and read through the first section about knowledge crunching and ubiquitous language. And it all made so much sense—where I worked, the business analysts and software developers already worked together to crunch knowledge into a domain model they both understood (or so I thought). The trouble was, even though when they talked together, they used that language, when the developers actually wrote the code, they used their own. Why? Well, I didn't know—mostly just because we usually thought our names for things were better, I supposed. Trying to keep the language the same just wasn't something we'd thought about much.

So, I decided that on the project I was working on, we'd start doing DDD by using the names from the business language for the classes in our code. I didn't discuss it with the business people, since I didn't think it involved them much—they didn't need to change their language, we developers just needed to use it.

Everything went fine for most of the project. Then, a couple days before release, the business decided that they wanted to rename one of our core domain concepts—and that was okay, right, because it was just changing a few labels on a few screens?

And that's when I learned that if you want to do DDD, it helps to get buy-in from the business.

So, happy DDD-ing everybody—because I do think lots of the ideas are great and worth exploring—just make sure you let the business know what you're up to and you'll avoid my rookie mistake.

Monday, October 26, 2009

Estimating is Like Measuring the Coast of Great Britain

Earlier today, Liz Keogh tweeted this, which I couldn't agree with more, as long as she's saying what I think she's saying:

Thinking about fractal estimation—estimates grow as scale shrinks—and wondering what dimension current projects have.
A while back, every time I started doing technical estimates for a release, I began to think more and more of the illustrations along the side of this Wikipedia article: How Long Is the Coast of Britain? Statistical Self-Similarity and Fractional Dimension.

The situation was, that as a developer in a waterfall process, when I was trying to estimate how long it would take to code something, even with the requirements supposedly "fixed," unless I examined the code I was proposing to change in so much detail that I was basically writing it—and that's not estimating anymore—I'd always miss things that would make coding take longer than I'd estimated. In essence, there were always craggy little details that upon actually writing the code, became significant or added up with others to become significant.

Now, I know that if your architecture and code are clean, this should happen less. But I still think it's generally true that until you actually write the code, you really don't know how long it will take, and the amount of time will usually be longer than you think when analyzing it at higher levels.

Then, I thought of this problem again when I attended a talk on Scope Budgeting. There, the general issue is that in Agile, if you write a user story, estimate it, put it in your backlog, and only elaborate it when you pull it back out to implement it, you may find that the size of the story grows at elaboration-time.

According to Liz's fractal estimation rule, that makes complete sense and should be expected. I agree. Whenever I have worked with user proxies to move from general functional requirements to specifics, the estimate has always increased. The amount of work needed to address all the details we discover always grows beyond the original estimate. If we made commitments based on that estimate, the only way to keep them is to prioritize and remove some of the details.

I can think of a few ways to address this problem, if we want to consider it to be a problem:

  1. Just be aware of it and deal with it as needed, which is a lot better than not being aware of it at all.
  2. Start measuring it, so you can factor it into your future estimates. This might be taken care of by comparing estimates to actuals and factoring that into future estimates. You'll need to decide whether the time it takes to do this is worth the return, though.
  3. Move toward techniques like Kanban that de-emphasize estimation. Whether or not this works for you will depend on your current situation, but it's always worth questioning whether you're estimating because you truly need to or just because that's what you're used to.


Update Sept, 2010:

Sunday, September 06, 2009

Pair Programming for Flow

A while ago, I attended the workshop Debugging Pair Programming by Matt Wynne .

Matt gave the same workshop at Agile 2009. That website has a good write-up of how it worked.

After the first part, where we discussed how to convince different developer personas why they should cooperate with pair programming, we moved on to the second part, where we paired up and interviewed each other about good experiences pair programming or collaborating in other ways.

I was paired with Tom ten Thij , who said something really interesting about pair programming.

He said that pairing can make it easier to get into flow.

This was completely the opposite of what I'd heard before about pair programming. Before, I'd heard it can be difficult to achieve flow while pairing—that you might even have to give up on flow, but that the increased code quality is probably worth the trade-off.

But Tom's point was that while pairing, you're less likely to procrastinate getting into your coding task. In other words, having a partner helps force the "activation energy" that flow activities can require.

So, as long as your pair works well together, and you keep everyone engaged by doing something like ping-pong programming, you might be able to achieve flow after all.

Tuesday, June 16, 2009

IronRuby & rake-dotnet

I'm back from attending a talk on IronRuby and rake-dotnet.

I haven't had much any time to play with Ruby, so a lot of what I took away is pretty basic:

  • You don't need to use parentheses when calling methods. That contributes to the magic you see when it's used for writing business-facing tests and DSLs.
  • IronRuby is much closer to 1.0 than I thought, only about a month away.
  • Theoretically, you can use it to do Cucumber and RSpec, though that wasn't quite working in this particular demo at the moment.

Anyway, it was interesting. Thanks to Gojko Adzic for organizing it, and Michael Delaney and Peter Mounce for presenting.

Monday, May 04, 2009

Notes from Gojko Adzic's "What is FitNesse and Should I Use It?"

Last week, I went to What is FitNesse and Should I Use It? by Gojko Adzic.

I was struck by the difference between two of his slides:

And a slide from a different talk about FitNesse that I'd attended a week earlier:

To be fair, Gojko said that it's very easy to hook lots of different kinds of testing into FitNesse, and he had been as guilty of it as anyone else.

Here are a couple other good things I picked up from Gojko's presentation that I hope to put to use:

  • Focus on "what" and not "how". Don't try to translate test scripts into FitNesse—that's "how" and can lead to having a lot of similar or duplicated setup code. In fact, if you find yourself writing many similar tests, you're probably focusing too much on "how".

  • To keep your tests as living documentation, separate them into to main categories: tests for the current release and tests for previous releases organized by feature. At the end of each release, move the tests from that release into the other category.

Sunday, April 26, 2009

Writing Unit Tests Should Be Fun

I picked up on "writing unit tests can be fun" vs "writing unit tests is boring" over at Mark Needham's blog.

Besides excellent points that Mark makes about the pair-programming game and that Uri Lavi makes about unit-testing code posing many of the same challenges as production code, there's another reason unit testing should be fun: flow.

I think a lot of developers know what it's like to experience flow while coding and know that it's a good thing.

It turns out that two factors that help produce flow are clear goals and direct and immediate feedback.

Writing tests first absolutely helps you clarify goals and receive quick feedback when you're coding.

Interestingly, flow activities can also require "activation energy" to get into them. (See Chapter 5 in Finding Flow by Mihaly Csikszentmihalyi.)

This is one reason why you might find yourself being a couch potato in your free time instead of working on your favorite hobby, even though you know if you got your butt off the couch and did that hobby, you'd actually enjoy yourself more.

Similarly, sometimes when I'm at work and I need to code something, I find it hard to pull together that activation energy needed to write both the tests and the code.

But I can say that when I do, it's almost always totally worth it.

Friday, April 24, 2009

Notes from ThoughtWorks London Geek Night: Startups That Innovate

Last night I went to the ThoughtWorks London Geek Night "Startups That Innovate". I know there are some people who wanted to go who couldn't because there wasn't enough space, so I'm going to share what I remember. And I aplogise for everything I remember wrong.

The first two speakers were Giles Thomas and Jonathan Hartley from Resolver Systems, who talked about founding Resolver and the technologies they use. Here's what I remember:

  • To get your startup going, you need people who can fill three essential roles: (1) Technologist/Developer (2) Rainmaker (3) User Advocate.
  • They use IronPython and it works well for them. At first, they picked it because it looked like a good language for rapid prototyping. When it came time to switch over to a "real" programming language, they decided that they liked IronPython so much that they wanted to keep using it.
  • They use PyUnit for unit testing. Some people in the audience thought PyUnit might not be mature enough, but Giles and Jonathan said they were able to make it work.
  • They use an internal Python-based DSL to automate acceptance tests.
  • They are an XP shop.
  • Developers really do pair program pretty much all the time, except for spikes.
  • With pair programming, it's true that you don't get as much of a flow experience as you would programming alone, but it still seems to work pretty well.
  • As an XP shop, they try to keep their working hours sustainable. That might be different from what you see in other startups.
  • One lesson they learned was: Don't go into stealth mode—it would have been useful to get user and community feedback earlier.
  • Another lesson they learned: Release earlier. It took them around 2 years to release v1.0, and again, it would have been useful to get user and community feedback earlier
  • Interns are a great resource for startups.
  • (Jonathan used vi instead of PowerPoint to present his talk, which was cool.)

The last speaker was Martin Dittus from Last.fm. Here's what I remember:

  • Last.fm started to having trouble scaling all of the updating of data that results from scrobbling. They realized that they didn't need to do it in real time and switched to batch mode.
  • They are using Hadoop to do this.
  • One of their interns, Klaas Bosteels, wrote Dumbo to help make working with Hadoop easier.
  • As a startup, they had trouble affording Business Intelligence tools, so they built them themselves.

I'm not very good at tweeting events, but some other people did better: London Geek Night tweets.

Also, I saw a list of upcoming ThoughtWorks Geek Nights while I was there. I think there were three in May and one in June. Here are links to the ones I could find links to:

Saturday, April 18, 2009

Links: Agile Practices and Rebuilding Legacy Codebases

Over on Code rant, Mike Hadlow recently put out an article I liked: Agile practices are not just about management.

Besides being good reading, it also reunited me with an article that I've been wanting to re-find for a while now, but couldn't quite remember the source: Uncle Bob's The Big Redesign In The Sky. There are so many good points there about rebuilding—or rather not rebuilding—legacy codebases that you should go read it right now if you haven't. And if you have, you should go read it again, just because it's that good (even though it gratuitously uses the number 42).

Wednesday, April 15, 2009

Sometimes It's Easier to Stick With What You Already Use

For the upcoming London Open Space Coding Day, we're thinking about working with messaging in enterprise applications.

That reminds me of the lesson I learned the last time I tried using MSMQ: Sometimes, it's easier to stick with what you already use.

The scenario was that we were going to import some record updates from an external system. Once we grabbed them from the external web service, we wanted to queue them up and bring them into our system.

"Aha!" I thought. "We need a queue. This is what MSMQ is for. We'll use that."

Unfortunately, this import is a very, very small piece of an application that otherwise is very, very largely database-driven. Ever since implementing the import, every time someone needs to test it, there's baloney about the MSMQ queues not getting set up right or not having permissions or some other junk. And that's ignoring that when we first coded it, we found out that lots of our developers didn't even have MSMQ installed, and they all had to install it.

On the other hand, if we'd set up the queues to be stored in the database, there would have been no problem. In our application, if you can't access the database, you're not going anywhere. In fact, in the next release, another developer needed a queue. He stored it in the database and never had any of the problems I did.

Now, this isn't a story about how you shouldn't use MSMQ. Instead, it's a story about how if your application is largely based on one technology, and to implement a single feature, you have a choice between using that technology and another one—where both will work pretty much equally well—you might want to seriously think about sticking with the one the rest of the application is based on.

On a related note, a few months ago, when I was at the February meeting of the London .NET User Group, Gojko Adzic and David de Floriner gave a talk on NServiceBus. It looked like an interesting way I might have been able to interface the message queuing so that I could have swapped out MSMQ with our SQL Server database without needing to change code.

Sunday, April 12, 2009

Egoless Programming: Admitting When You Should Be Shot

Mark Needham brought up Egoless Programming on Twitter the other day, reminding me of one of my favorite times I got to admit "I did this, including the mistakes."

It looks much funnier as an xkcd-style cartoon than it did in real life:

(Disclaimer: All of the drawing above was copied directly from xkcd, because I can't draw at all. But the words are mine—well, mine and those of the co-worker who wanted to shoot me.)

Tuesday, March 31, 2009

Looking Forward to Alt.Net London Beers Tonight

I'm looking forward to attending Alt.Net London Beers tonight to see what social gaffe I can commit next. My favorite from last time was when someone asked me if I "was you-switch" and I looked at them blankly, wondering what they could possibly mean. In retrospect, I knew that there were several developers there from uSwitch, and I was just being asked if I was one of them. But at the time, I completely forgot, and the best my mind could turn the question into was something like... "Do you use switch statements? Because you know, in the OO-world, that's not cool." My secret is that I probably have used switch statements in the past year. But I didn't like it. Really.

Seriously, though. It's a good event. I made it to the last two, where we discussed Robert C. "Uncle Bob" Martin's SOLID Principles and "avoiding the big rewrite," including ideas from Michael Feathers' book Working Effectively With Legacy Code.

Friday, January 09, 2009

Debugging Deadlocks in SQL Server Sucks Less These Days

I'm debugging deadlocks in SQL Server 2005. I hate debugging deadlocks.

The good news is that debugging deadlocks in SQL Server 2005 sucks a lot less than it did in SQL Server 2000.

Bart Duncan expresses the difference well:

Turn on trace flag 1222 with "DBCC TRACEON (1222, -1)" or by adding "-T1222" as a SQL startup parameter. This trace flag is a new trace flag in SQL 2005, a much improved version of the tried-and-true -T1204. If you’re running SQL 2005, you should be using 1222 instead of 1204 unless you have deep-seated masochistic tendencies. Alternatives to 1222:
  • If you are using SQL 2000 or SQL 7.0, you’ll have no choice but to fall back on the older -T1204.
  • There’s a "Deadlock graph" Profiler trace event that provides the same info as -T1222. Feel free to use this instead of -T1222 if you’re on SQL 2005. But don’t waste your time with the "Lock:Deadlock" and "Lock:Deadlock Chain" trace events that are in SQL 2000, as they provide an unacceptably incomplete picture of the deadlock.

Hooray!

That quote is taken from the first part in an excellent three-part series on debugging deadlocks in SQL Server 2005:

Also, there's Basic SQL Server Deadlock Debugging over on Tog's Blom.

I also like the Troubleshooting Deadlocking section in Inside Microsoft SQL Server 2005: Query Tuning and Optimization by Kalen Delaney.

Wednesday, April 23, 2008

Avoid Resharper 4.0 Nightly Build 775

If you're trying the Resharper 4 beta nightly builds, I just thought I'd warn that I had trouble with build 775 from 11 Apr 2008, which is currently the newest build marked "Works here". When I installed it, the Resharper items, such as "Find Usages", were disabled in the context menu. I found the issue discussed in the Jetbrains forums, and they said they fixed it in a later build.

Now, I'm using build 780 from 18 Apr 2008, and it's working well for me so far.

Friday, December 21, 2007

Customers Do So Care What Your Code Looks Like, They Just Don't Know It

Over at Coding Horror, Jeff Atwood claims "Users couldn't care less whether the underlying code is pretty."

Baloney.

The article sparked lots of responses noting that customers do care, because ugly code is often hard to maintain, and code that is hard to maintain often leads to more bugs, as well as to longer implementation times both for bug fixes and for the new features that keep you ahead of your competition.

But yes, in a short-sighted way, Jeff is right. Customers often don't appear to care about quality until something bad happens.

  • They don't care about the bad quality of cheap toys from China, until they find out they are hazardous to their children's health because the toys contain too much lead.
  • They are so enamored with the bling of their SUVs that they don't think about quality until news headlines start shouting about rollovers.
  • And, they don't care about ugly, unmaintainable code until your product has a showstopper bug and it takes you forever to fix it, because you can't figure out how to. Or, until a competitor has a feature that your customers are dying for, but that it takes you forever to match, because you can't figure out how to integrate it into your ugly codebase.

Whoops! It turns out that customers care about quality after all.

So yes, customers do care, it's just that they are so dazzled by promises of features and the potential for bargains that sometimes they forget—until something bad happens.

As always—and I think this may really be part of Jeff's point anyway—there has to be balance. Take the time to write maintainable, quality code so you don't end up in the "whoops!" situation. But on the other hand, don't stare at your code editor, re-refactoring for hours on end just to write a masterpiece.

Friday, September 22, 2006

What Is The Best Way To Use Immutable Atomic Value Types With XML Serialization?

Here are two items from Effective C#: 50 Specific Ways to Improve Your C# by Bill Wagner:

Item 7: Prefer Immutable Atomic Value Types

Immutable types are simple: After they are created, they are constant. If you validate the parameters used to construct the object, you know that it is in a valid state from that point forward. You cannot change the object's internal state to make it invalid. You save yourself a lot of otherwise necessary error checking by disallowing any state changes after an object has been constructed. Immutable types are inherently thread safe: Multiple readers can access the same contents. If the internal state cannot change, there is no chance for different threads to see inconsistent views of the data. Immutable types can be exported from your objects safely. The caller cannot modify the internal state of your objects. Immutable types work better in hash-based collections. The value returned by Object.GetHashCode() must be an instance invariant (see Item 10); that's always true for immutable types.

Not every type can be immutable. If it were, you would need to clone objects to modify any program state. That's why this recommendation is for both atomic and immutable value types. Decompose your types to the structures that naturally form a single entity. An Address type does. An address is a single thing, composed of multiple related fields. A change in one field likely means changes to other fields. A customer type is not an atomic type. A customer type will likely contain many pieces of information: an address, a name, and one or more phone numbers. Any of these independent pieces of information might change. A customer might change phone numbers without moving. A customer might move, yet still keep the same phone number. A customer might change his or her name without moving or changing phone numbers. A customer object is not atomic; it is built from many different immutable types using composition: an address, a name, or a collection of phone number/type pairs. Atomic types are single entities: You would naturally replace the entire contents of an atomic type. The exception would be to change one of its component fields.

Item 25: Prefer Serializable Types

Prefer adding serialization to your types when practical. It should be practical for all types that do not represent UI widgets, windows, or forms. The extra perceived work is no excuse. .NET Serialization support is so simple that you don't have any reasonable excuse not to support it. In many cases, adding the Serializable attribute is enough

But, are immutable atomic value types serializable to XML?

Here is the immutable atomic address structure, pretty much taken straight from Wagner's book:

[Serializable]
public struct Address
{
    private readonly string _street;
    private readonly string _city;
    private readonly string _state;
    private readonly string _zip;
 
    public Address (string street, string city, string state, string zip)
    {
        _street = street;
        _city = city;
        _state = state;
        _zip = zip;
    }
 
    public string Street { get { return _street; } }
    public string City { get { return _city; } }
    public string State { get { return _state; } }
    public string Zip { get { return _zip; } }
}
And here is a class that uses it:
[Serializable]
public class Office
{
    private string _name;
    private Address _address;
 
    public Office() { }
 
    public string Name
    {
        get { return _name; }
        set { _name = value; }
    }
 
    public Address Address
    {
        get { return _address; }
        set { _address = value; }
    }
}
Now, here is some code that creates an Office and serializes it to XML:
Office office = new Office();
office.Name = "Chicago";
office.Address = new Address("1060 W Addison St", "Chicago", "IL", "60613");
 
XmlSerializer s = new XmlSerializer(typeof (Office), new Type[] {typeof (Address)});
s.Serialize(Console.Out, office);

And here's the output:

<Office>
  <Name>Chicago</Name>
  <Address />
</Office>

Where's the address information?

MSDN explains in XML Serialization Considerations:

Only public properties and fields can be serialized. Properties must have public accessors (get and set methods). If you need to serialize non-public data, use the BinaryFormatter class rather than XML serialization.

My Address properties don't have public set methods, and so aren't in the XML.

Now, I like the immutable type idea. It feels good and clean and right to me for things like Address. And Martin Fowler and Eric Evans agree—they both have descriptions of immutable value objects in their books Patterns of Enterprise Application Architecture and Domain-Driven Design, respectively. So, I really want to use the immutable value type idea. However, I'm going to start using these types over a web service. That means I want a good way to serialize them, where "good" is defined by James Shore in Quality With a Name as

A good software design minimizes the time required to create, modify, and maintain the software while achieving acceptable run-time performance.

And so, the question is: What is the best way to use immutable atomic value types with XML serialization?