I would argue that meta-structures, modules, frameworks, platforms, and services are all higher-level feature groupings than classes. My hierarchy of programming system abstractions:
- services
- platforms, solution stacks
- frameworks
- modules, packages
- meta structures: metaclasses, higher order functions, generics, templates, traits, aspects, decorators
- objects, classes, data types
- functions, procedures, subroutines
- control structures
- lines of code
Meta-structures like metaclasses,
higher order functions, and
generics
clearly add abstraction to basic classes, functions, data types, and data instances. Traits, aspects, and decorators are newer mechanisms for combining code features, and similarly 'accelerate' other classes and functions.
Even pre-object languages had modules and packages, so putting them above classes might be debatable. Bu they contain those classes and meta-structures, so I rank them higher.
Frameworks are the meatiest answer--they orchestrate multiple classes, meta-structures, modules, functions, and such in order to provide sophisticated high-level abstractions. And yet frameworks still operate almost entirely in the realm of programming.
Solution stacks or platforms generally combine multiple frameworks, subsystems, or components into an environment for solving multiple problems.
Finally, there are services--often deployed as Web or network services. These are architectures, frameworks, solution stacks, or application capabilities delivered as complete bundles. Their internals are often opaque, primarily exposing administrator, programming, and user interfaces. PaaS and SaaS are common examples.
Now, this progression may not be entirely satisfying, for a few reasons. First, it makes a neat linear progression or hierarchy of things that aren't perfectly linear or hierarchical. It covers some abstractions like "stacks" and service that are not entirely under developer control. And it doesn't posit any new magic pixie dust. (Spoiler: There is no magic pixie dust.)
I think it's a mistake to look just for new abstraction levels. All the ones I listed above have existed for years, even if they haven't all been as prominent or popular as they now are. And over those years, the abstractions possible at every level of coding have improved. We now have general-purpose, generic collections, not just arrays. We loop over collections, not just index ranges. We have list comprehensions and list filter and map operations. Many language's functions can have a variable number of arguments, and/or default arguments. And so on. We are increasing abstraction at every level, so adding more levels isn't a requirement for increasing the overall level of abstraction.