I’ve often heard it said that DSLs make a codebase harder to understand, because programmers familiar with the language the codebase is written in now have to learn the DSL as well. Here’s my problem with that argument: every codebase is written in an embedded DSL. More often than not that DSL is ad-hoc, informally specified and bug-ridden, but a DSL all the same.
The syntax may be familiar to anyone who knows the general purpose language it’s written in, but the semantics are just as hard to grasp as any other DSL out there. Usually, harder to grasp, since there’s so much more code to read to understand what it is exactly that’s going on.
I can write C++. Does that mean I can download the source code for Firefox and jump straight in to fixing a bug? Of course not.
I really think that Lisp got it right, and that the next time I write any Emacs Lisp I really ought to think of what language I can express the problem domain better, then implement that language. It’s something that feels right but that somehow I’ve never actually really done.
It’s true that designing a DSL means designing a language, and that not all programmers are good language designers. But what’s the alternative? Use no abstractions? Let them write a giant mess for others to attempt to navigate?
In the end, isn’t the art of language design a way to state solutions to problems, simply? To capture the essence of what’s trying to be said/programmed elegantly?
I don’t know about you, but to me that just sounds like programming.