The difference is in creep of functionality and expectations. So much stuff that wasn't even on the table 10 or 20 years ago is now expected so inherently that it's not even set out in the requirements. All those extra classes, complexity, and layers of abstraction do have purposes. We can continue talking about the Microsoft stack; my experience is there too. Yes, in older days you could knock together a report with ten lines of database code and a form in Visual Basic or even Access.

But expectations change. Your fat client VB Win32 app isn't good enough in a world where everyone expects to have every piece of functionality accessible with no client installation, using a web browser. Now you're rewriting it in ASP. Now you have to deal with sessions (which VB gave you for free just by virtue of the fact that the program ran continuously in memory), concurrency, logging, IIS hosting, and loads of other complexity. The functionality gains are huge over your VB program: easy access for multiple distributed users. It's just not so visible since it's just an expectation of the platform.

Five years later, now your standalone ASP pages are losing out to slicker competitors. Now every good site has on every page a banner and breadcrumb trail and sidebar menu and search box. That's not something that ASP does, unless you fake it with piles of server-side includes inserted into every page. So you move to ASP.NET with its concepts of master pages and HTTP pipeline modules and hierarchical controls. These give loads of functionality over and above older ways of doing things, even if you use only a small part of it. Multipliers of effort now exist in places and degrees that weren't previously possible.

Now your business wants federated single-sign-on with a partner web site and company. This wasn't even conceivable for a desktop Win32 app twenty years ago. But now you can implement it by invoking a few WIF library calls from the correct layers of abstraction. Sure, it'll take longer and more complexity than your single login box in your VB desktop application. But it's flexible and scalable in ways previously unimagined.

Or think about the back end. Twenty years ago, that was an Access or Sybase database where 5000 rows was a lot. Now modern database platforms scale past five billion rows, on any number of servers across a farm, with all sorts of automated procedures for live backups and encryption and failover and sharding and whatever else.

Maybe you're thinking of SQL Server Reporting Services? Yeah, it seems like it takes a long time to implement that compared to a one-off report with some charting control. But you get whopping loads of functionality along for the ride: pagination, filtering, printer formatting, linkage to CRUD actions, ability to clone the report for editing. You don't think about the functionality because it just comes as expected with the platform. And yes, some of the complexity will leak out into your application code ("no, don't page-break between the transactions for stock sale and cash credit.") But paying the price on an apparently slower or overengineered implementation really can give you highly leveraged multipliers of effort.

Recalibrate your notion of "same functionality" and you'll see why the software industry has gone where it has.