Recording Venue: Skype
Guests: Martin Fowler, Rebecca Parsons
In this episode, Markus talk with Martin Fowler and Rebecca Parsons about domain-specific languages (DSLs). Topics covered include a definition of DSL, Internal vs. External DSLs, reasons to use DSLs and reasons not to, the DSL lifecycle and the role of language workbenches. The conversation is loosely based on their book Domain-Specific Languages.
Transcript brought to you by IEEE Software
Markus Völter 00:00:16 SE radio brings you relevant the detailed discussions about software engineering topics at least once a month. Thanks to our audience and the partners listed on our website. The podcast, welcome to a new episode of software engineering radio. This time we have an episode with mafia follower and Rebecca Parsons about domain specific languages. And as usual, we start with our guests introducing themselves. Also, I don’t think there are many listeners who don’t know you guys, but we should still do that. So why don’t you introduce yourself?
Martin Fowler Well, I’ll start off my name’s Martin Fowler. I’m a internet loud mouth who speaks a lot incessantly on the topic of software development and my particular interest in domain specific languages was reinforced by the fact that I spent rather more years than I’d like to think writing a book about them.
Rebecca Parsons 00:01:14 And my name is Rebecca Parsons. I’m the chief technology officer for ThoughtWorks. Um, I’ve got a strong background in programming languages and I’ve always been something of a languages geek and, uh, the, the work on domain specific languages with, with Martin, I was primarily focused on it from the programming languages perspective, but I also have a, um, significant interest in helping businesses build software better. And we believe in the long run, uh, domain specific languages are a good way to go about doing that. So we’re, we’re excited about the opportunity to, um, make more people familiar with domain specific languages and hopefully give us some new use cases for them.
Markus Völter 00:01:53 Right. Um, well, okay. So I guess we should start by first defining what a DSL domain specific language is since we’ve already been talking about it. So who wants to go, Oh, I should go with that. And of course I should have the definition right in front of me that I used in the book. Hang on a moment.
Markus Völter 00:02:17 Okay. So I have here the, the T the, a standard text on the subject, so nice to be able to say that, um, and in it, I have a definition, so I define it as a computer programming, language of limited expressiveness focused on a particular domain. Okay. And I, I talk about how there are elements of this definition of four of them. One is that it is a computer programming language. So it’s not, um, something like a business terminology or something of that kind. Right. Um, I mean, the idea of trying to build computer systems or the consistent business terminology.
Martin Fowler 00:03:00 Using what the domain driven design people call it, ubiquitous language is a good idea, but the domain specific language is something that’s executable by a computer, right? The second thing is that it’s a language, so it has a kind of language nature, which is a rather fuzzy definition, but it should have this quality that it feels like some kind of language, not just for instance, the sequence of API calls or something of that kind. The third point I make is that it’s a limited expressiveness, and that’s something I guess, that I’ve particularly focused on, um, in a, in a way to distinguish domain specific languages in general purpose programming languages. Um, so to me, the interesting thing about the main specific languages is that you, you can’t write an entire system in a DSL. You can only use it for sort of point parts of the system, right. And following from that, the fourth point is that they tend to be focused on a specific domain.
Rebecca Parsons 00:03:57 And I would also say from a programming languages perspective, that what constitutes a language, although in our nomenclature, it’s very often fuzzy, there are specific aspects of what it takes to be a language. And one specific part of that is what is the syntax of the language? What does it look like? What constitutes a legal sentence and in the context of a, of a domain specific language you want that syntax to make sense to within the con within the construct of the domain. And then the second aspect of, of a programming language that’s useful in this context is the semantics. What is the behavior or meaning that is expressed by a particular legal, uh, legal sentence. And so when we think about creating a domain specific language, we have to have an understanding of what are the concepts that exist within this domain that we want to be able to express with this computer language, what is the behavior that might manifest as a result of manipulating these concepts? Uh, as Martin points out, it has to be an executable language. And then the third thing is what is a natural way for people within the domain to put a different constructs together from their domain into something that would con uh, constitute this executable behavior,
Martin Fowler 00:05:13 Right? I mean, this, this topic of limited, limited express, and this is of course interesting, right? I mean, does this mean that all Diaz I’d have to beat declarative, whatever that exactly means, or, I mean, some people say that if a DSL contains things like expressions or statements, then it’s not a DSL anymore. So can you, can you maybe grasp that a bit more concretely this limited expressiveness thing, because I struggled with it all the time. Yeah. Well, it’s one of those vague boundary condition things. Um, for me, it’s really was triggered out of this. What makes the difference between a, a DSL and a general purpose language? Um, being focused on a domain is not quite enough. Um, the example I often throw in is the R language, which is useful statistics. Um, and it’s a very complete language. You can do all sorts of things with our, um, and although it’s focused on the notion of statistics, it’s power is such that it, it has a different feel to the kinds of things that when I was thinking of things like regular expressions or CSS or something of that kind, um, I mean, you could argue the Coldwell is a domain specific language targeted at certain kinds of business applications.
Martin Fowler 00:06:33 Yeah. And so the boundary condition, when focusing on domain, this didn’t feel very good, but when you begin to explore, well, it’s really about limited expressiveness and all sorts of overcome things come out of it. And particular, for instance, one of the arguments against using domain specific languages is that it’s complicated to build your own Pasa for instance. Um, but if it’s a domain specific language, we’ve limited expressiveness, the problem is way smaller than it is. And if you’re doing a general purpose language, and that affects a number of things, I think in language usage in design, if you have a simple language, a lot of the things we assume for general purpose languages, aren’t true. Right.
Rebecca Parsons 00:07:16 I would also say that the question about expressions depends significantly on what domain that you’re talking about. Um, a physicist, for example, is quite used to working in complex mathematical equations and trying to say a domain specific language that would be talking about physics wouldn’t have, um, expression or equation like concepts, w w would be ridiculous. Um, however, uh, if you look at a marketing application where you’re building business rules for D for determining offers, that might be going to a customer much more than simple addition and subtraction, or maybe percentages, um, would, would not be natural within the domain. So we do have to think about it from the con from, from that construct. Um, I do believe part of the reason that, uh, DSLs have been so hard to work with in the past though, is the fact that when people start with the limited domain, then they toss in, well, we need conditionals.
Rebecca Parsons 00:08:14 Then they toss and we need iteration. And all of a sudden you’ve got a general purpose programming language that actually happens to have some accounting principles in there as, as first-class objects. And so the ability to, to segregate these domain scripts from the other processing that goes around them, I think it is a critical component for us to be successful, um, in domain specific languages. I don’t think that implies, it has to be declarative though. There are still procedural or behavioral aspects to it. Um, but, but we do want to make sure that that domain language doesn’t get big enough to become Turing complete. Yeah. Well, okay.
Markus Völter 00:08:56 Um, let’s leave it at that. Um, and that might be a bit too extreme. Yeah. Not too far. Actually.
Martin Fowler 00:09:03 I look at tiering complete, I look at tiering completeness as a smell. Right. It’s a sign that there’s something probably wrong, but it certainly isn’t an absolute sign of a problem.
Markus Völter 00:09:12 Yes. Yeah, absolutely. Um, so you also mentioned before that a DSL is more than an API or a framework. Um, and now there are of course internal and external DSLs where internal DSLs are embedded in a host language, which brings them potentially dangerously close to API APIs and frameworks. So, um, can you try to draw the boundary first between frameworks and internally as ALS and then obviously, uh, regarding Exxon Lia sales?
Martin Fowler 00:09:43 Well, this is another of these very fuzzy boundaries on it, right? Um, for dif I mean, it’s essentially, if you look at it and it’s sort of very simple elements. Yes. An internal DSL is just a string of API calls. Um, but what’s interesting is comes down to this part of our definition of it, having a language nature that you should when you’re writing an internal DSL, although you happen to be writing Ruby, if it’s a, a Ruby internal DSL or Lisbeth it’s well less. So in this case, you shouldn’t have a feel that I’m writing Ruby. It should feel more that I’m writing this internal DSL. Yeah. And I think what it boils down to is that with API calls, when we, when we tried to design an API, we try to make each API call stand on its own. It’s naming, um, its definition.
Martin Fowler 00:10:37 And ideally we should have a limited amount of temporal linkages between when we make the API calls. And we typically understand them by reading down something like Java darken, it’s one method, another method, another method, but with an internal DSL, they’re designed to be composed together in sentences. So individually the methods may not make much sense. You’d look at them and say, well, that’s a stupid name. And some of the ways in which it’s, you know, the way it takes its arguments and that kind of thing just doesn’t make sense if you look at it standalone, but it makes sense in the context of a sentence. And that albeit a very fuzzy distinction is I think the one that, that separates out internal and external internal DSL, some API APIs,
Markus Völter 00:11:18 It’s certainly the best definition in that sense I’ve ever heard because, um, there isn’t, I mean, it’s, you know, people just say things like, well, it has to feel like a language, but what, what does this mean? And I think you’re, you’re you’re attempt, or you’re, you’re, you’re, you’re tying this to the names of the methods and the independence of the methods from each other is a very good, very good way to put it. Yeah,
Martin Fowler 00:11:40 It was, that was hinted to me in a conversation I had with a former colleague of ours, Mike Roberts, and he said is the difference between an internal DSL and an API that an internal DSL has a grammar. And that was really what triggered that fault thinking. Well, of course you can argue, you always have grandmas, but very limited grammars. We have an internal DSL, you’ve got a little bit more. And hence, that led me to this fourth of the sentence becomes the fundamental concept, however, internal DSL, however,
Markus Völter 00:12:10 Internal DSLs don’t use formal grammars to specify the valid syntax syntax of a structure of sentences, right? I mean, that’s one of the main principles that, that distinguished them from, from external DSLs, but you usually do use a grammar or something similar.
Rebecca Parsons 00:12:25 Well, I would assert as a language as type that even if you don’t write down the grammar and a formal grammar specification, you have a grammar for your language that does exist. And that, that, that grammatical structure does imply the relationship between the different aspects of the sentence. It is obviously, um, more explicit in, in the external DSL case, but in the internal DSL case, there is still a grammar because you have to have some way of mapping between these, these structural elements in your sentence, to the, the, the, the semantics that are supposed to result from the, from the combination of those things, whether they, whether it be nesting, whether it be modification of a clause, all of the different, uh, cement or syntactic, um, approaches that we have for building up a grammar, those are the ways these different, uh, semantic domain concepts can be related to each other.
Martin Fowler 00:13:21 And that’s something I float into the book a bit more because when I’m, when I was looking at the various techniques you have of combining elements in an internal DSL, I found those an interesting correspondence between which techniques you’d use. And what was your logical grammar that you might have in place? Certain grammar, constructions implied certain ways of using language constructs, not. I found that a very helpful way of thinking about your options when it comes to an internal to yourself, right?
Markus Völter 00:13:54 So is it fair to say that all languages that are friendly to internal as ELLs have some of the same language features like the ability to avoid parentees parentheses parentheses, or, you know, commerce or something like that. So is there like the set of language features that makes the language DSL friendly?
Martin Fowler 00:14:14 I suspect so, although it’s not something I thought about in a huge amount of depth, um, but yeah, certainly the minimizing of unnecessary punctuation, whether it be key words or simple things like commerce or parentheses certainly helps. Um, I think it also bird, certain constructs are useful. For instance, the ability to have closures is really useful because it allows a hierarchic nesting that is otherwise difficult to achieve. Um, well, it’s a hierarchy nesting combined with being able to alter the execution order, um, which is useful for that. Um, in addition, I think, um, significant, um, syntactically significant white space, like actually becomes a problem for an internal DSL because if you want, because often you want to format your DSL differently to the way the language normally is formatted, right. In order to bring out the DSL quality of it. And if you’ve got, um, if your indentation is syntactically significant, you can’t do that. And, um, so I think that’s a hampering piece as well. Okay. So one benefit I think of internal DSLs is that they potentially can interact very well with the host program. Although that of course can also be a disadvantage if you want to disconnect the domain people from the implementation. So, um, you want to elaborate a bit on these tradeoffs embeddability, composability with GPLS and the domain expert, you know, usability.
Martin Fowler 00:15:53 Well, that boundary condition of ING is, is really quite interesting, cause it really does cut both ways. I mean, some problems it’s really nice to be able to mix easily between the DSL and the general purpose language. And that’s where an internal DSL is very, very suitable. Um, the example that immediately Springs to mind mind there is built description systems such as make rake and, and the like, um, I’ve definitely come to the view that having an internal DSL, which is what rake the Ruby built system uses is much better than having an external DSL, which is what make and ant effectively have. Um, but there are other problems where it’s good to have a hard line where you say we don’t want to, um, maybe if we let that line be too fluid, then it’s too easy for a host language to overwhelm the DSL for people to write expressions that go outside of the boundaries. So it really, I think depends on the problem as to whether you want something with a hard boundary or a very fluid boundary. And, um, and so that’s really an interesting case of sometimes good, sometimes bad.
Rebecca Parsons 00:17:04 And I would actually turn the question around a little bit. Um, one of the, one of the problems with an internal DSL is that you are bound by the syntax and the competent computational model of your host language. And if you buy the assertion that what we’re trying to do is express things naturally within a domain, if what is natural wasn’t within that domain does not map cleanly to the computational model or the syntax of, of the host language you’re going to, you’re, you’re going to have to alter what you would like to do in the domain language to make it possible, to, to be in the internal language. So I would, um, I would like to start from what is the requirement of the language, but then of course I’m a languages person.
Markus Völter 00:17:50 I mean, I think it’s really interesting. I mean, if we go back two or three years or four years, and at least stay a little bit in the mainstream, we had tools like antler, our ex text, which were basically, uh, tools for building standard on externally as ELLs. And they were internally as ELLs in the languages. You already mentioned. Now things are changing a bit, right? I mean, for example, with X text, while you can’t easily extend Java, you can include an existing expression language, uh, X bays in, in MPS, you can easily extend Java or C. So, and not in a way where you use meta programming with the host language, but rather by really literally extending the language definition. So that is another form of if you will embedded DSL, it’s not really internal in the sense as you have defined it. And it has many of the advantages of both, you get tool support to get a real grammar, uh, or whatever the formalism is. And you still get close integration between, uh, you know, GPL and DSL. So I think interesting things are happening there to, to give you more options in this space.
Martin Fowler 00:18:54 Yeah. And that was, it was something we experimented, um, several years ago with intentional, uh, the idea of just combat composing different languages within the same piece of script as particularly nice for something like where you’ve got a, a system that student go doing sequel, and you can put the SQL right in there, you can put your code right in there, and you can also have very nice linkage to the test cases right in there as well. Um, and I thought that was a very interesting direction to take, but this is where you move into the, we’re going to need more sophisticated tools, which of course is what things like and an NPS are pushing towards. Yeah.
Markus Völter 00:19:31 And maybe just as a teaser, uh, not too long from the time when you hear this episode, that will actually most probably be an episode on se radio, which explores this idea a little bit further. Um, okay. So, um, and we’ll talk about some of the tool aspects later again. Um, so another concept that I find very prominent in, in your talks and in your book and which I don’t always agree with in terms of the prominence you give it, uh, is the, the semantic model. So, so can you elaborate the difference between, you know, the semantic model, the metamodel of the DSL, the abstract syntax, all these things.
Martin Fowler 00:20:13 Okay. Um, the example that I like to use to think about this is if you’ve got something that you want to model using a state machine construct, um, if you have a problem where you’ve got to deploy a hundred different systems and they all have slightly different behavior, but their behavior can be nicely captured through a state machine, then a natural route to go. Certainly if your other modeling direction is you say, well, let’s build a model of state machines, and then I can populate it 50 different ways for 50 different cases. And that’s something database people do buy, I mean, state machine things inside databases or object people do it by creating object models of state machines, et cetera, et cetera. Now, a DSL can be used as part of that, cause it’s a good way to express a state machines so that you can write state machines down is to do it in terms of writing a DSL.
Martin Fowler 00:21:13 But what you’ve then got to, you’ve got this concept of a model of state machines and a DSL that is able to express things in terms of state machines. And my feeling is that they are both very important and what’s more, there’s actually in many ways more important to this, to having a good model, a lot of the advantages and disadvantages that people state for DSLs can actually be stated in terms of whether they’ve got this kind of model or not. They may call it a library. They may call it a framework, but it’s fundamentally a thing that allows you to express things in terms of that model, what the DSL does. I refer to it as a thin veneer over the model, because it really just allows you to express what you’re doing in that, um, in that domain a little bit more cleanly, but it’s then gonna populate that model.
Martin Fowler 00:22:05 So a DSL has a syntactic facade around a potentially complex framework. Yeah. And the point is, I’ve seen a lot of DSLs implemented that don’t use this approach, but the problem that, well, the advantages of having a clear model is that for start, it allows you to express semantics in terms purely of the model, without worrying about the syntax of your DSL and how are you going to pause it and all that kind of thing. It allows you to test the model independently of how it’s populated through the DSL. And that I think is a very useful separation of concerns.
Rebecca Parsons 00:22:42 Hmm. I think it’s also important to distinguish between an abstract syntax tree and a semantic bottle. There may be a close correspondence, but there may not be. And if you, if you think about things again, from the perspective of the domain and what the Lang, what this DSL is trying to express relative to the domain, you have, you have concepts in that domain and there are, there are behaviors that you want these, these concepts to be able to manifest. And that’s the semantics of that domain. And you can start from the domain. What are my sensible, I’m trying to avoid using the word objects. That’s why I’m saying concepts, because this isn’t, this isn’t Oh, necessarily even. So I have concepts within my domain and I have behavior that might manifest itself in my domain. And there is something that constitutes interaction. My domain that might look like a procedural, um, step one, step two, step three, or workflow, but it might look like something very different, like a state machine behavior, um, as an example.
Rebecca Parsons 00:23:42 And so I can talk about the, of this language in the, in the language of the domain. And I could talk about the semantic model in that con in that context. And then I simply look at, okay, what is the syntax that I want to layer on top of this to allow me to populate the, the, the representations of these concepts that I have in my language, and to express the behavior that I desire of, of these concepts. So separating out the, the, the syntax tree, I think is important, um, because you, the, the purpose of the syntax and the purpose of that semantic model are in fact quite different.
Martin Fowler 00:24:22 I mean, the, the reason why, why, why I sometimes disagree a bit is that first of all, in embedded systems, you can’t do it often because you have to be very efficient. You can’t have a big framework. So that that’s one thing, right? You don’t want to just populate a framework. You want to generate very optimized low-level code. So go hang on that point. I mean, in the embedded systems you’re talking about, do you have the positive of a domain specific language as part of your embedded system? No. No, of course. Well, that’s the point, right? The cement, once you have a semantic model, and I didn’t talk about this earlier on, but it is a follow on thing. You can then choose to execute that semantic model directly, effectively by interpreting it all by doing cogeneration off the semantic model. Okay. Then we’re talking about two different things that we need to clarify.
Martin Fowler 00:25:10 Um, there is the idea of having a framework, maybe one that already exists, or maybe one that you’ve built for the purpose, for which you then build a DSL, which basically populates the framework. And then the framework runs that does not work in embedded systems for the reasons of the overhead. Of course, what you can do and maybe should do is you have a clearly defined semantic model, which will then either generate or interpret in embedded, certainly will probably generate. And that is something you decouple from the syntax and the abstract syntax, but these are two different things. Oh, I guess I see them as the same thing, just how you got there, right? If you’ve got an existing library or framework, you might say, okay, I’m going to make that be my semantic model. But if you’re going from the beginning, you’ll build the semantic model.
Martin Fowler 00:26:00 And you’ll DSL syntax typically hand in hand together. And then of course, it’s, it depends on the circumstance, whether you need to generate or not off the semantic model and going one step further, depending on the tool I use, the language structure will be very close to what you would ideally define this as a ManTech model. And then you can argue whether you actually need two of them. Right. And that is basically my point, but, okay. So we’ve solved that for me, is that particularly with cogeneration case, you don’t go directly, you don’t write in your grammar file, the generation code author, which I have seen people do. And that’s where I feel there’s an opportunity to separate consent. Okay. But, but I mean, we shouldn’t probably discuss this forever, but if you use, for example, X text, you, you write a grammar, the grammar automatically creates a meta model, which is the abstract syntax of your language. And then you generate code from that. So you don’t embed a generation stuff in the grammar, which is as, I mean, this is, this is this bullshit, right. But I would not in this case create yet and novel, let’s say EMF I-Corps file for the semantic model and then transform the abstract syntax created by X text into that one and then generate code.
Rebecca Parsons 00:27:16 Yes. But, but that, that depends on the qualities of your semantic model and how closely that maps to, what is the natural syntax within the domain. It might make sense to go directly from the syntax tree. It might make sense to go from the Semtech straight to a model that makes it easier to do the cogeneration. And that’s going to be very problem specific.
Martin Fowler 00:27:36 Yeah. I mean, for instance, if you’re evaluating arithmetic expressions, then an abstract syntax tree is an excellent semantic model. You can have the same artifact playing two different roles and that’s perfectly okay. Yeah. Well then we agree. I think so violently boring, you’d already touched the point of interpretation versus cogeneration. I just think we should cover that to some extent, I guess people know it from interpreters and compilers, it’s basically the same story, right?
Rebecca Parsons 00:28:07 Yes. Yep. Um, basically when, when you’re looking at interpretation, what you are, what you are executing against is this semantic model, whether it be an abstract syntax tree or, or some other representation. Um, and it’s, um, within the, the, the compiler world, you’re very often, uh, working off of either an abstract syntax tree or some other internal representation of the program, be it a program dependence graph. So it’s exactly analogous in that context. And the nice thing is you can make the same kind of choices that you can make in a language, um, uh, scheme, for example, you can both interpret and compile directly to native code. You have the same kind of choices where you can have the moral equivalent of the read about print loop to do quick debugging and such within the, in your DSL. And then when you want to, you can compile it down to two something or cogeneration, uh, for, for more efficient execution. So there is, there’s no conceptual difference between what’s going on here in DSLs and what we talk about in programming languages and compilers,
Martin Fowler 00:29:10 And with perhaps an extra twist that when you generate code, you actually have the choice of do I actually generate effectively a model in data that I interpret in the generated code structure? Or do I just go for straight ahead, um, code with no notion of a model in there, and that has its own trade offs, but that’s an independent decision of all the other pieces of the deal chain that there is another nice thing that helps to confuse people. And that is that a coach generators are actually
Markus Völter 00:29:42 Because they interpret the model and there’s a side effect. They generate code.
Rebecca Parsons 00:29:46 Yes, exactly. Exactly. The, um, the output domain for a code generator, um, is, is, is native code. And that happens to be just different than the actual domain of what,
Markus Völter 00:30:03 Like ideally is to write an interpreter and then have some magic of automatically deriving a compiler for that. Uh, I think this is known as I’m not really, that’s kind of beyond what I really talk about, but I think it’s called a partial evaluation. Is that true? Anyway, the point is, have you come across, I mean, I know there is work in compilers in that space, but have you come across that kind of approach in DSLs where, where you can automatically derive a compile of our target platform from an interpreter that you’ve maybe written in some abstract specification
Rebecca Parsons 00:30:41 DSLs are not nearly that sophisticated yet. I certainly haven’t seen seen anything. That’s, that’s, that’s equivalent to that in the DSL space. Um, there are, there are certainly ways that, that I could imagine that, that you could do such a thing, but I certainly haven’t, haven’t heard it, haven’t heard of it being done anywhere.
Markus Völter 00:31:01 Okay. I mean, the, the first ingredient you would need, there is actually some kind of formal way of specifying the semantics. And that is an interesting question in itself for DSLs. Right?
Rebecca Parsons 00:31:11 Exactly. And, and, you know, the way I can actually see it happening is if you do have something that is more closely tied with, with a framework where you, you actually have more, more of an ability to, to take advantage of, of, of some connection between something you have in your semantic model and executable code, you already have available to you with this framework. Right. So that’s probably the obvious analogy that, that I can see at the moment. But, um, I don’t think that that’s, I don’t think that’s something that’s going to be, um, I don’t think that’s, uh, that’s going to be a popular early topic. We, we still have a whole lot of questions in terms of just what constitutes a good DSL, where the boundaries go and yeah, and trying to, trying to get that far down the road, I think is, is still quite a ways off.
Markus Völter 00:32:01 Okay. So let’s come back and address some more practical topics again, uh, you know, after this theory, uh, why would one use DSLs? What are the benefits?
Martin Fowler 00:32:15 There are two primary benefits that I tend to talk about. Um, the first is simple program of productivity. And for this, my example is regular expressions. I never a very cryptic construct and all the rest of it. But if you look at a regular expression, um, and you compare it to the code that you’d have to write without the regular expression, it’s much easier to understand modify, rate the regular expression. And so a lot of DSLs just helping that terms of program and productivity. I mean, that’s part of the reason why rails got so popular because they express so many of what they did in these little DSLs scattered around the framework and people like that. So that is in itself is enough in a lot of cases, I think. Um, but there’s also a bigger prize out there, which is, um, for that, my example is CSS.
Martin Fowler 00:33:08 Now that is a programming language that most of the people who programming it don’t think of themselves as programmers. I think of themselves as web designers, and they’re describing this really quite complicated language in terms of it semantics. Um, but they’re able to manipulate it in terms that they at least have some sense that I understand. Now the value here is not so much that, um, with, with this kind of DSL, you want domain people to be writing it themselves. So there are certainly cases where it happens. I think the biggest gain is that you can get to a point where domain, people can read the DSL and have a conversation based on it with developers or parapros then, or pair program or that program. Because then what you’ve got is a very rich information channel between domain people and developers. And since that divide between domain people and developers is to my mind, the biggest problematic divide.
Martin Fowler 00:34:09 We have many divisions in software development. Um, anything that can bridge that gap is really nice. Now, of course, it’s not easy to be able to pull that off. Um, but the benefits can be quite huge in doing so. Right. And, and just as a remark there, I kind of distinguished between like application or business domain DSLs and technical DSLs based on the target audience. And many of the tradeoffs we’ve discussed before also kind of hinge on this thing. I mean, for example, external DSLs with good tool support are better for domain people. Whereas internal deals, the outs with tight integration in the programming language may be more interesting for technical people. So there are, there are some relationships there I think. Oh, absolutely. I think, I think internal DSLs are particularly attractive if your only audience is programmers because when they get to programming their regular language, particularly if it’s a language that’s suitable for DSLs. Yeah. But as you move to more, more external people, then the freedom of syntax and the freedom of semantics that you get with an external DSL become a lot more attractive.
Rebecca Parsons 00:35:11 Well, in any, even just the expectations of, of the tools. Um, I know that the developers with IDs, they’re, they’re very bound to, to the keyboard shortcuts and, and there are methods of interacting with a development environment tool for developer that seems very unnatural for, for business people. Um, when, when you watch someone who is a true wizard at manipulating an Excel spreadsheet, they don’t interact with that development environment in the same way that, that a truly expert developer interacts with, with a Jada ID or with, or with visual studio. And so the expectations that you have around tools are very different as well and, and how, how it, you can, uh, provide a tool that is natural for someone in a domain is very different. As soon as you get out of, out of the technical domain into the application domains,
Martin Fowler 00:36:03 You mentioned the E word is XL at DSL. No, I think it’s a general purpose programming. Absolutely. A general purpose programming language and a very interesting platform because of the fact that it is the most widely used programming language for people who don’t consider themselves to be programs. Yeah. There is another, another, a connection there. I think wherever XL is used at DSL is lurking somewhere.
Rebecca Parsons 00:36:33 Yes, I would agree.
Martin Fowler 00:36:35 Yes. There was actually a research project going on at the T a technical university in Delft where they are working on exactly that connection, where they are trying to understand why and how people use excellent XL in business context and see to what extent DSL DSLs can be a better solution there. Um, any other advantages of DSL before we look at the downsides? No free lunch, of course.
Rebecca Parsons 00:37:02 Well, I, I do think one of the important advantages, uh, particularly of an external DSL, although you can pull it off in an internal one, it’s more difficult is that you, you can express the behaviors that are associated with those domain concepts in a way that’s natural to the domain. And this, this gets into the, these alternative computational models where, where you can actually think about a problem and model it and express it as a data flow system, even if you are going to execute in a completely different, um, uh, computational context. And so for, uh, not, not so much potentially in business domains, but when you start to think about a scientific domains, uh, that ability to, to change computational models, I actually think is an important one. And trying to figure out a way to express, um, express, uh, a concept not only that is not natural, um, in the programming languages, but even the behavior is a stretch.
Rebecca Parsons 00:38:07 I mean, programmers are stubborn. We know how to take, take on an object oriented language and make it, do whatever we want it to do. But if it’s not natural in that language, it’s going to be even more difficult for the domain person to really understand what’s going on. And so trying to, uh, being able to separate out the semantics of the model with this alternative computational model and then build the execution engine for that separately, I do think is, is an advantage of someplace where you would look to, to use DSLs that also provides us a way where we can start to address some of the, some of the performance characteristics as well. Where, where, if, you know, if you’re looking at, at particular scientific computations, this, this computational model might be more efficient than that, because we know some things that the characteristics of the data. And so those are things. If we can separate those things out, it’s easier to express then trying to explain to someone, okay, well, you’ve got to write two versions of this program because if your data looks like this, you don’t want to run it the other way. Yeah.
Martin Fowler 00:39:06 I mean, yeah, go ahead. Yeah. I think that the alternative computational models is particularly interesting to me because I’ve come across from time to time teams that will build, um, uh, this rich semantic model of part of their domain in there. That’s incredibly productive, but it’s, it’s both, it’s a mixed bag because the people who understand that Symantec model, they can do an enormous amount really quickly, but a lot of people find it very difficult to learn and very difficult to approach. And so one of my hopes is that people who are taking on DSLs will say, Oh, by making a DSL as a front end to this rich semantic model, I can actually make the whole thing more approachable because instead of looking around in inside data structures, trying to find out where the program is, they can actually see the program, um, in a much more explicit form.
Martin Fowler 00:39:56 I mean, what really is interesting. I mean, when people start using DSLs, they often do that because they think, you know, we can write programs in a more concise way and we can generate all this crappy code we don’t care about. So that’s the first look at yourself. Then at some point they noticed, well, Hmm, actually there is another benefit. The syntax can be so that we can integrate domain experts and, and we can capture our business knowledge. So that’s kind of the next step. And then even further people come about this, this alternative Symantec models and notice that based on this, they can do much more interesting things, not just in terms of writing less code, but making a more interesting analysis, proofs, correctness, you know, constraint, tank stuff. So it’s really interesting how as people use DSL, it’s more, the somewhat more advanced or less obvious topics become more important. Yeah, I agree. So downsides, there have to be some, yeah.
Rebecca Parsons 00:40:58 I find, I always find the language to caffeinate, um, complaint an interesting one, because if you are doing your domain specific language properly, that language expresses the domain. And unless you believe that you can effectively program within an application context and not understand the language of the domain, yes, you’ve applied a formal syntax to it, and you’ve applied a formal semantics to it rather than the more informal notion that we often carry around in our head whenever we’re programming in a particular domain, but those, those exist in those language languages exist. And so I think all we’re doing in this context is making those things more explicit. And perhaps because we are being more explicit about the existence of these different languages, the places where these languages interact or intersect, or perhaps heaven forbid conflict, um, will become more obvious because we are talking explicitly about these languages rather than them lurking in the background without us paying attention to them. So that that’s one that, that I, I have a difficult time actually calling it out as a, as a disadvantage to me, it’s, it’s more a feature.
Martin Fowler 00:42:10 Yeah. It just occurred to me. I might have to, we might have to go slightly matter cause we didn’t explain what the language could cough and your problem was, so I’ll explain it. Shall I? You may want to put this in front of no, no, no, no. We don’t leave it up to you. Um, so the language cacophony problem is basically saying, well, if we have start using DSLs, then this system, instead of just being a Java system, it’s got 30 languages in it and people are gonna find it much harder to learn and understand because I’ve got to deal with 30 languages instead of one. Well, otherwise who deal with 30 frameworks, how that exactly. And that’s the counterpoint to that. It goes, you’ve got to learn the frameworks anyway. Um, and if the language is there any good, then they make the frameworks easier to deal with. Now of course the bad language is going to make things worse, but that stuff always makes things worse. And there are plenty of bad frameworks out there. Right. Okay. So let’s, let’s put that into the undecided category, but there must be some real disadvantages. Well, there’s a real cost of building and you have to build the necessary constructs to make a domain specific language. And that input entails some cost of building and some cost of maintenance.
Rebecca Parsons 00:43:22 Yeah. And I think too, when, particularly when you think about, uh, domains that are changing rapidly, it’s one thing to modify your code and modify your test to express an, a new business environment. If you have a lot of your business logic encapsulated in a domain specific language and the business context changes to the point where, um, you want a different language, you have, you have a very different kind of migration problem on your hands in terms of how do I map this domain language, um, to this new domain language. So I do think there’s there’s questions around, what does it really mean to evolve a language? Um, what does it mean to migrate old scripts across the evolution within the domain specific language? And, and so I do think there there’s a, there’s a complexity there that we really haven’t figured out how to grapple with.
Martin Fowler 00:44:14 Yeah. And this, this is also leads to the, what I find is one of the interesting comments. That’s not just the true of, of domain specific languages, but generally the frameworks as well, which is you have this tendency to create blinkered abstractions where you, once you’ve got a good abstraction, it kind of puts your blinkers and you can’t
Martin Fowler 00:44:32 See things that don’t really cleanly fit into that abstraction. Um, and there’s, I think a, an argument, a reasonable argument that domain specific languages can exacerbate that problem. Um, I mean, you get it in any case, but if you’ve got a really nice DSL and it really likes abstraction, then yeah. I can see that there’s a definite danger there that you’re not going to see things that fit outside of it. Yeah.
Rebecca Parsons 00:44:55 I think that there’s another issue too, and that we really don’t yet understand what constitutes a good DSL. And so the probability of creating a language that doesn’t necessarily serve the needs well of the users, particularly if, if the focus is on this, we’re going to set our domain expert down with our, with our developer and have them pairing on, on this. You, you, if you’ve got a bad language, you are probably going to make that communication channel worse rather than, than, than better. And we still really don’t know, um, how to approach language design in general for, for a DSL there, there’s still a lot of questions out there on what, what constitutes a good language design, you know, we can talk about it very conceptually we’ll, it should, you know, naturally express the concepts, the concepts, but what does that, what does that mean? How does that manifest itself when looking at a particular domain and a particular language? And so we do have the possibility of, of making the process worse rather than better if we don’t get the language. Right.
Martin Fowler 00:45:59 Hmm. Yeah. I just always think, I mean, what’s the alternative, I mean, not having a language at all using word documents or using bad frameworks, I mean, you know, bad frameworks, which don’t capture the domain are also a problem. So I guess whenever you’re trying to solve a whole class of problems or a whole domain, then you always have the problem of what is the right abstraction and how do you fit in the 20% that don’t fit the abstraction. So, yes. So the question is, how quickly can you, well, so maybe, maybe if you have a domain that evolves quickly, maybe you have to build a language that allows you to build some abstractions in the language. So you don’t have to change the language if some sections change, things like that. Right?
Martin Fowler 00:46:42 Yeah. Although if it’s really fundamental changes to the language, then I think that’s an issue because, uh, the big, the ability to build new abstractions in the language is to my sign. Another sign of a general purpose programming language. Well, I, I agree, of course, but on the other hand side, I mean, I have seen examples where, where it does make sense in some limited cases to, to, to, for example, very, very primitive case. I have a bunch of hardware building blocks. And other question is what properties can I ask this hardware about? Like temperature, speed, whatever. And if you code that into the language, that may be bad because if the driver now supports an additional data value, you have to change the language. So rather you put it into a, you know, you define these things in the language, you know, things like that.
Martin Fowler 00:47:26 Yeah. But again, I would say the word that you, those limited yes. Limited abilities to build your abstractions is okay. Yup, yup, yup, yup. Right. Domain specific abilities in some sense. So, yeah. Um, we already tried to too well, so we of course prepared this episode, right. So we have a script a little bit and the next thing is DSL life cycle. And it talks about what makes a good DSL and the idea of layering over a model. We talked about these things already, right. So is there anything you want to add in that space?
Rebecca Parsons 00:47:58 Well, I think one of the questions that I often get asked is, is how does this really manifest itself in the software development life cycle? If I have a problem, how will I go about knowing it’s time to have a DSL creating the DSL, if it’s an external DSL creating the language parser, how does that then translate into impacts on my build system? Um, how do I deal with, with language evolution? I think one of the interesting examples that we have about this in a more limited way is the use of, of, um, more, more business relevant DSLs for building automated tests. So things like twist and cucumber, and some of those, those, those testing frameworks where you have kind of a middle ground where, where people who are trying to express acceptance criteria for a system are, are using something like a DSL, uh, to, to specify their intention of, of, of the test.
Rebecca Parsons 00:48:57 So you have, you know, in a context like that, you might have a DSL that, uh, or idea cell like thing that is being used for testing as well as a DSL that that is being used to, to actually more directly ex express to the program. So when, when we look at the life cycle, it is it’s, it’s the creation and evolution of the language, it’s the creation and evolution of the language processing aspects, whether that be the implementation within the internal language or the building of the language processor. Then we look at, particularly in the case of an external DSL, the impacts on, on the build pipeline. Um, and then we look at what do you have to test with a DSL? You obviously want to make sure that the translation between a particular sentence in your language and the semantic model is correct.
Rebecca Parsons 00:49:47 Um, we can probably, if we’re doing external DSLs feel fairly confident that parser generation tools are going to generate the right kind of pars or, um, but are we actually associating the right, uh, semantics to the, to the particular output of the parsers? Um, so you want to test the language processor itself, but then you also have to have a mechanism to test the, the DSL script itself. So I’ve put together a program for something, what does it mean for me as a user to test this? Um, and how might, uh, how might that testing phase fit into a standard build pipeline? So those are some of the, the aspects of, of the, the, the life that we have to look at. And then of course, as, as the language evolves, how do we migrate scripts, um, that had been written in that DSL so that they operate in the new version of the language,
Martin Fowler 00:50:37 Right? Yeah. And a lot of this stuff depends quite a bit on the tooling. Right. And can’t be discussed in general, I think. Yeah. So what do you say to people who say I’ve studied computer science 10 years ago? I never really understood this whole grammar and parcel stuff. It was always the hardest thing, compile construction. And now you want to make me build my own languages, forget it. Right. Well, as I always say this people, there’s a common fear of writing pauses and there’s two reasons why people have this fear. One was because they didn’t take the compiler class at university. And therefore think that ours is a scary thing. And the other reason is that they did the classic university and they know it was scary, scary. Right. But the problem of course is that, is that all of these classes taught pausing in the context of general purpose programming languages and trying to posit ESL is a very difficult exercise.
Martin Fowler 00:51:32 So I’m trying to pass a general purpose programming language, especially if you pick something like C, which is a horrible thing to pause anyway. Um, and that’s really the difference. A little DSL is not at all difficult to write a powerful, particularly if you use a pause, a toolkit, but even if you do something, some simple technique like pals or combinations, it’s not really that tough as long as the language is relatively simple. And again, by separating, separating out the semantics into a semantic model, your exercises is then just populating that semantic model. And it again, simplifies the exercise considerably, I think,
Rebecca Parsons 00:52:08 And that there, there are, uh, well understood at least in the language processing community well understood concepts of what languages are hard and easy to parse. And we actually have much better tools, many people who took a compiler instruction class actually use Lexan yak and, you know, antler as an example, as much easier to use as parts or combinations are much easier to use them. Yeah. Although I do have a, have a fondness for yak. I have to, I used to teach one of those compiler courses after all. Um, but, uh, uh, the, the important thing is there are things you can do in the design of your language syntax to make it easier or more difficult to pars. And, and, and the other thing is DSL programs or DSL scripts tend to be shorter than large programs. Um, it’s probably also a smell if you’ve got a million line pro script and a DSL. And yet, you know, we do have to do things like compile huge programs, uh, that have complex relationships between the different parts and, and part of, of the, the drive for the DSLs is to try to think of things, you know, in a more limited context. And that is going to result in smaller scripts with, with potentially fewer interactions between parts of the scripts.
Martin Fowler 00:53:26 And so all of those things are going to make the language processing problem easier, and to take your argument one step further, if you have relatively small programs, you can use relatively bad performing parser formalisms. And that is why, for example, the guys working with echo Fisher, they use SDF, which is the GLR parser, which makes writing grammar as much easier. It’s a bit slower than antler, but who cares? We’re fast machines and our programs. Exactly, exactly. Right. And I guess another argument you could make is if you use tools like X text and you actually go through the trouble of writing a grammar, which may be hard for people, maybe not, I don’t know, but you just don’t just get a parcel. You also get an ID, so you get more for your work. So that’s even another argument that people may want to.
Martin Fowler 00:54:15 Yeah. And I suspect actually grandmas aren’t that scary because people will use them all the time to understand how a language works. It’s relatively common thing. It’s just all the other stuff. And particularly when you deal with a much more complicated language. Yes. Right. I mean, you really came home to me when I was, um, preparing some examples for the book. And I, I used the example that I used in the first chapter, which I should mention is available as a free download. So I’m not necessarily advertising the book here. And, um, it’s basically a simple state machine. And at one point I did it using XML because that’s the, of course, a common way of doing a DSL is to wrap it up in XML. And that way you don’t have to write a parser. So it took me a morning to take the XML script and write the necessary processor to populate the model from that.
Martin Fowler 00:55:07 And then the next day I did a custom language and used antler. And again, it took me a morning exactly. The same amount of time. Yeah. Um, and I actually used a bit of antler I’d never used before just to fit just because I felt that would be easier to talk about in the book. So there’s a bit of learning curve involved now. Okay. I’m a bit more used to than perhaps the average person is, but not that much. And the point is it’s not really that much harder, um, to use those kinds of tools to pause a simple language. Yeah. And then of course there is one other way to look at it. If you don’t like parsing, then don’t use it. I mean, there are all these projectional editors, uh, which don’t parse, um, they may have other challenges, but you don’t have to do this grammar stuff. So. Right. And that’s internal DSLs argument as well. Of course you don’t have to then exactly. Right.
Markus Völter 00:55:58 So, um, I guess
Martin Fowler 00:56:03 We already mentioned this notion of language workbenches, at least I didn’t, I’m not sure we actually went from mentioned the word, but we talked about everything we have yet, so we should somebody don’t use try. Okay. So I tend, we’ve already talked about internal and external DSLs and I see those as two main classes DSL. And then the third
Martin Fowler 00:56:24 One I see is language workbenches, which is a fairly broad phrase use the tools that are specifically there to allow you to design and build not just the language in how we normally think about a programming language, but a whole environment for interacting with the language. Um, the examples that triggered this, I guess it was back in around 2005 or so when I first started looking at what attentional software was doing, uh, I first started seeing what MPS were up to, um, and some Microsoft efforts as well. But I would say intentional NPS were, were my first two introductions into this space. And they struck me as a little, there’s a lot of interest in common elements here. You, you are describing some kind of meta-model in some kind of metal modeling environment to lay out your meta-model. Um, you typically define some kind of editor that allows you to manipulate your language in a much more rich way than just simply typing text.
Martin Fowler 00:57:23 And then there’s typically some kind of tools to allow you to do cogeneration out of that. So that you’ve got something that’s really executable. You’re not just sort of doing what a case tool might do and wander around, waving your hands a lot. You actually are executing something. And, um, that really struck me as a very interesting approach because I mean, there are lots of limitations to thinking of text as a sole input medium. Now I think there are a huge pragmatic advantages. Our whole industry is focused around text. Um, but once you get away from that, uh, it was really, I was brought home to me quite nicely. One of the, uh, former colleagues, Matt famil, was talking about how we, when programming in a modern IDE like intelligence or eclipse, a lot of the time you’re not typing anymore. You’re just hitting all Tenter to do it, you know, in giving it, giving the, the, the idea hint, and then putting completion codes and the ideas then building much more.
Martin Fowler 00:58:20 And you’ve got a sense of, I’m not manipulating text here, I’m manipulating a real model of the program. Um, and of course, what a tool like a, an MPS does is it allows you to really get into that much more. And I think these are very interesting tools because not just could they allow us to do what we currently think of languages more intriguingly, but also to go a step forward. I mean, we’ve talked about how, how I think Excel is this really quite rich language environment. If we really want to have something that’s going to communicate very deeply with domain people, we want to build languages like Excel, and that requires these kinds of tools. So I think the potential here is huge. Um, the question of course is how far we along, how far will it take to be practical, et cetera, et cetera. Yeah.
Rebecca Parsons 00:59:12 One of the other benefits I see as a consequence of the language work bench approach is the, that it gives you in terms of designing your DSLs. You can be more focused in the design of your DSL because this, this language work bench environment, um, particularly on the intentional side, um, perhaps not quite as naturally, but I think it’s still, it’s still a feature of MPS, um, where these languages, it’s easier for them to cooperate with each other. So you can say, I am going to talk about persistence over here, and I’m going to talk about, um, aerodynamic modeling over here. And I’m going to talk about metallurgy here. And I have a, I have the infrastructure that will allow those DSLs to cooperate rather than trying to figure out how am I going to get something that’s going to be natural to a metallurgist and an, uh, you know, the aerodynamic engineer at the same time. Um, so I do think that that’s something that, that is going to be, uh, critical to the development of, of domain specific languages. Is this ability for those languages to interact in the workbenches, make that far easier than even the more traditional, uh, uh, programming language processing approaches, right?
Martin Fowler 01:00:29 Hey, I’m in the lucky position of being able to spend a lot of my time currently working with MPS. And, um, we are, we have actually built an, an extension of C that uses a table notation for decision tables, for example. And so, so this stuff really works. And, um, also this whole thing about language composition, language modularization, extension, I mean, it’s unbelievably cool what you can do now. I mean, you can also do it with, with text-based tools to some extent, right. So, um, would you include X text as a, would you call that a language workbench or generally do? Yes. Okay. So it’s got different styles, but it’s still the same, right? So that was my impression as well, that you’ve kind of removed this, this constraint of being projectional to make something a language work. Right? Yeah. I did write that when I wrote the articles in 2005, because everything I’ve seen was projectional at that point. But if that X, X, Tex was a counter example of something that came in without any kind of projectional capability and clearly, um, fit well enough to, to fit in. Yeah. I mean, if you invented, you know, programming again today, I mean, no sense of the person would restrict themselves to seven bit ASCII characters or Unicode. So I think from a conceptual perspective, this projection stuff is completely convincing and the tools are also really getting there. But of course there is this whole thing about integration with existing worlds. Yeah.
Rebecca Parsons 01:01:55 Well then there is also the change in the way you think about solving a problem. Um, and we have an entire army of, of software developers out there who think about solving problems in an old fashion or in a functional fashion and, and how you approach a problem is very different. If you are looking at it in this, uh, in this, from the perspective of a DSL. And I think that this is going to be an interesting transition for us as we start to experiment with, with different places, DSLs can, can be used. I think we’re going to be attacking it from a couple of different angles. Um, the technical domains, we already have lots of DSLs, and I think we’re going to see that continuing to advance. Um, there, there are many things that people are already quite comfortable with thinking about as a DSL rules, languages are an obvious example. And, and, um, the concern I actually have is that people will be so focused on using a DSL to represent a rules language, uh, that they, that they’ll miss the, the more general aspects of it. But, but I do think we’re going to see, see that this movement towards thinking about problems differently, but there’s a, there’s a long way to go before the average computer scientist coming out of university is going to think about solving a problem in this way.
Martin Fowler 01:03:11 Yeah. It really changes your worldview if the language is not a constant and unchangeable constant anymore. And when you talked about these alternative computational models, I mean, imagine you could reuse a state machine language and then embed a domain specific actual language into it. Right. Things like that actually become possible. So that’s really cool. Yeah. Yeah. And just one of the things that in is the problem with doing anything like the book writing idea is you always have to kind of put limits about what you do. And one of the sad limits was really deciding, I couldn’t really delve into the language Workman chair, and I haven’t really looked that much more in it over the last year or so, but it is something on I need to look more at again, because I think it’s, it’s got such potential, well, let’s put it this way. Initially when I read your book and notice that you didn’t talk much about domain of language workbenches, I was a bit frustrated, but then I thought, actually, this is great because now I can write the book on these tools. Exactly.
Martin Fowler 01:04:13 So everything has two sides, I guess. Yeah, exactly. And I don’t, I do think there’s a lot of huge amount of potential in that area. It’s kind of odd in a way, people are very excited at the moment about new languages and functional languages, the scholars, the closures, the F sharps and all the rest of it. And I must admit part of me feels kind of, well, no, I mean, the really interesting stuff is what you can do with the language work match. Yes. You have that amount of attention moved into that space then I, and I think that’s where the real you’re going to get a really big shift. Yes. I think they can do other languages. They can make small gains, but the really big gain would come through the language world venture direction. Yeah. So, um, we are at the end of our prepared notes. Um, did we forget anything? Is there anything you want to add that I kind of skipped or that kind of didn’t get the necessary attention? Nothing leaps to mind?
Rebecca Parsons 01:05:11 No, I got it in the points I wanted to make.
Martin Fowler 01:05:16 Okay. If we were to television, you should know, uh, you know, put your book into the camera so people can see it. We have to do that verbally. Um, we’re on Skype here. So I mean, the book is called a domain specific languages and the author is obviously and Rebecca. So, so people should be able to find it easy enough to hunt down. Yeah. Okay, good then. Um, I thank you very much for being on the show. It has, um, we’ve been planning this for a while and I’m really glad that it worked. Yeah. I guess then that’s it. Thanks for being on the show and, uh, well talk to you sometime soon on some conference. Hope so. Thank you, Marcus.
Markus Völter 01:06:05 thanks for listening to software engineering, radio SEO radio. It’s an educational program brought to you by hillside Europe. If you want more information about the podcast and the other episodes, visit our [email protected]. If you want to support us, you can donate to the se radio team via the website, or you can advertise for se radio, for example, by clicking on the Dick Reddit delicious and slashed of buttons, or by talking about us on Twitter and Facebook, you can also support us by joining team and shouldering some of the work to contact the team. Please send email to [email protected]. Or if your feedback is specific to an episode, please use the comments facility on the website. So other people can react to your comments. This episode of se radio, as well as all other episodes are licensed under creative comments, 2.5 license, please see the website for details.
[End of Audio]
This transcript was automatically generated. To suggest improvements in the text, please contact [email protected].