Showing posts with label software. Show all posts
Showing posts with label software. Show all posts

Thursday, July 30, 2009

Respect, don't trust: A little philosophy on the emotional life of the software team.

I haven't heard much talk about the emotional world of the software engineer, so I'll offer some late night ruminations on the topic.

The deliberate conflict between the engineers making software and quality assurance fascinates me. Here's why: While software engineers passionately try to make things work, QA engineers diligently work to prove that the software is horrible. If you put this behavior in another context there would be pain and strife. One person persistently pointing out someone else's flaws. How rude!

In a healthy team, this is not discord, it is work and sometimes even fun. It's beautiful to watch. The graceful dialectic offers some life lessons and gives me hope in human nature. We can be honest and frank, we can seek truth and scorn "white lies". We can do this respectfully, with passion, and without hurt.

Here is how software teams make this work.

Respect, don't trust 

QA never trusts development. A QA who trusts the developer would believe -- without empirical proof -- that the software works. That would be silly. QA's role is to aggressively and skeptically to prove the developers' work flawed. QA seeks to prove. While mistrusting, the QA team respect the developers intelligence, creativity and passion. Respect does not require trust in this relationship - It a relationship where mistrust and skepticism are possible, emotionally, because of the teams' strong mutual respect. 

Trust and faith are good for your wife and your religion. Anyone or anything less than these gods deserves respectful skepticism. 

Be fearless of mistakes - mistakes and corrections make the world work. 

There are few situations in life where products must be right the first time. This is true in assembly line manufacture and live virtuoso performances. Most of life is about mistakes and corrections. In a conversation, if we don't understand each other, we dialog and correct. If I don't catch a fish on the first cast, I can try again. Bikes constantly wobble a little as we balance from side to side.  

Productive software engineers don't fear mistakes. Engineers who fear mistakes hoard their work for weeks, keeping it to themselves. Finally, pride satisfied, they throw an overwhelming amount of change of the wall to QA. QA needs weeks to validate - the cycles take many times longer than they should and the product is invariably late, rough in the places that need to be smooth, and polished in places where it doesn't matter.

Software works better when the developer fearlessly checks in small pieces of work continually. A little due diligence - send to to quality assurance. The right things are fixed and fast. Back to the physical world analogies: A bicycle with small wobbles moves fast. The only bike that does not wobble is probably smoothly falling over. 

Back to respect: The developer can fearlessly check in because of the respect offered from QA. QA respects the daring of the developer showing her raw work to the team.

( The final product is of course flawless. Mistakes the customer sees are bad. I'm talking about the early life of software. Typically, we make hundreds or thousands of bad builds before we make the final release build. So, the customer sees the one "right" build, but the life of software development is a story of continual mistakes and corrections. )

A defect in software is not a defect of the author.

Defect systems offer a powerful emotional tool - we don't talk about the systems this way very often. I rarely hear, in software, QA walk up to an engineer and say, "You stupid lout. You made the CSS wrong and the now the border of this table clips the text."

Instead, the developers does there best to make something pretty. QA digs into it, fines a tiny flaw, and files a bug report into a bug database. The bugs get prioritized, assigned out and fixed. The separation means that the flaw never gets personal. The author can handle a statement like "There is a flaw in the software" much better than "You broke the software."

All software teams think defect systems are essential for organization - I argue they are also essential to avoid getting distracted by the emotions of making mistakes.

Tuesday, July 28, 2009

My Simple 3 Step IIS Setup System

This is my secret system for getting IIS to work on new computers (servers or desktops). Permissions, default identities and user interfaces change with each OS. I'm not going to write a book on all the things that can go wrong with IIS. I've got got 3 simple steps that shake out different types of problems very fast.

Audience: Software Engineers or QA Engineers don't want to reconfigure IIS more than a few times in a year. The folks in operations probably have a powershell script to do this.

Three steps and a tip

Starting point. New server? Installed W7 on your development machine and it isn't serving up your site any more? It's all the same problem.

Step 0: Start with a sanity check and Run Compmgmt.msc (computer management). Do you see Internet Information Services? Any suspicious icons?

Step 1: Drop a static web page into the site and browse to it.a For example: <html><body>Hello</body></html>

Step 2: Drop an a very simple ASPX page into the site and browse to it. Example: Response.Write("Hello"). My dynamic test page is a more complex than this, to report host header, virtual directory, and so forth.

Tip: Verify this site in multiple browsers. Even better, chose a browser with a “Private” mode. In some configurations (or mis-configurations) you might send NTLM credentials and the site impersonates your credentials, masking permissions problems.

Step X: What you don't want to do.

Don't debug basic IIS setup problems in a complex site. For example, daptiv will have a few dozen confounding factors: from special handlers to run of the mill database and storage configurations to several choices of authentication.

OK, here are some details.

But really, don't clutter up your mind by memorizing these. They are examples. IIS 6 configuration does not resemble IIS 7 configuration.

Step 0 problems - check the obvious

Are you missing an IIS component? It's easy to do. The components vary from release to release. On Windows 2003 x64 – installing SMTP requires CAB file hacking and you might have hacked it wrong.

By opening IIS Management, you verified that the metabase is readable. I've got a short list of known ways to corrupt the IIS MetaBase and longer list of unknowns. SysPrep, for example, can someimes mangles the machine keys IIS uses to secure its data. BTW, I don't know how to resolve metabase problems. The only method known to work without an overpaid IIS Consultant nearby is to uninstall IIS and reinstall.

Step 1 problems – static page

Is the web site running? Check IIS management console. The website might also be stopped because configuration isn't valid. Two sites on port 80 with the same url? Invalid application pool? These problems are easy because event log tells you the problem.

Permissions? If I can't see the static page on a new IIS instance, it is usually because of permissions at the virtual root. I get this often, as I’ll create webs at odd paths such e:\src\3\root\SecretProduct\www, and refuse to make IIS_IUSRS an admin on my box. Permissions should be easy: Add users one at a time in a sensible manner until it works. Remove them until it stops working. Now you know what needs access.

Account names will change between IIS, windows, and .NET versions. Typically I need to add permissions to the folder for:

  • Application pool identity – needs at least read access: My app pool usually runs as Network Service or a domain account.
  • The account used for anonymous access. (IIS_IUSRS or IUSR, IUSR_COMPUTERNAME, or something fancy)

Step 2 problems – ASPX fails

The ASP.NET extension might not be enabled. This is configured in entirely different places on IIS 6.0 (Web Service Extensions) and IIS 7 (ISAPI and CGI restrictions). It's disabled by default on some versions of Windows, ever after IIS is installed.

Of course, this is a good time to run aspnet_regiis.exe. If any identity (Application Pool) is not the default, use aspnet_regiis.exe -ga. Use aspnet_regiis -i with total abandon.

Summary

That's all I need to know to get most web servers running IIS. There is a basic troubleshooting principal here: start simple and build up facts.

Saturday, August 02, 2008

A deep dive into COM, ApartmentStates and VS 2005 unit testing

I’ve had some adventures in what is clearly “Legacy” code recently, and had the pleasure on learning all about STA vs MTA apartment states, and what this means for unit testing in VS 2005. Let me warn you that this is an obscenely technical post. Mainly, I’m posting it because I’m certain to forget the details next week. If you want something non-technical, go ogle my children.

Summary: Do not use MTA, there are good reasons STA is the default.

Update 2008-08-19: OK, if you are in a hurry, do use MTA. Consider creating two test projects, one for STA and another for MTA. Getting the tests to work in STA is "proper", but not easy.

Scenario: An eager TDD developer wants to create unit tests for a .NET application that uses COM component, for example, a Microsoft office application. The woes you experience are described in threads such as this (MSDN forums) with misleading answers.

Side note: A test project where you are referencing COM objects and MS office applications is not a unit test project. Unit tests cover functionality with no or few external dependencies. You are writing very valuable functional or integration tests in the style of unit tests. You still need true unit tests.

What is happening?

Usually, a COM component such as an MS Office Application is heavy and slow to create. You want to share an instance to avoid creating it for each test. Reread the document for apartment states carefully. Note that the default, “single threaded apartment”, does not allow you to share a COM object across threads. VS 2005 test executes test initialization, assembly initialization, and tests on different threads. Ergo, you can't create a COM object in test initialization and use it (directly) in your tests if you run with Single Threaded Apartments.

Also note that STA is the default. Many COM components will not work with Multi Threaded Apartments. For example, the .WebBrowser control in .NET 2-0. Even the trivial .NET file open dialog requires STA.

More background: about COM runtime callable wrappers.

One answer to this is to execute your tests with Multi-Threaded Apartments. Having tried this, I strongly discourage it. A few hours of test support wrappers can get around the STA problems. MTA problems:

1) A lot of the COM components require STA threading. You’ll get errors such as “ActiveX control '8856f961-340a-11d0-a96b-00c04fd705a2' cannot be instantiated because the current thread is not in a single-threaded apartment.”
2) If the actual application will run in STA, a test using MTA is an invalid test. Assuming this is an automated integration test (as it interacts with heavy COM dependencies, it is not a unit test), you want it to exercise the code in a realistic manner. A different threading model will lead to false failures and successes.

My solution:

To start with, build this out with Test Driven Development. What do you need to do? You need a test initialization method that creates some COM objects, you need to access objects during tests, and clean them up afterwards. So start with the following :
  1. test class that will demonstrate the ability to "share" a scenario using COM objects.
  2. a test initializer
  3. two test methods that access the objects. Interestingly, the second test failed until I got it write. Order didn't matter.
  4. a test cleanup method

Problem: I don’t want to create a heavy office application for each test.

Solution: While you can't share COM RCWs across threads, most heavy COM objects such as MS Office applications allow you to get an existing process via Marshal.GetActiveObject(). I create an Office Application wrapper and a builder responsible for its creation. The tests call something like Builder.GetApp(). This gets a new COM RCW that might be an existing MS Application process or a newly launched Application.

Also note that even in Single Threaded Apartment state, you can share these wrappers and COM RCWs in a thread static variable.

Problem 2: What about all those other smaller com objects? I want to set up a scenario during test initialization with lots of cells or ranges, then use those little COM objects in my tests.

Solution: Stores a way to find the COM object during test initialization (store the cell location, a task uniqueid, or something like that), rather than the actual COM RCW object. Then write a utility that provides a quick way to get the COM object for the test from the static variable. For example Wrapper.GetCellForActiveBook (identifier).

Problem 3: But GetActiveObject doesn't always work ...
Right, you can't always use the GetActiveObject trick for all types of objects. I'm still working on this. For example, I haven't been able to create "document" level objects (MSProject.Project, Excel.Workbook) in test initialization yet, and grab that specific instance in the tests (on a different thread). Solutions include.

  1. For some reason, the ActiveObject (ActiveWorkBook, ActiveProject) property gives me a document that I can create in initialization and use through the tests. This limits the test suite to a single document, and there is a risk that another document becomes active, breaking the test. I'm uncomfortable with this ... but using it successfully.
  2. Create a new instance per test. Use helper methods to repeat scenario initialization. While a little slow, I'm prefer this approach, as it keeps the tests clean.
  3. Create a document in initialization and save it to disk. Pull it from disk for each test - this creates the COM RCW on the test thread. I haven't pursued this approach.


Finally, be careful to close those COM objects! It's often harder than you think.

If you are playing with COM from .NET, read and understand Marshal.ReleaseComObject and the very handy Marshal.FinalReleaseComObject. In the solution I describe, you will have to carefully manage MS Office application instances or your test suite will leave dozens (hundreds?) of open MS office applications.

ReleaseComObject is very necessary after working with something like WindowsInstaller.Installer.OpenDatabase. The author of these automation interfaces neglected to implement the close method for database objects, while the C API requires that you close the database. Consequently, ReleaseComObject is the only way to avoid leaking resources and leaving a lock on the MSI file you read.

Other details - In a case where I am either creating a new Office app or stealing an existing process with Marshal.GetActiveObject, it's important for the wrapper to know if it created the Com object (you need to close the application process that you created) or stole it (you should only release the com object).

In summary, I hope I can't remember the details next week.

Anyway, there is lots of complexity in closing COM objects. For this reason, I package all heavy com objects in wrappers. A Builder pattern handles creation, and the IDisposable pattern handles cleanup. Easy. Once done, I can forget about this whole sorry technical deep dive by next week, and think about more important things.

Tuesday, July 04, 2006

Tenzing on Trike

He may seem like the rough type, but he's got a soft spot for flowers. Posted by Picasa