Friday, August 24, 2012

I used to be a C/C++ programmer.

Certain not-very-much-like-C things in Delphi still trip me up. Like this code which I wrote today, expecting it to zero pad my integer values:
    var
          hour,min:Word;
    begin
             ...
     result := Format('%02d%02d',[hour,min]); 
     // expected '2400', got '24 0'


After a bit of googling, I found that you need this syntax, which seems very unorthodox to me:

   result := Format('%.2d%.2d',[hour,min]); 


As weird as that use of a decimal place in a Format statement involving only two WORD or Integer type variables (hour/min) looks to me, it works just like a %02d format specifier would in C, Java, C#, Python, Perl, Ruby, and Everywhere Else in the Known Universe, other than in Delphi and TurboPascal.






Thursday, August 16, 2012

Clean code, greenfield development, and the Developer Ache

Much has been written lately about "writing clean code".  Whether it's the "Uncle" Bob Martin books, or other similar books, there has been a lot said about writing code which is a joy to work in.

The alternative word to "clean", is "legacy", which means "a pile of crap that I hate working on".

I'd like to suggest that in fact, 99.99% of all the code that runs everything, including Windows, your bank machine, and the rest of your bank, the entire world banking system, the fuel injection computer in your car, the firmware for every system in every airplane currently in the air, and just about every piece of PC Windows, Linux, Mac, and  embedded system software in the world is "Legacy" software.

I'd like to suggest that clean code is an asymptotic desire of an insane mind. That programmers can become obsessed with code cleanliness to the point that they can place some aspects of clean code above the other more important aspects of clean code.  Of course the "clean code" people advise correctness, completeness, usefulness to the customer and the world, but I haven't seen them advance any ideas on how these ideals can be pursued in a manner that is sustainable, and which can balance pragmatism against idealism, such that the survival of the businesses and knowledge-based economies that live thanks to these systems is assured.

Sometimes we create amounts of technical debt which require not only technical solutions, they require mental conditioning to withstand working in the code. Sometimes a kind of zen quietness is needed more than a kind of ninja coding style.

Imagine, if you will, deep in the bowels of the Microsoft campus, lives a senior software developer who is responsible for the Windows Explorer Shell APIs and codebase.  Imagine it's 5 million lines of insane code.  He can't change any of it without breaking a million plugins or extensions, and he's still getting heat from managers who can't code, for the 57 serious bugs that shipped in Explorer.exe in the Vista RTM.  He dreams of a clean codebase, but he knows it can never happen.

There are just too many constraints on real useful software, to ever allow complete rewrites.

Now let's switch to Delphi programming.   What if 99% of the Delphi code out there is a Big Ball of Mud.   No encapsulation.  No abstraction.  No cohesion.  Plenty of bad stuff; Coupling ties everything to everything.   You can't bring one unit in from a project without pulling in 4.5 million lines of code via the snarled mess of uses-clauses that tie the whole unit to everything else in it.  Nothing is unit testable.  You can't rewrite it without killing your company and your main product.   Everyone wants an incremental addition here and there, but nobody has the patience to wait while you clean it up.

What do you do?   I would argue that everything that the clean-coding crew says you need is still true. But you need to turn down the volume dial on your own internal anxieties.  You need to give yourself the time, the imagination, and the freedom (internally) to imagine that these problems really can be solved, but that the solutions won't come in a complete form, but rather, incrementally, slowly, and that after a sustained effort, you might get cleaner code.  Never ever will you have clean code.

But maybe just maybe, you can make things better.  Just not perfect.   And that's the difference between insane, and sane.    Maybe some coders have undiagnosed Obsessive Compulsive Disorders.  So become more self aware, and become a better coder.


Tuesday, June 26, 2012

Celebrating Twenty Years of Failure in the Mobile Space

There's interesting reading, great 1990s nostalgia, and some pictures of long forgotten devices at this IT World article:


Flops and Vapor: 10 ways Microsoft tried and failed to rule the Mobile device world


It's an amazing list of Microsoft-sponsored mobile software failures.  It shows us how compelling the "tiny pocket computer" idea has been in all our collective imaginations, and how elusive success has been in that space.


Even those technologies that have succeeded have not had a long or stable shelf life.  Mobile technology is more uncertain, and the market is far less stable than the PC market.


It might give you pause, if you were a major vendor of software for the Pocket PC, in 2001, or a Palm Pilot software vendor, in 1999, that your market might not exist in 10 years.  Could the same thing happen again, to Apple-device software ISVs?  It would be a historical anomaly if the market didn't at least cool off a little bit.


Anyways, nobody has tried (and failed) more often in the mobile-device space, than Microsoft.


Click the link, and read, and weep.  And ask yourself, how many of those gadgets are in my gadget junk drawer.   I personally bought (or wanted to buy) at least a dozen such devices, including Microsoft-based offerings running Windows CE, and some others, including various models of the Palm Pilot PDA.


But while Palm is dead, and its most notable successes lead to nothing but failure, Microsoft has survived its failures, making it perhaps the most unique company in the technology business.  Its sheer financial health, lead by the Windows and Office division's billions of dollars in profits, lets it lose billions on mobile devices, XBox game systems R&D, and other things, without substantially affecting the bottom line.   


So, the ability to not only survive, but continue to thrive, while throwing away more billions on wasted R&D than any other company in history, is in fact, something to celebrate.  I'm actually serious here.  People owe Microsoft some respect for that.  And I do respect Microsoft, even though they do things that make me mad.  Give me back the Office 2003 User Interface, and get rid of that useless ribbon.  But hey.... Windows 7 is nice.  Try not to screw up Windows 8 too badly, okay?









Thursday, June 14, 2012

Indentation Holy Wars.

One thing that surprises me to no end is the number developers I meet who are willing to take up arms and fight to the death over the indentation and whitespace style of their code. And capitalization. And other things that the compiler ignores.

This wikipedia article, which is C/C++ centric, shows the main variations popular in C/C++ programming, and in related languages that use curly-braces, including C#, Javascript, and others.

Here's my personal indentation and whitespace style:

// Warren Style (The One True Way)
procedure MyProcedure( Arg1, Arg2 : Integer; Arg3 : string );
var
  i: Integer;
begin
  if arg1 > 10 then begin
      for i := 0 to 10 do begin
         DoSomething;
      end;    
  end else begin 
      DoSomethingElse;
  end;
end;

By my count, there a great many ways that people could rewrite, or nitpick about the above very simple code. Here are but a few of the myriad whitespace options Delphi people argue over:

1.  begin starts a new line, always? (Yes/No)
2.  Do we put a begin..end around a single statement or do we leave off Begin/End where possible?
3.  Indentation levels (2,3, or 4 spaces).
4.  Initial indentation level different than sub-levels (commonly 2 character indentation after var keyword, more than 2 character indentation inside begin/end blocks.
5   Location of begin and end : Pick a style from the wikipedia list.  Allman, Banner, K&R, and others.
6.  How do you police the width of your files and formatting of large argument lists to procedures?
     One parameter per line? As many as will fit in 80 columns?

If I multiply the options above, I get somewhere between 40 and 100 different options, depending on how many choices I can manufacture at the stages 1 through 5 above.

We all know holy wars are not objective matters.  But why do holy wars break out, and why do developers have a hard time dealing with variance from their chosen style?

I would like to propose that developers do not read their code. They see shapes, and where necessary they read their code. When code is not formatted the way they like it, they find that the level of effort that they must expend is increased.  So, in the end, it is a selfish sort of argument, as all holy war topics are.    My own preferences run towards the sample above, but any of the following are acceptable to me:


// 2 & 4 space Jedi Style
procedure MyProcedure(Arg1, Arg2 : Integer; Arg3 : string);
var
  i: Integer;
begin
  if arg1 > 10 then 
  begin
      for i := 0 to 10 do 
      begin
         DoSomething;
      end;    
  end 
  else 
  begin 
      DoSomethingElse;
  end;
end;


// Save The Chars Style
procedure MyProcedure(Arg1,Arg2:Integer;Arg3:string);
var
  i:Integer;
begin
  if arg1 > 10 then
  begin 
      for i := 0 to 10 do      
        DoSomething;
  end 
  else 
      DoSomethingElse;
end;



// consistently 2-spaced Jedi Style
procedure MyProcedure(Arg1, Arg2 : Integer; Arg3 : string);
var
  i: Integer;
begin
  if arg1 > 10 then 
  begin
    for i := 0 to 10 do 
    begin
      DoSomething;
    end;    
  end 
  else 
  begin 
    DoSomethingElse;
  end;
end;




The one style I encountered firmly entrenched at a big Delphi shop, that I could not live with is this style:


// Pascal+Banner Style

procedure MyProcedure(Arg1, Arg2:Integer; Arg3: string );
var
  i:Integer;
begin
  if arg1 > 10 then 
  begin
      for i := 0 to 10 do 
      begin
         DoSomething;
         end;    
      end 
  else 
  begin 
      DoSomethingElse;
      end;
end;




Did you see what happened there? The second (green) end keyword looks to me like it goes with the for-loop's begin (blue), but it actually goes with the if statement's begin statement.  Now not only does the visual "it scans easier" argument that the fans of the banner style prefer not make any sense to me, in the example above,  begin..end blocks inside a procedure have one set of rules (the banner style) but the outermost begin and end above, the ones I have marked in bright pink above, still line up with each other.  The mental anguish that the above style caused me, during my 9 months of employment at the company where the senior developer preferred that style probably caused me more anxiety and grief than any programmer in the world could imagine whitespace causing, until you end up on the losing side of a holy war on a topic you can't win.


You see, when an application's already built, and formatted a certain way, you have, as a single guy working at a company, a bit of a professional obligation to do what you can to work with that style. I tried, and I tried to learn to read the code style above. I found I could not. I gave up on formatting my code like I was told to format it. I just couldn't do it, my brain, and 30 years of habit were rebelling against me. I asked other delphi developers and they said they couldn't live with that style either.  But neither could the company or its longest standing Delphi guys countenance any change.  


In the end, there was only one way out.  I am no longer working at that company, and I'm glad to be gone.  Indentation and whitespace weren't the only ways we were not a good fit.  But it was a bit of a case in point.  Could you rewire your brain, to accept a style that later, after you're gone from a company, you still regard as a form of brain damage?  I couldn't.  


In the end, the rule is the rule;  Companies set up shop and run for 30 years, and you, the developer need to learn to work within their rules, and if you can't, then get out, or be fired.  Fair enough.  But it still amazes me that something as insignificant (to the compiler) as whitespace, can be a make or break criteria for you keeping your job, or perhaps even, whitespace might kill you.  Stress, and anxiety over a long period of time kills and sickens human beings every day.  Even if all the stress and fighting is only over something as insignificant as whitespace.


Addendum:  The multi-assignment alignment Sub-Holy-War.


Have you ever written code like this:
        A.Size       := GetAreaSize(Arg1, Arg2);
        A.Width      := GetAreaWidth(Arg3, Arg4)
        A.PanelColor := GetThemeColor(Arg5);


When I do, I like to have the equal signs line up if all the assignments are in a group. I prefer the above style to using with.  Other people hate it when you put an extra space after A.Size.   

Saturday, June 9, 2012

The Delphi 1.0 Installer was Awesome

This is the delphi 1.0 installer running. It's the dashboard of a sports-car, probably a Porsche.  The speedometer shows the progress from 0 to 100% of installed.

Bring Cool back to software installation, Embarcadero. Installers should be fun.  Oh, and free support for installation with a phone number to call, right there, on a little "note" on the windshield of your new "Porsche"; Priceless.




Friday, June 8, 2012

Why I still hate, and yet grudgingly respect, C++

There are lots of great "Programmer to Programmer" questions on the sister-site to StackOverflow, called programmers.stackexchange.com, where a lot of the general non-programming related questions that are somewhat software development related, but not exact technical questions with exact technical answers. Here's one I came across today:

  Why do so many people dislike C++?

The answers there are very good, but my favorite one is the answer that brings up a podcast conversation between Jeff Atwood and Joel Spolsky, two of the guys behind the whole "StackOverflow" empire, among other things.

 The gist of that answer is that you have to read a book about the "gotchas" in order to avoid writing really bad C++ code. A well-intentioned person who doesn't understand the difference between lvalue and rvalue references, copy constructor semantics, the intricacies of casting, const and non-const and when to use each, and the problems of writing exception safe code, concurrency and threading, and on and on...

 Well, I've always hated, but grudgingly respected C++, as a Delphi guy. I am in the C++ guy camp with the desire to have a binary that is standalone with no runtime at all, but yet, I see, that most of the Windows Visual C++ people seem to accept redistributing MS VC Runtime dlls along with their apps. Say it ain't so, m my C++ brothers.... DLLs that you ship should be your dlls only. Being forced to ship a DLL that contains some bits of your standard library is just so wrong on so many levels.

 Since the question on Programmers.SE covers enough of the reasons why you might hate C++ I'll just tell a story about why I hate C++. In 1995 I was working for a small software company making OS/2 software in C++. It was the last professional C++ job I ever held. I was using IBM VisualAge C++ for OS/2. In those days, writing code in C++ was rough. IBM actually had a nicer class library than most people, and their documentation was almost always right.  But it was shockingly difficult to write a database application in C++.

My main gripe was the lack of decent string handling libraries and capabilities in C++.
I counted at least four ways of writing string-processing code in our codebase:

 1. You could use IBM's non-standard-C++-library strings.   These had capabilities that the standard C++ library string types lacked, but the reverse was also true.

 2. You could use the standard-C++-library string types.   The most fun thing about using these was the absurd things that they did include, and the obvious things that they didn't include a way to do, requiring you to hand-code a tonne of string functionality yourself, over and over and over.

 3. You could use regular C char buffers and C pointer to char strings.  And you could then enjoy buffer overflows, and access violations, if you made mistakes.

 4. You could use your own class that basically used operator overloading, or whatever style you wanted to use, to try to provide the semantics that you wanted, as if you were programming in Visual Basic.  Most people started out using #1,#2,#3 and when they hurt themselves badly enough, they would start a side project writing their own C++ String Type. One String to Rule Them All.  Of course, they would then get lost in evil C++ side-effects involving casting, type coercion, lvalue and rvalue semantics, and so on. Oh, and string heap memory management.

 I saw all four of the above in use, and on three different occasions started writing my own C++ string classes, and it sickened me. I wanted one string to rule them all.  I wanted a string type built into the compiler that everyone would just use.

I had loved using Turbo Pascal in DOS, and in 1995 when Delphi came out, I saw that it had one, and only one string type. Sadly, it was the Pascal 255-character string type.  But when Delphi 2.0 came out, it was love at first sight. A proper String type built in.     Ironically, delphi now has a whole pile of string types, and the meaning of String has now changed three times (ShortString -> AnsiString ->UnicodeString)  and yet, we've survived it.

Back to C++ for a moment. You see, the codebases we used were so full of different string classes that I spent a lot of time converting string data from a standard library string to a character buffer or pointer to characters (PChar in delphi terminology).  The UI layer used the IBM string class.  The stored procedure layer used Char buffers and Char pointers with dynamic memory allocation (malloc).  In between, chaos reigned.

Now the above criticism isn't just about strings. It's that C++ is a giant playing field where millions of very talented developers have built giant monster piles of code. Half the world runs on the stuff they have built.

 And now I will switch from griping to respect mode.

 1. Microsoft Office is built in C++.

2. Almost every major Game studio writes in 100% C++.

3. No other language can do everything C++ can do, and yet compile to native code. Never has this been more true than since the advent of the new C++ 2011 standard. Check it out it's pretty neat.

 4. Finally, because of the tools, libraries and the rest of the C++ ecosystem, C++ is the most powerful cross-platform binary compiled language on the planet.

While I'm glad that I don't have to learn all the intricacies and accidental-complexity of C++, I do want to be able to link in C++ code into my Delphi apps sometimes, and for that reason, I'm quite excited at Embarcadero's future directions with LLVM/CLANG and C++Builder. In the microsoft camp, I'm truly impressed with their C++ 11 support in Visual Studio 2012. In the library and tools world, I'm deeply impressed by wxWidgets, BOOST, and the entire commercial ecosystem of C++ game development tools. Almost every major-studio game produced these days is 100% built in C++. So, let's give C++ a round of applause. And be glad if you've got a job doing Delphi and you don't need to understand copy constructors and type coercion, or discussing  some obscure massively-multiple-inheritance scenario you've devised.

Friday, May 25, 2012

Bob Martin: NO DB. Me: Any Sane DB.

The venerable OOP guru Bob Martin has weighed in on SQL, and NoSQL. He admits candidly to disliking SQL databases, and the way they just jumped in and dislodged non-database centric developer's lives. Their ubiquity, at one point, and the belief that any kind of persistence layer other than an SQL database persistence layer was somehow "not good enough" lasted nearly 25 years in our industry. I started out, and remained until recently, an SQL-database hater, conditioned to hate SQL by the bitter experience of many projects where it seems that SQL and the concerns around it, destroyed the project, and the company. I especially learned to loathe IBM DB2, on OS/2, and a series of misbegotten attempts at multi-tier database application architectures. I learned quite recently that SQL is actually not too bad. I don't love it. But I don't hate it either. I have however, learned that proprietary data-stores that are home-brewed can have quite a lot of glitches, and are generally not to be trusted. If there's two things I hate more than SQL databases they are:
  • Private binary-repository stores used as the primary repository for critical customer data.
  • Any persistence system that is not trustworthy.

    A trustworthy system must have at least three of these four characteristics:
  • Be fully unit tested. (SQLite=Yes)
  • Be widely used by respected/large products (SQLite=Yes)
  • Not have lots of people ranting about why it sucks (MongoDB,CouchDB, etc).
  • Open source to prevent vendor lockin.

    I have one non-negotiable, too:
  • Not have misfeatures, that cause data loss, that make me hate it. (Remember subversion's early BSDDB back end? I still haven't forgiven BSDDB or Subversion for that.)

    Having said that, my current job, and my previous job have involved working with Microsoft SQL Server, and as commercial databases go, it's actually pretty nice. And if your database is small, it's free, with the "Express" edition. Nevertheless, it's hardly painless. It seems very easy to make mistakes that you will only realize are mistakes after years of work. That's why the "DBA" and the "Database developer" roles were born; Because doing SQL databases is hard work, and screwing them up is easy.

    Lately, I have become very interested PostgreSQL, which is a hybrid database, offering classic SQL features, and a lot of great stuff that the NoSQL crowd has come to offer as well. I also have a lot of respect for SQLite, and for desktop-only zero-configuration cases, I have come to prefer it. However that stance is new for me. I actually had a very loud argument, where I was completely (irrationally, and wrongly) against ever using SQLite in any Delphi application written by any team involving me. Hey Steve, if you're reading me; I was wrong. SQLite is actually kind of awesome.

    I realize that the DB world and the persistence-layer of programming, are hotbeds of opinions. ORMs are great. ORMs suck. Automatic OOP persistence layers are a current area where debate is raging loudly. The classic "SQL for everything" people tend to value hand-crafted SQL and queries, and so any layer that tries to map (via an ORM) objects to SQL is going to suck, in some cases. However, if you want a non-relational persistence model (which is actually ideal for many classes of problems), you're always going to be wondering if you went the wrong way, when you get yourself into the sorts of troubles that SQL-based solutions don't suffer from. How about the debate between the "Scalability Über-Alles" crew and the "Data Integrity Über-Alles" crew. It's a holy war, and it's on.

    There are no silver-bullets. But there are some lead-balloons out there.