Dark ages with rounded edges

By , October 5, 2009

Yes, the day I’ve been avoiding for so long has come and I’ve decided to look at Apple development environment in details. And what I found was not pretty – Xcode IDE and Objective-C. After years of basking in ignorance, assuming general forward movement of humanity, I stumbled across this artifact from the past that seems to be taking over the mobile world.

Objective-C is an interesting language and seemed like an interesting step from C towards more dynamic languages. However, the toolset (IDE, Frameworks, APIs) that surrounds it for the sake of Mac and iPhone development makes it look just as ugly as Visual C++ looked 10 years ago. Coming from Java, .NET and Ruby development environments, iPhone application development looks like a relic from the museum of natural history – curiosity that deserves to be on the shelf collecting dust.

The amount of tedium one has to go through to build a simple business application is just mind boggling. It feels like the people who develop and market this have been locked up in the reality distortion field for the last 10-15 years and have missed the advances happening everywhere. Every iPhone developer session I went to lead to conversations about inevitable memory leaks and corruption. Everything takes 3 times as long to develop as for any other platform. Don’t forget to restart XCode 20 times per day whenever you are not sure whether this is XCode bug or yours. I have seen this in the past – that’s what C++ projects were 10-15 years ago: lengthy, hard to write, very prone to crashes, horrors of shrink-wrap distribution model.

With this in mind a lot of things make sense: the draconian control policies of Apple store approval process, the obnoxiously lacking ability to multitask applications and the overall secrecy. What else can Apple do to separate perception of their reliability and simplicity from reality of the platform? Try having memory leaks in the background applications with only 128-256MB RAM total and essential phone operations under threat. Or explain why the long running program can’t be written by typical developers because they will have an obscure crash condition somewhere that cannot be dealt with. Their way was to try to take full control.

There are some positives that come out from this attitude. Forcing multi-week approval cycle for even the simplest application changes enforces a higher general quality of apps in the store. Developers hate it, but users might be better off in most cases. However, mistakes happen and inability to correct them quickly irritates both developers and users. Also the performance of the applications is generally better than those of their peers on competitor phones. The phones today are in many ways comparable to desktop computers 10 years ago – no one was running Java for intensive applications back then. The low level C-style code tends to be written with performance in mind more often than not. While Java can be as efficient in many cases, the typical developers are already not thinking about squeezing every possible efficiency and that is unforgiving on phone-like devices.

Apple performed remarkably well on a dated platform due to focus on mindshare of high paying customers. This is a testament to the power of their marketing machine and ability to execute. Reduce the choices to one thing that works for most. Pay attention to the polish, implement only few features but do them really well since most users aren’t too bright to use the extra stuff anyway. Their solution to the horrors inside was to paint bouncy icons with rounded edges on outside and control the gateway. Appearance is everything, welcome to the Dark Ages 2.0 …

For all you disbelievers – Apple stuff is incredibly easy: http://www.youtube.com/watch?v=Nx7v815bYUw Think same!

Greatest unit test

By , July 14, 2009

Recently got a warm and fuzzy feeling when opened a new project for inspection, performed search for word “test” and found three matches in the source tree all pointing to different instances of usage of “greatest”.

On ease of IIS vs Apache configuration

By , June 27, 2009

Recently ran across what felt like a relatively straight forward task – make IIS 6 and Apache run side-by-side on the same Windows 2003 server using same port but different network interfaces. How difficult could this be? Apache was installed and configured first. IIS was installed, configured and started next. Then the computer was rebooted to test automatic application restart and all hell broke loose…

1) First Horror – Apache fails to start because IIS is hogging up all ports (well described all over the internet blogs)

After wasting time in fruitless attempts to use nice-looking IIS menus had to switch to Google searching for something much more obscure. Established the fact that IIS consumes all network interfaces even if you explicitly specify which one to listen on in its menu. That is default behavior from Microsoft that assumes that no one in their right mind would ever install another Web Server next to IIS (they turned out to be right). A variety of posts were arguing the merits of editing DisableSocketPooling registry setting vs running optional command-line httpcfg utility. An article from Microsoft (http://support.microsoft.com/kb/813368/EN-US) resolved this confusion – the first command was applicable to IIS 5 (hope no one uses it anymore) and has no effect on IIS 6, the second applies to IIS 6 only.

Per the instructions ran command: httpcfg set iplisten -i IIS_DESIGNATED_IP_ADDRESS. Now Apache and IIS could be started in the reverse order. The perceived man over machine victory was very short-lived because the subsequent reboot test showed a 20-30 minute start-up delay that did not exist before.

2) Second Horror – incredibly slow failing IIS start-up (no answer found on google)

The new non-UI configuration changes to IIS broke the machine beyond the wildest expectations. The services kept trying to start and were timing out and retrying causing very slow start-up behavior. The event log inspection yielded the following message.

The IIS Admin Service service hung on starting.
The FTP Publishing Service service depends on the IIS Admin Service service which failed to start because of the following error:
After starting, the service hung in a start-pending state.

Tried to rollback the changes using httpcfg delete commands – no help, the server seemed to be permanently broken and would not boot normally anymore. A few more people on the internet reported similar problem but no answers were published.

After a lot of experimentation found the solution that definitely qualifies for top lunacy category: IIS configuration needs to be backed up and without any changes immediately restored. I guess httpcfg leaves registry or IIS metabase in somewhat inconsistent shape and IIS restore does more than just restore. Otherwise how could restoring configuration that is known to break a computer fix anything?

So now when someone complains about not having a visual editor for Apache configuration, compare this with IIS registry/metabase combined nonsense. It takes less time to learn advanced Apache configuration examples than deal with this.

Not so clear case

By , June 26, 2009

Some software systems inspire strong love-hate feelings. ClearCase falls into this category and has a devoted set of admirers and a seemingly much larger community that loathes it. How come it is so widely spread given a huge “hate it” crowd? The answer probably lies in the placement of communities – senior architects/administrators with experience going into horrors of computing dark ages and a fresher developer group used to fast low-overhead systems.

ClearCase was a novel and feature rich product when it came out. In addition to offering a good set of source control features, the system encompasses a lot of interesting design ideas to solve main mid-to-late 80’s problems: slow computers, small expensive local disk space, network-based virtual file system architecture. The system could act as a hybrid between source control and build system and retain artifacts built by other team members to not force recompilation of components. This was useful when compiling something of BSD kernel size on a single machine could take a night. Thus a lot of senior developers invested time into learning the depths of ClearCase to make the complex project development easier to manage and to save everyone else time. It would often become almost full time job for 1-2 smart people on every moderately sized team.

Fast forward few years from the original system release to late-90’s: most of the issues that the design was addressing started to disappear. In addition, what most likely disappeared is the original development team that created ClearCase (I am guessing here but this almost always happens in the endless chain of product acquisitions). What was left is the old fame, the marketing team and lack of serious competition on the market. It is all downhill from that point…

The system’s Achilles heel lies in the main spot that is loved by the purists – its network file system (MVFS). The performance of the system outside small local LAN is beyond hideous – it is difficult to write something as slow on purpose. This is probably attributed much more to implementation decisions and talent loss on the CC team than the design itself.

I have not seen anyone who used ClearCase successfully recently. In all of the installations observed it has been hampering basic developer productivity and was not relying on any build “reuse” features.

Here is a short summary of the ClearCase usage in groups where I worked (does not apply to entire companies):

Oracle (1998) -> CC-based source/build management abandoned (it’s check-in performance was unfavorably compared to 2400 bps dial up modem located somewhere in Germany)

First Jewelry (1999): the contents of entire repository was lost due to administrator trying to tune the performance. It had to be restored from current versions sitting in static copies on developer workstations.

Bank of America group 1(2004): abandoned and successfully replaced by CVS due to horrible distributed network performance (check-out/check-in cycle was taking 40 minutes to 1 hour from every developer daily)

Bank of America group 2(2009): still used to make development miserable for anyone located more than few hops away from the repository. Remotely located developers do static view snapshot check-out once a day, make a local copy (to avoid overhead of ClearCase’s super slow file system) and then figure out what files they changed using diff at the end of the day to copy them over the view folder and check them in.

Most ClearCase defenders say something apologizing like: “you did not have the right administrator”, “did not try feature A?, yes, then you did not have a good administrator” , “worked for me”. Maybe there is a way to make it work, but it sounds more like an exception than the rule. Thus I would hope the system usage would be more of an exception too as it clearly outlived its usefulness.

I am typing this post in San Francisco as I am checking out a project from Chicago over fast internal network. However, for ClearCase it takes 1 hour to get 2000 files with about 30MB total data. That’s only slightly better than that 2400bps modem, they must have gotten a newer 56kbps model…

Shortcomings of Flash to overcome (HTML comparison)

By , May 27, 2009

1. UI Navigation. This should have been Flash strength but somehow seems to be one of the common traps for new application developers.

Horrible UIs deserve a volume in my upcoming encyclopedia and modal dialogs will definitely be one of the first chapters. Coincidentally, this seems like one of the most abused UI concepts in Flash applications that I observed. Open up a detail page and do not let a user navigate away from it without pressing Cancel or Save… Why would anyone want to see two detail pages side by side? Work on few things at once? Why would anyone want to open tabs? Just because the dialog is semi-transparent it does not mean it ventured far from its green screen ancestor.

The special award goes to pop-under modal dialogs (AKA “click me if you can figure out that I am there”). Second place is taken by Windows 3.11 style cascading errors that seem to be popular with a bunch of sample Flex applications.

Simple browser option to right click and open new window or tab goes a long way in making applications easier to use.

2. Text search and selection. HTML and good browsers spoiled most users, people do not often even read the page – they just start typing the search word to jump directly to the sentence containing their search term. In addition, text on the screen is normally selectable and can be easily copied into other documents. This trivial common behavior is not so common in Flash – takes special effort to create UIs behaving in data-friendly ways.

To catch up to HTML a good UI framework needs to build good search capability that includes labels, text, form fields. Also have to provide a way to select just about any text in the application.

3. HTTP GET (and bookmarks). Sending, saving and posting links is one of the most common ways of sharing information on the web and the support for this in Flash per initial review is limited to very few 3rd party libraries that I do not see in action. That means that absolute majority of the applications out there offer no way to share anything except the main entry into the application. A good Flex UI framework should provide a way to export the current UI location as URL path.

The Ostrich Security Model by Adobe (being adopted by MS Silverlight too)

By , May 15, 2009

Adobe introduced crossdomain.xml file to control whether Flash application can read data from servers. In a nutshell, the crossdomain.xml file must be present on the website and explicitly grant access to clients originating from other domains for anyone to read data/make calls to this server. Excerpt from Adobe Flash player security white paper (http://www.adobe.com/devnet/flashplayer/articles/flash_player_8_security.pdf):

… if the site serves private documents or anything that requires some form of authentication (such as a password), or if the server is behind a firewall where only certain users can access it, it is risky to put a public policy file on that server. Doing so would enable Flash applications to download documents from the server whenever they run on the computers of users that the server trusts. These applications could potentially reveal private data from the server to people whom the user or website administrator does not trust.

This is just about as dumb as it gets with server security. It essentially shuts down your polite flash clients from accessing data but it won’t prevent anyone reading the same data via their own proxy server (trivial to write/configure), JavaScript, etc.

So we established that the servers are not protected by this. Would this limitation protect clients? Not likely – any “man in the middle” attacker would not be lazy to put crossdomain.xml file to fool clients into reading data. The only remaining questions is who can protect the society from the idiots who designed this “security” mechanism and made life more difficult for developers of internet mashups?

getSynergy(Oracle,Java) = ‘timestamps do not work’

By , May 14, 2009

The excitement about the news of Oracle acquiring Sun is prompting me to write an entry about their synergy.

Let’s take one of the developers’ favorite topics – working with dates in different time zones. Why would anyone ever do that to themselves?!?

Understandably, Oracle decided to not worry about making timezone calculations work properly in their .NET and Java drivers. Calls to function getTimestamp() backing TIMESTAMP WITH TIME ZONE columns return stored time with timezone thrown away for any timezone. For example, if one stored ‘May 13, 2009 15:05:25 -0700’ then resultSet.getTimestamp(colNo) returns ‘May 13, 2009 15:05:25’ ignoring the client timezone. I.e. it is right only in Pacific timezone. This is true for both Java and .NET functions – remarkable bug consistency!

The only seemingly sane way to read timezone info into java.sql.Timestamp is via retrieval of date column as a string that then has to be parsed. Of course, to make matters worse Oracle returns timestamps in the format that neither Java nor .NET can parse using any possible date parsing configuration (2009-5-13 17.3.15.991000000 -5:00″)

Below is a snippet of custom code for Java that performs this conversion.

I am not completely sure why Oracle cannot fix their driver. I suspect that they know that people have already built all sorts of hacks that will only work based on their original buggy behavior. I contacted Oracle about similar behavior for .NET – they call this a feature…

However, if it all possible – think through your time zone design first. The old and proven UTC times-only everywhere approach works…

/**
 *
 * Oracle TIMESTAMPTZ, when converted to string, contains six extra digits, all zeroes,
 * tacked on the seconds field.  This is unparseable by the formats used by the DateFormat
 * class.
 *
 * The timezone offset consists of an optional + or - sign, the hours offset, a colon, and the
 * minutes offset, e.g., -5:00.  This is similarly unparseable (we need it to be of
 * the form "-0500").
 *
 * This method massages the given timestamp string, removes and converts the problem data
 * described above, then parses it into a true Timestamp, taking the timezone into account.
 *
 */
public static java.sql.Timestamp convertOracleTimestampTzStrToTimestamp(String dateStr) {
// six trailing zeroes (seconds) followed by the timezone offset: an optional +/-
// sign, one or more digits (the hours), a colon, and one or more digits (the minutes).
  Pattern oracleDateStrPattern = Pattern.compile("(.[0-9]*) ([-\\+]?)(\\d+):(\\d+)$");
  Matcher m = oracleDateStrPattern.matcher(dateStr);
  if (!m.find()) {
    throw new RuntimeException("Invalid date format received: " + dateStr);
  }
  String datePart = dateStr.substring(0, m.start(1));
  String msPart = dateStr.substring(m.start(1), m.start(2)-1);
  int ms = (int) (1000*Float.parseFloat("0" + msPart));
  String signStr = dateStr.substring(m.start(2), m.end(2));
  if ("".equals(signStr)) signStr = "+";
  String hoursStr = dateStr.substring(m.start(3), m.end(3));
  String minsStr = dateStr.substring(m.start(4), m.end(4));
  StringBuffer sb = new StringBuffer(50);
  sb.append(datePart);
  sb.append(".");
  String msStr = Integer.toString(ms);
  appendZeroPaddedString(sb, msStr, 3);
  sb.append(" ");
  sb.append(signStr);
  appendZeroPaddedString(sb, hoursStr, 2);
  appendZeroPaddedString(sb, minsStr, 2);
  String javifiedTzStr = sb.toString();

  DateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd HH.mm.ss.SSS Z");
  java.util.Date d;
  try {
    d = dateFormatter.parse(javifiedTzStr);
  } catch (ParseException e) {
    throw new RuntimeException("Invalid date format received:" + dateStr);
  }
  java.sql.Timestamp retval = new java.sql.Timestamp(d.getTime());
  return retval;
}

private static void appendZeroPaddedString(StringBuffer sb, String str, int desiredLength)
{
  int len = str.length();
  for (int padz = 0; padz < desiredLength - len; padz++ ) {
    sb.append("0");
  }
  sb.append(str);
}

Preface

By , May 14, 2009

This is an inaugural post on this blog. I am writing an encyclopedia of brain damage in software development where I will share wonderful coding experiences from various areas. Stay tuned for marvels of Java, C#, PHP, JavaScript, Ruby, ActionScript, etc. Feel free to add your own experiences and comments.

Panorama Theme by Themocracy