Abstract:Historically, programming languages have been-benevolent-dictators: reducing all possible semantics to specific ones offered by a few built-in language constructs. Over the years, some programming languages have freed the programmers from the restrictions to use only built-in libraries, built-in data types, and builtin type-checking rules. Even though-arguably-such freedom could lead to anarchy, or people shooting themselves in the foot, the contrary tends to be the case: a language that does not allow for extensibility is depriving software engineers of the ability to construct proper abstractions and to structure software in the most optimal way. Therefore the software becomes less structured and maintainable than would be possible if the software engineer could express the behavior of the program with the most appropriate abstractions. The idea proposed by this paper is to move composition from built-in language constructs to programmable, first-class abstractions in a language. We discuss several prototypes of the Co-op language, which show that it is possible, with a relatively simple model, to express a wide range of compositions as first-class concepts.
MotivationThe software engineering discipline faces many challenges; one of the important challenges is to cope with the changes that need to be incorporated into software systems during their lifetime. A particular difficulty is that small, local changes in the requirements of a system, often lead to non-local changes in the software. This is caused by the fact that the structure of the implementation tends to be significantly different from the structure of the problem domain.Another software engineering challenge is managing the complexity of software (Royce, 2009). We are building increasingly large software systems. Such systems encompass a substantial amount of inherent complexity; partially in the problem domain and partially in the solution domain. However, the realization of these systems also introduces a large amount of accidental complexity (Brooks, 1987), while going from the conceptual solution to a realization model.A key argument adopted in this paper, and previously coined, e.g., by Brooks (Brooks, 1987), is that the limited ability of realization models to accurately represent the concepts and their interdependencies in a conceptual solution is the main cause of accidental complexity. As a result, the complexity of realizations is typically substantially larger than the complexity of the conceptual solution.In software engineering, a key strategy for dealing with change and managing complexity is "divide and conquer": achieve separation of concerns (Dijkstra, 1976) by dividing a solution into building blocks and delivering working systems by expressing proper compositions of these building blocks. The history of programming and design shows a steady movement towards supporting higher-level abstractions of building blocks and more advanced ways of expressing such compositions. For example, object-oriented and aspect-oriented progr...