Archive for the ‘development’ Category

Thoughts on the iPad

Saturday, May 1st, 2010

I love the fact that the iPad has no preferred orientation. I find myself often turning it upside down. I have the apple cover and with the stand up and upside down it sits really nicely on the lap when I’m sitting on the couch.

The keyboard is definitely usable for typing. In fact I love the fact that it autocorrects as I type. I loved this on the iPhone and it is even better on the iPad. We’ll see if I still like using it for content creation in a week or so.

Consuming media is compelling. It’s beyond the first flush of awe that you get when you use it for the first time and it’s the sort of thing that will only get better as the apps mature.

The NPR app is a killer app - I’ve read and listened to more content there today than in a long time. And i can see it being like a paper - the sort of thing that becomes part of the daily ritual, listening to a story as I have breakfast, or get ready to go out.

The battery life is superb. I’ve been using it all day and it is still only at 50%. When that happens on the iPhone I start looking for a power outlet. I guess it’s going to take a while for that habit to die.

For all the amazing apps that are out there (and they are *amazing*) there are some rough edges and false starts. Since no one has actually had the chance to use one before developing the apps it is amazing how good they are. I can’t wait to see what the next generation apps are like.

Now for some observations on the apps.

Omnigraffle is still much like a mouse driven app. The gestures associated with drawing are not yet intuitive. This is going to take some experimentation, so despite the power of that app on the desktop I think the space is open for a competitor who gets it right.

Many websites display the old desktop versions on the iPad. So for example you get the desktop version of the BBC. Now it is great for reading those sites, but one great thing about the iPhone sites was that it forced sites to trim down the extra guff and concentrate on content. It feels strange to have a third of the page filled with an advertisement on the New York Times iPad app. And the BBC website is much nicer on the iPhone than on the desktop version. It will be interesting to see if people start optimizing their sites for iPad as they now do for iPhone.

The Magazine and newspaper apps are a revelation. It’s like the newspapers in the Harry Potter books (or the book in Neal Stephenson’s Diamond Age for the geeky) in that photos become videos, you can expand them, you can play them, all in place. It really does feel like magic. And it is surprising how much of the web is already accessible despite the lack of Flash. Flash is dead. Sorry Adobe.

So what about the closed nature of the iPad? Well I pretty much agree with what Joe Hewitt says as reported here.

It is all very well to complain that apple is closed and a walled garden etc. But like it or not, apple are inventing the future here. So unless you want to be the Lotus 123 of the touch era, you should take every opportunity you can to learn how this new platform will work. That knowledge will be transferrable in the same way that Microsoft’s learning from developing the early Macintosh versions of Word were. This is a brand new human computer interface, from the company that designed the last new HCI back in 1984*

* yes I know, the WIMP interface was developed at Xerox PARC. But the desktop metaphor, overlapping windows etc. were all Apple. And they brought it to market. It doesn’t count if no one used it.

- Posted using BlogPress from my iPad

Microsoft’s recursive search

Tuesday, August 12th, 2008

Finding things on Microsoft’s site is an exercise in frustration.

Here is a case in point. I am looking for a fix to a problem caused when trying to open a VSTO (Office) project in Visual Studio. I get a helpful error that says “The project type is not supported by this installation.”. There are a few places around the web that talk of this problem and suggest ways to fix it. I follow one link to an MS web page:

http://www.microsoft.com/downloads/details.aspx?FamilyId=A2151993-991D-4F58-A707-5883FF4C1DC2&displaylang=en

Unfortunately this is an old link, and the page no longer exists. MS use their flagship Live Search to give me a set of alternatives. Unfortunately, and insanely stupidly, the very first link that comes up as a result of the search is the same link that I was trying to go to in the first place — the one that doesn’t exist.

Sigh.

Interestingly when I put the same search into Google and follow the link, I get the same ‘not found’ error but the first link on the page is not the recursive search link.

Is that Martin Fowler?

Monday, August 4th, 2008

I was showing http://cuil.com to a colleague — I like the three column view — when I noticed this rather unexpected image appear when I did a search for Martin Fowler : http://www.cuil.com/search?q=martin+fowler

So who is that youngster that appears? Did Martin clone himself a few years back and is starting to accustom us to his new younger avatar?

Martin Fowler\'s clone?

The photo does not appear on the linked page that I can see, and the image link itself (http://www.cuilimg.com/imgsrv?i=020410:620124592474843) doesn’t help. But there is a clue in the categories on the right hand side :

Eureka!

So here is the solution - it seems that Martin has actually been a fictional character all along, and indeed Patterns of Enterprise Application Architecture itself is a subtle astroturfing campaign to add credibility to a character in an english soap opera.

Who knew? :-)

The Apple iPhone has no ‘off’ button

Tuesday, May 6th, 2008

Update: So it turns out iPhones *do* have a way to turn it off but its just that I at least never read the manual (because you don’t need to) and didn’t discover it. My main point is still interesting I think, that you don’t need it enough to want to find it. As usual I will leave my mistake here for the word to read. :-)

Apple get usability. By now there must be very few people who don’t realise that. But in case there are some out there, lets just look at a couple of examples that struck me recently.

I own an Apple iPhone. I bought it in San Francisco, unlocked it myself, and have been using it constantly for the last month. It is without question the best phone I have ever used. Not perfect, for all the (3G etc.) reasons that you can read about on the blogsphere, but it is pretty damn close, and certainly closer than any other I have owned, including my abortive attempts to get to like “smart phones” in the past (Palm, Nokia etc).

But it struck me after a month of using the thing that there is a glaring missing feature. In fact it is so obvious I’m astounded that I haven’t noticed it before. There is no ‘off’ button.

There is a button on the top right that you press to lock it - the screen turns off but little more.

There is also a ‘be quiet’ button on the left side, above the volume control. Hit it, and the phone gives a little shake and then remains silent. This is equivalent to choosing the ‘Silent’ profile on a Nokia or other phone.

The most amazing thing about the lack of an ‘off’ switch is that you never notice it. Hey, it took me a month. And when do notice, and start to think about it, you realise that you never actually needed an off button anyway. The only reason that I used it on my old phone was because I was going into a meeting, and I wanted to make sure I wasn’t disturbed.

But this shows the reason that Apple doesn’t need it. With my old Nokia, ‘Silent’ was a profile, and I had to trust that the people who created that profile did the right thing, and turned all the sounds and notifications off. That they didn’t think “You know, this feature that I’m working on is really *really* important — no-one would *ever* turn it off — so I’ll give an ever so subtle beep even in Silent mode”. I don’t trust anyone to do that. I don’t trust *myself* to do that if I’m developing software.

So what Apple does is say: “No, this isn’t an option, its not a profile that you can customise. No questions asked — hit this button and I won’t disturb you. Not at all. Never”. It is still a trust issue. But I trust that button. I trust it because it doesn’t feel like a software option — the button implies a hardware solution — a built in switch that kills the sound. (Of course I understand that in reality it is software, but trust is conveyed by the visceral physical click of that button).

Apart from wanting to make it silent, why would you ever turn off your mobile? These days turning off a mobile is like locking yourself in a dark room and calling out to your friends that you aren’t coming out. Life — or at least social life — stops [1]. So the Apple iPhone has no off button.

Another shorter example. I am writing this sitting outside the Apple store in NY. You know the one, the glass box on 5th Avenue. Every couple of minutes someone takes a photo of it. It is beautiful, ad the plaza that surrounds it is comfortable and popular and full of people sitting eating lunch. A shop that gives something back. Nice.

Inside the store, it is very busy, very crowded. Apple stores have the highest per foot profitability of any store here. But it is still cool and comfortable and a pleasant place to be. But it is quite noisy. So how do you sell iPods, which are ‘all about the music’ as Steve Jobs likes to say in a noisy environment?

I don’t know how other companies would do it, but what Apple do is load all the iPods on display with Bose sound cancelling headphones. These are the $250+ headphones that you see long distance travellers (like me) using on long haul flights to cut down the airplane noise and get some sleep [2]. Despite the noise in the store you really can hear the music, and the chaos of the store disappears when you put them on.

This is the attention to the user experience that has made Apple what it is. It is pleasant to visit an Apple store. It is pleasant to buy an Apple product. It is pleasant to use an Apple product. And it is why the Apple iPhone doesn’t have an off button.

[1] While writing this it struck me that the same is true of my laptop. I never switch it off, I just close the lid. And that makes me wonder if we will someday see a laptop from Apple that has no off switch?

[2] They are using the AC3 ones that sit on the ear, and I guess that is because a used over the ear headphone might feel unsanitary, whereas the on the ear design leads to less actual contact. They are not the battery operated ones though, I don’t know what exact model they are.

REST Podcast

Saturday, March 22nd, 2008

While in San Francisco recently for a meeting, a group of ThoughtWorkers got together to record some podcasts. The first has now been posted here:

In this two-part series, Martin Fowler, Chris Stevenson, Jim Webber, and Sriram Narayan discuss REST (Representational State Transfer). They touch on the history of REST, a detailed explanation, and examples. Additionally, they discuss programming with the Web today, modeling your resources, types, RESTful enterprise development, and reuse.

http://www.thoughtworks.com/what-we-say/podcasts.html

Fixing Broken Windows with Ratcheting

Tuesday, March 11th, 2008

Many codebases suffer from an accumulation of technical debt — small sub-optimal fixes and tactical decisions. Each of these probably made sense at the time, and we always intend to come back and fix them, but somehow never have time. Ratcheting is one technique that may help to address this problem.

The Problem

You are on a large codebase in a large team. The codebase hase been around for a while, and as always in these cases, has accumlated some technical debt. These are mostly simple things that would be easy to fix, but there are so may of them that it can be hard to see where to start. And since you are busy releasing new versions and working on new features, it is hard to find the time to just work on these trivial things.

But just leaving them is bad too - since this lead to an acceleration of problems. If there are 100 warnings, then 101 is not so bad, is it? If there are already 30 ignored tests, does it really matter if I ignore this test? These are the sort of simple day to day compromises that lead to a long term deterioration in code.

This is the boiling frog syndrome — where a small incremental change is not noticeable but over a long period of time there is a significant change.

Another example is build time. Over time our builds tend to get longer, and while today’s build may only be a second or two slower than yesterday’s, over a year or longer we may be looking at significantly slower builds.

Avoiding this is one problem. Another is fixing it when it has occurred, but you can’t take the development process offline to just fix the technical debt.

It is easy to say ‘the build should be no longer than 10 minutes’ but what do you do if it is currently 20 minutes? What do you do if you have hundreds of build warnings, or FxCop reports thousands of (mostly trivial) problems?

Ratcheting

A ratchet is defined as “a ratchet is a device that allows linear or rotary motion in only one direction, while preventing motion in the opposite direction.” — Wikipedia

What we are trying on our project is a software version of the ratchet. The approach is fairly simple, and consists of the following steps:

Identify a problem — Choose one of the issues that you have, and find a way of reducing it to a number. Examples are build time, the number of ignored tests, the number of enums, switch statements, code coverage or pretty much whatever you can count.

Stop it getting worse — This is the crucial piece. In every build, check the number, and compare it to the number in the previous build. If it is ‘worse’, then fail the build. Of course what ‘worse’ means differs for different metrics. Build time is worse if it goes up. Coverage is worse if it goes down.

Make it better (optional) — In this step you fail the build if the number doesn’t get better. I think of this as tightening the screws. I like to think of it as a reference to literally tightening loose screws on some kind of machine. But done badly it could be a reference to tightening thumbscrews to torture people. A tyrannical ‘architect’ doing this could kill team morale. On the other hand if the whole team agrees to it and chooses the thing to ratchet then it can be a positive reinforcement.

This means that every time someone checks in, they have to remove one of these items. It may be simple, as in fixing one build warning, or more complex, as in improving code coverage. It will affect productivity a bit, but only a little bit for each checkin. It makes sure that everyone takes responsibility for fixing the problems in the code. Done well, I think this can enhance the team.

Repeat — There’s a lot left to do. Choose another metric. Keep the previous ratchet in place, or you will lose the benefit.

Trying it out

On our current project, we have 85 ‘TODO’ comments in the code. This is classic technical debt. Who knows if these are still valid? We have turned ratcheting of these on in our build to test the idea. With a team of 7 pairs, it should only take us a few days to get that to zero. I’ll let you know how it goes…

China, and the Great Wall

Friday, December 21st, 2007

great Wall

I have been continuing the ThoughtWorks tour, and have finally made it to the China office, in Beijing. The office has just moved here from Xi’an, and so the Monday that I arrived was a busy one, with old friends re-connecting, and the office rapidly filling up. In fact, we have very little room left, and may have to start find new space pretty soon. Once I have a few more photos, I’ll post a gallery of office photos. It is pretty much along the lines of other TW offices, a large open space with flat ‘dining tables’ and a very fun, collaborative feel.I was lucky enough to get here in time for the ThoughtWorks Away Day.

On the Sunday we went to the Great Wall near Beijing. The gallery is here (I haven’t put these on flickr yet, since it s blocked by the great firewall. Sigh.).

Biking to Ooty

Tuesday, November 27th, 2007

I guess there are always a few things that we don’t tell our parents until after the fact. No, get your minds out of the gutter, I don’t mean that. I mean the sort of thing that mother’s don’t need to know. They would only worry for no reason, so let’s spare them that and fill out the details later.

This was one of those. Recently the ThoughtWorks India office went to Ooty for an Away Day. The Away Day is a weekend technical and cultural fest (basically it involves geeking during the day and drinking and dancing at night) and in India we generally bus to somewhere within a few hours of Bangalore and spend the weekend there. This year was in Ooty, which is a hill station about 280km from Bangalore, past Mysore.

The route takes us to Mysore on one of the nicest South Indian roads (divided higway with 2 lanes each side), through Bandipur National Park (home of Project Tiger) and up a spectacular road to Ooty itself (36 hairpin bends).

A few of us felt that this was too good an opportunity to pass up, so with the help of Royal Enfield we got together some bikes, and the 14 of us took off at 7am to bike the 280km. For anyone who has not experienced the roads here, that may sound like a fairly quick jaunt. In fact, it took us about 12 hours each way. But the trip was awesome, and well worth it.

We were supposed to leave at 7am from the Bangalore office, but due to various issues, we were actually only able to leave by about 9:30. We drove for about an hour through Bangalore’s insane traffic, and ended up stopping for chai on the outskirts, near Bangalore University.

Rest stop before Mysore. Sagar picked up the sugar cane from a load that had been left on the road after a truck tipped over. This is fairly common here, as many trucks are overloaded and top-heavy We saw 2 just on the way to Mysore.

Rest stop after Mysore.

Lunch outside Gudalpet. We were waiting for Dheeraj, who was involved in a minor accident in a small town near Mysore.

Chai on the edge of Bandipur National Park.

Waiting for us at the petrol bunk.

At the bottom of the hill, we thought “Maybe we should fill up?” but it was getting late, and we felt that we were OK. famous last words of course. As a result we had to wait around while Keshav went off to find us some petrol. Luckily we were at the top of the hill, quite near Ooty, and there was an excellent chai stall.

The view from the hotel in Ooty.

Playing cards, Sunday night in Ooty.

Ooty — waiting for people to wake up

royal enfield enginerepairing the bike, OotyPlaying Uno, while waiting for the bike to be fixed

Ooty — Mechanics shop - playing cards again.

Coming back on the Monday, we hoped to leave at 10am, but we needed to get one of the bikes seen to first. It had lost the top gear. Unfortunately the mechanic took a long time to arrive, and when he did there was little he could do, so we had to ride it back to Mysore without a fix anyway. So we ended up leaving quite late, about 3pm.

Hairpin bend, Ooty

One of the 36 hairpin bends on the Ooty road. Near here, a car had gone over the side earlier in the day, falling down a sheer 100m drop. On the way up, we had done this road in the dark, and the rain. I’m kind of glad we couldn’t see the view, even though it was awesome coming down.

Bandipur national park.

This is the home of project Tiger, and one of our colleagues who drove back apparently saw one with cubs crossing the road, which is extremely rare, as they are quite shy. Deer and elephants are common though. We came upon a group as we rounded a corner, which was quite a shock at first, until we noticed that they were chained and domesticated. It is mating season right now, and wild male elephants (called ‘tuskers’ here in India) can be quite touchy.

Elephant with chain

Elephants in Bandipur

In Bandipur Keshav ‘distinguished’ himself by riding standing up and generally fooling around. It is relatively safe on the Thunderbirds since they are pretty stable at the low speeds we were doing, and there was not so much traffic in Bandipur.

Indian road near Mysore

Riding to Mysore In Mysore we stopped while the bike was seen to. It turned out to be a long job, so we ended up leaving the bike there. The dark green bike here is a very rare diesel model produced by Royal Enfield in the 70s. Yes, you did read that right, it is a diesel motorbike.

On the way back, in the early evening, I dropped the bike near a speed-breaker (aka speed bump, sleeping policeman). These are very common on Indian roads near cross roads and the entrance to towns, even on what you might consider a ‘highway’. Sometimes, as in this case, they can be very poorly marked. None of us saw it in time, and the vehicles in front of us also braked very late. My front wheel locked, and as any motorcyclist would tell you, once that happens you are not going to stay upright. Fortunately I was going slowly, and suffered only bent pride and some scrapes on elbow and knee.

Sripad was shaken up a bit by seeing the accident, and he himself came of the bike a few 100m later, as a result of hitting a pig. These are the hazards of Indian roads. Both he and the pig were fine.

Recovering at Coffee Day, half an hour after dropping the bike.

Murphy’s law hit later on I guess, when about 2 hours later the bike started acting very strangely - and handling like a sofa. I thought it was my imagination at first, then it was getting much worse. Naturally I assumed it was the after-effects of the accident. I swapped with another rider and when he rode off I noticed that the back tyre was going flat. This was at 10:30 at night on a Sunday, and when we stopped at a (closed) petrol bunk, I was pretty sure that it was a forlorn hope to find someone to fix it.

'Puncher' shop'Puncher' shop

Repairing punctures

Fortunately in India there is always hope. It turned out that there was a puncture shop a couple of kms back in the last town, and miracle of miracles, they were still sitting around drinking chai. A hundred rupees and we were back on our way. For me there were no more problems, although Keshav managed to have some fun when his muffler fell off. He carried it back to Bangalore, and eventually, after an event filled ride, we all made it back safely.

All in all it was an eventful, painful, wet and wonderful ride. It was a great way to travel, and hopefully it won’t be the last time I ride a bike across India. I’ll still wait till afterwards to tell my mother though.

Wix bug fix for importing InstallShield project with Dark

Thursday, November 22nd, 2007

I have been spiking migrating our project’s InstallShield scripts to Wix. There are several good reasons to do this, which I will get to in another post.

But when trying to decompile the InstallShield msi using Dark I get the following error:

dark.exe : error DARK0001 : Cannot set column 'KeyColumn' with value 0 because it is less than the minimum allowed value for this column, 1.

Exception Type: System.InvalidOperationException

Stack Trace:
   at Microsoft.Tools.WindowsInstallerXml.ColumnDefinition.ValidateValue(Object value)
   at Microsoft.Tools.WindowsInstallerXml.Unbinder.UnbindDatabase(String databaseFile, Database database, OutputType outputType, String exportBasePath)
   at Microsoft.Tools.WindowsInstallerXml.Unbinder.UnbindDatabase(String databaseFile, OutputType outputType, String exportBasePath)
   at Microsoft.Tools.WindowsInstallerXml.Unbinder.Unbind(String file, OutputType outputType, String exportBasePath)

It turns out that InstallShield doesn’t put the right values in the _Validation table (whatever that is). Some hints are in this bug. It is next to impossible to fix it from the InstallShield side, so I did it by fixing the Wix side.

Note: You need to check out the CVS version of Wix to build it - the source downloads from the website do not work. No documentation on this anywhere of course. Sigh.

When you have the code compiling, the hack is simple - modify the columnDefinition for KeyColumn in the file src/wix/Data/tables.xml to allow 0’s in that column. Note that this is a hack not a solution. This may cause other problems and probably the Wix guys will need to fix this for real, maybe by supplying a default value. But it did allow me to export the MSI successfully.

Patch against the latest cvs:

Index: src/wix/Data/tables.xml
===================================================================
RCS file: /cvsroot/wix/wix/src/wix/Data/tables.xml,v
retrieving revision 1.49
diff -u -r1.49 tables.xml
--- src/wix/Data/tables.xml	21 Sep 2007 07:58:40 -0000	1.49
+++ src/wix/Data/tables.xml	21 Nov 2007 14:32:05 -0000
@@ -1482,7 +1482,7 @@
         <columnDefinition name="KeyTable" type="string" length="255" nullable="yes"
                 category="identifier" description="For foreign key, Name of table to which data must link"/>
         <columnDefinition name="KeyColumn" type="number" length="2" nullable="yes"
-                minValue="1" maxValue="32" description="Column to which foreign key connects"/>
+                minValue="0" maxValue="32" description="Column to which foreign key connects"/>
         <columnDefinition name="Category" type="string" length="32" nullable="yes"
                 set="Text;Formatted;Template;Condition;Guid;Path;Version;Language;Identifier;Binary;UpperCase;LowerCase;Filename;Paths;AnyPath;WildCardFilename;RegPath;KeyFormatted;CustomSource;Property;Cabinet;Shortcut;URL" description="String category"/>
         <columnDefinition name="Set" type="string" length="255" nullable="yes"

The Editable Grid Antipattern

Friday, February 23rd, 2007

“Make it look like Excel” is one of those “requirements” that wakes me up screaming in the middle of the night, in cold sweats and gibbering…

IMHO it is almost always a failure of analysis, a failure to dig deeper and discover the actual problem, a failure to “Ask why? five times” [1]

Here’s an example of what I mean, based on a real example that I have seen.

Maintaining Employee Information

Suppose I have an application for the maintenance of employee and employment information. There is a dialog that shows the employment history of the person in a grid that looks something like this:

This grid is editable. Basically they are directly editing the underlying database table.

Why?

Because we need to be able to change the dates.

Why?

So we can enter a termination date and the reason for the termination

Why?

So we can update the employment history when we terminate an employee.

Terminating an Employee

It turns out that when they terminate an employee, they go to the employee status screen, and change the status from ‘employed’ to ‘terminated’. Then they go to the employment history page and update the employment history with the new end date, and the reason for termination.

Consider the implications:

  • It is possible to change the status of the employee to terminated without having that reflected in the employment history
  • It is possible to change the employment history to reflect a termination, while the employee status still has them as employed.
  • The operation to terminate an employee is not atomic (the status field and history entries are changed independently)
  • it is possible to change the dates of an employment in the past - without any thought to the consequences.

Here’s a (hopefully hypothetical) example of the problems this may cause. Alice changes the status of Bob to ‘terminated’ but does not change the employment history. The company decides to pay a bonus based on the time that an employee has been with the company. Bob gets a gold watch in the mail despite the fact that he has been working for another company for 5 years now.

Usability Problems

Chris is new to using the system. Diana has just been re-employed by the company. So Chris goes to the employment history which looks like this:

and changes it to reflect the fact that she has been re-employed:

Diana is *really* annoyed when she doesn’t get the gold watch in the mail despite having worked for the company for over 25 years.

Complex Business Rules

Imagine the business rules that would be needed around this implementation if you want to make it reliable and keep it as is:

  • you should only be able to edit the last EndDate of an employee’s history
  • if you enter an end date you need to enter a termination date
  • the end date must be after the start date
  • the start date must be after the previous end date
  • you can only enter the end date if the status of the employee is ‘terminated’ (but i want to change the history before the end date is entered!)

Complex Requirements

Suppose someone notices that the status and the history can be out of sync - they come up with a couple of new requirements:

  • as a user, I want the status of an employee to change to terminated when I change the end date of an employee on the history page so that the status is in sync with the history
  • as a user, I want the status of an employee to change to terminated when I change the end date of an employee on the history page so that the status is in sync with the history

Not only are these business rules and requirements complex and hard to understand, they describe the system in terms of the implementation. Since the implementation (the editable grid) is directly tied to the database, you might as well describe the system in terms of changing rows in the database. There is no relationship of the requirements to the actual tasks being performed by the user (Terminate, Re-employ etc.)

Hopefully you see the problem.

Asking “Why?”

So what can we do?

If the original team had asked “Why?” a few more times then the stories might have looked like this:

  • As maintainer of the company employment records, I want to be able to terminate an employee, as of a certain date, with a reason so that we can stop paying them a paycheck.
  • As maintainer of the company employment records, I want to be able to re-employ a previous employee, as of a certain date so that we have a single record for that employee.

How would that be implemented? Maybe a “Terminate” button on the employee record screen, that pops up a dialog like this:

Simple. Usable. Atomic. Safe. Easy to implement.

So if you find yourself implementing an editable grid, I would strongly Strongly *STRONGLY* urge you to go back to your customer and ask “Why?” 5 more times.

Caveat: Sometimes, just sometimes, it may make sense to have an editable grid that ‘works like excel’. If so, use Excel. That is what it is for.

[1] “Ask why five times” is one of those many things that has entered the lexicon from Taichi Ohno, lean manufacturing and the Toyota production system.
http://www.toyota.co.jp/en/vision/traditions/mar_apr_06.html