Monday, September 28, 2009

Joel Spolsky Has an Interesting Idea of Duct Tape

Joel's recent post reveals a strange notion of what a "duct tape programmer" is.

His first description is of someone who uses C++ templates and multiple inheritance to describe has-a or does-a relationships--someone who knows just enough about inheritance to see how type inheritance can save time, but not enough about contracts to foresee the brokenness of this design. He then goes to a design patterns meeting. I am glad he is going to a design patterns meeting to learn about object composition, and all that's wrong with this lazy, hacky implement-via-inheritance antipattern. I say this template-abuser is a duct tape programmer. Mr. Spolsky calls this kind of programmer an astronaught, and says the duct tape programmer does _not_ hack in this way.

Next, Mr. Spolsky says, "You see, everybody else is too afraid of looking stupid because they just can’t keep enough facts in their head at once to make multiple inheritance, or templates, or COM, or multithreading, or any of that stuff work. So they sheepishly go along with whatever faddish programming craziness has come down from the architecture astronauts who speak at conferences and write books and articles and are so much smarter than us that they don’t realize that the stuff that they’re promoting is too hard for us."

Multiple inheritance per se is simple; the complexity is in actually using it. Templates (in general) are the mainstay of the copy-and-paste abuser--the extremist duct tape programmer--but I think Joel is speaking here of C++ templates. A practical and effective programmer will make effective and proper use of generics (assuming static typing is also being used). Therefore, even with all their problems, C++ templates are a necessary part of good C++ programming if you insist on using C++ to begin with. Who would use COM for anything other than working with legacy code? Multithreading is a fact of life sometimes, but should not be used for performance alone without sufficient reason. What "faddish programming craziness" do practical programmers "sheepishly go along with"? No answer to this question is explicitly given in the original article, but Joel does proceed to tear about ideas that have passed into common usage.

Finally, the portrays unit tests as an enemy to releasing on time. First he quotes Zawinsky, saying unit tests "sound great in principle. Given a leisurely development pace, that’s certainly the way to go. But when you’re looking at, ‘We’ve got to go from zero to done in six weeks,’ well, I can’t do that unless I cut something out. And what I’m going to cut out is the stuff that’s not absolutely critical. And unit tests are not critical. If there’s no unit test the customer isn’t going to complain about that." Then he says "we’ll forgive [duct tape programmers] if they never write a unit test."

Technically, you can ship without unit tests. There are 2 alternatives:
1. Don't test. This way, when you accidentally encounter a bug, it is harder to find the source. Also, you risk the customer complaining about bugs that are shipped. Worse yet, you spend all that time to build a piece of crap. Such a waste of time is both immoral and unfulfilling.
2. Test manually. The disadvantages here are more time spent testing (not less!) and having a harder time finding bugs.

Skipping unit tests is like using duct tape. Using unit tests is _wise_.

Tuesday, August 25, 2009

Apples on Pasta?

Apples have a sweetness similar to that of tomatoes. "Self," I thought to myself one day, "if I add an apple to this tomato sauce, will it round out / complete the flavor of the tomato?" So I tried adding an apple to a simple pasta sauce, and replied to myself "Self, this isn't quite right... but you're on to something!"

After a few iterations, here's what I have come up with: Saute the following to the desired doneness and serve over pasta:
-diced apple. Golden delicious has worked well so far, but something less sweet might be more desirable.
-some onion. Red and white work well. I do recommend one of the more "onion-y", less sweet onions to contrast with the apples.
-some green bell pepper. Again, contrast with the sweet apples.
-just a little diced tomato. Remember, apples are the star of this show.
-sea salt, red pepper, and oregeno to taste.
-Optionally, also add red wine vinegar and/or olive oil.

Apple on pasta is as easy as any other pasta dish, but offers a very different flavor and texture.

Thursday, May 7, 2009

eventId's 1334, 1089, and 1000

Today, I encountered a problem where my ASP.NET app would not run on my machine. I would get "Server Unavailable" in my browser, and eventId's 1334, 1089, and 1000 in the Application Event Log. The same application ran smoothly on a fellow developer's machine.

Many Web resources suggest using aspnet_regiis.exe enable ASPNET to access the GAC, but that was not my particular problem.

Instead, we have a legacy Visual Studio 2005 Web Application Project (not to be confused with a "Web Site") with unusual configuration requirements: It has to run in a virtual directory located at the root of the Web site. Something tells me this is redundant.

Anywho, steps to make it work included:
  1. Publish to the desired folder (C:\inetpub\wwwroot for example).
  2. Set both the Web site root and the virtual directory root (in IIS) to that folder.
  3. In VS, on the Web section of the WAP's properties, under Servers, select "Use IIS Web server".
  4. In the project URL, put "http://localhost/MyVirtualDirectory".
I hope this helps someone.

Friday, May 1, 2009

First Project with NHibernate 1: Lessons Learned

The ministry where I work recently completed the first revision of our new Money And Marriage Web site, which we built using several new methodologies and tools, one of which was NHibernate. The team put me, the still-green associate developer, in charge of creating a Data Access Layer (DAL) to house the great ORM beast, taming it if you will. One of the interesting requirements of this DAL was that it should completely protect the app-at-large from all persistence concerns, as well as _not_ expose NHibernate in case we decide to use a different ORM instead. Therefore, the app-at-large would not know of NHibernate, but the person writing the app-at-large would have to refer to the *.hbm.xml (NHibernate mapping) files to understand what MyUnitOfWork.Get(id) would do, precisely.

Because we are still new with NHibe, our code is probably not as useful of a solution as you will find elsewhere; thus I will not misguide the reader with such, but will instead share what we learned:
  • For any database, no matter how "legacy" it is, an ORM tool is far better than no ORM tool, even if you still find yourself hand-coding some methods to custom-massage Buisness Objects between the BL and the ORM.
  • For new or (or perfectly kosher old) databases, you can simply use ISession.Get(id), Set(obj), etc. without customizing anything on a per-type basis. Yes, this simplifies your DAL by an order of magnitude! That is, if you have n types in your BL, the number of methods in your DAL goes from O(n) to O(1).
  • NHibe is rather awkward for working with legacy databases. Be prepared to massage data yourself (unless you simply know more NHibernate tricks than I do and can handle insane / exotic situations).
  • Before committing to NHibernate (or any other complex tool for that matter), hold some tech talks / lectures with all techies involved to not only get everyone on board, but also to brief everyone in how to properly use the tool. There are a few instances in our code base where we did certain things like handling relationships between entities the manual way, using ID's of related entities in our BO's rather than using references to those entities and letting NHibernate work its relationships magic. Most of these instances were my doing in working with a legacy database. More knowledge of NHibernate would have helped.
  • Unless you are an uber-brilliant programmer who can simultaneously keep client code from caring about persistence concerns like transactions while still providing a DAL API allowing client code to express persistence requests at the domain level, you should let the app-at-large control transactions. I see no way around it.
  • You can let the app-at-large be blissfully ignorant of connections, and maybe even caches, except that it should keep track of what objects are and are not attached (persisted).
  • Some ORM-related concerns, such as the fact that you cannot attach two different instances representing the same entity to the same session at the same time, will still percalate up to the client code, unless you invent an ingenius scheme to prevent that.

Saturday, April 11, 2009

Pictures Are Worth More Than Words

When desiring to open a door, if it has a handle, I pull. If it has a panel, I push. This is true regardless of any sign that may be on the door that says "Pull" or "Push"--I obey the real-world object before I even read the sign.

I find it funny that most hole-in-the-wall stores that have a door with a handle and a sign that says "Push" also have 1,000 other signs and posters and other information that I will not see as I walk in. If there was just one big, obvious sign that said "Push" and no other distractions, I might push on the door to walk through. But I will always pull the handle otherwise. Then one of the store employees comes to open the door for me and says "You have to push on it," and I feel stupid.

Resulting lessons include:
1. Real-world objects, images, and conventions trump any amount of text warning users of exceptions to rules, unconventional behaviors, and other gotcha's and pitfalls.
2. Every bit of text is a distraction from something, or itself will be overlooked. Less is more. Words and phrases > complete sentences.

Take your car, for instance. Does your panel read:
You are travelling at approximately 57 miles per hour. The current engine temperature is approximately 120 degrees Fahrenheit. Your lights are on. ....
Obviously, this would cause problems.

I hope most people know this already. This post is for those who do not. Please, for the love of your fellow humans, make extra effort to make things easy to use, removing the need for long text to read through. Usually, this will save both you and your users time, and keep your users from feeling embarrassed because they don't know how to open a door.