Hacker News new | past | comments | ask | show | jobs | submit login

All those kind of projects share the same flaw: it uses a DSL instead of an existing language, so tooling/documentation/testing/support/modules are going to be very weak, and 100% depending of the creator for the first years, in a domain that is already a niche.

It could be a library with good API instead. Or even a special env setup for an existing language with injected built-in and automatic imports.

Now you could argue that the goal is to have this "simple DSL that looks like english" so that normal people can use it.

This argument has existed since DSL exist, and the result is always the same:

- the simplicity of the language will, in the end, limits its usefulness. Not every domain is like SQL/HTML/CSS, where descriptive is enough. Complex domains need branches, loop, namespaces, etc. Eventually you will be forced to add features in a twisted way to something that was not designed for it and replace its simplicity with ugliness, or restrain yourself and be limited forever. See Ansible DSL for a good, or rather, horrible, example of that.

- end users that can't use a normal programming language won't suddenly become tech saavy because your DSL is simple, but their use case will never stop at simple. So they will start building complex systems as soon as they use it for real, with a limited DSL and their limited ability. The system will become a monstrosity, and you'll have no tooling to help.

- successful dsl are usually not simple. Css is not. Sql is not. Html is an exception because it has no logic. This has logic.

- it looks so cool. It's like candy for tech lovers. Even to me: I find it so sexy. And so people will adopt it, ignoring the arguments above. Ignoring the decades of such attempts that ended up in pain behind so many corporate firewalls. There will be many tweets at adoption to talk about how nice it is, but no blog post 2 years later to admit it was a bad idea. And then it will happen again with $new_shiny_dsl_based_tool.




All these kinds of HN comments share the same flaw: they unnecessarily detract from the work the OP has done by attacking use cases that the project never claimed to solve.

DSL's, for all their problems, do simplify complex programming logic, and people use them every day to do great things. DSL's like Ansible and Chef save people an order of magnitude of time for server provisioning hence why they are wildly popular.

It seems reasonable to me that someone would build a DSL with the same goals for web browser automation. The screen recording example gif they have looks so intuitive even a non-programmer could do it.

I don't look at this project and expect that it solved every problem with web scraping and reading the README it doesn't look like they are claiming it does either.


All these kinds of HN comments share the same flaw, in failing to recognize that the primary obsession of hacker news is in discussing the flaws of things posted on hacker news.


I would argue that thats the benefit.

I want people more knowledgable than me to comment and point out the flaws in products/reports/theories. Thats what I love about HN.

How critical are those flaws? It's up to you. If you take the approach of "there is no right or wrong, only opinions" when you read comments, it's much better off.


I would argue that trying to find flaws is flawed (atleast in this context). Much better to use a neutral approach where you are equally open to strength and flaws.


Using Ansible is what made me lose faith in DSL's in all the ways mentioned (eventually wanted loops, conditions, variables and namespaces...). Ansible is an API over a domain and if it were originally just represented through a Python language library I don't see why it would be less accessible or productive. Even something as simple as YAML can be screwed up and turned complicated.


Even though I know how to program, I really like Ansible and probably wouldn’t have gotten into it if it had the same functionality but used Python instead of YAML.


Building infrastructure is complicated. Have you found an easier way then Ansible to accomplish building infrastructure?

Ansible does make yaml more complicated, however, you don't need to use much of that complexity for simple projects. Compared to Terraform, Chef, Google Deployment Manager, and Windows Desired State Configuration, Ansible is by far the simplest to get up and running on to do real work with.


AWS CDK would be an example of using a programming language rather than a DSL to build infra.


There's also Pulumi that covers a wider range of infrastructure than AWS only.


Have you tried SaltStack?

It uses YAML too, but always felt much more cleanly composed, and smoothly integrates with scripting languages.

I've never truly broken into orchestration and am still salty about that so please, take my post with a grain of salt.

(Full disclosure: I have literally no professional affiliations whatsoever.)


> Even something as simple as YAML can be screwed up and turned complicated.

Your problem is that you think YAML is simple.


Some of us legitimately believe DSLs are rarely the right choice. We don’t say this to shit on people’s work, we say it to kick off a conversation about API design.

I’ve written DSLs in the past. I was a Rubyist! I have come to some perspective on those choices in the intervening years. I’m a big fan of functions that take arguments, and I am skeptical of hidden shared state.


You can be skeptical of DSL's but still recognize that they provide a time/complexity trade-off. I agree that it's probably not the right decision to write your own DSL for something but to dogmatically crusade against all DSL's feels silly to me when there are so many popular projects using them.

Ansible is popular because it is accessible to devop type roles (previously known as sysadmin or IT services) that may know some programming but would fail to produce results nearly as fast if they were simply left with python libraries. It would not be as popular as it is today if it were simply a python library.

Criticizing this project for using a DSL as it's interface over some programmer purity test BS is completely missing the forest for the trees.


> they provide a time/complexity trade-off

I think that’s too specific of a claim for such a broad category as DSLs.

I think in specific cases there is a time-complexity tradeoff you can exploit, those are the (IMO extremely rare) cases where a DSL is worth considering. But in a lot of cases it’s just added complexity. Functions are pretty powerful.

And they are also easier to reason about. Often the DSL adds “time” because you’re like “why the heck isn’t this working” and it’s because of some weird state you can’t inspect that’s deep inside your parse tree. “Guess I better start reading the source code of my DSL runtime. Oh look, someone hacked a corner care into the parser.”

My rule of thumb would be something like:

1) if you have time to make your DSL superbly executed, and 2) you are very certain it can make an entire class of problems go away, and 3) you don’t expect weird corner cases to ever show up in a future project that break the model ...then it’s worth considering.

As a professional coder though, I don’t see a lot of situations like that. In particular the “build this module superbly” is generally not an option on the table. Nor is “you can model the domain of future needs thoroughly” But I work at startups, I bet at a BigCo if you are a very senior person DSLs are on the table more often.


Your whole argument boils down to "use a DSL only when appropriate" - no argument here on my end.

Still, I don't think that makes a DSL a bad fit for this specific project, even by your own standards.

> 1) if you have time to make your DSL superbly executed, and 2) you are very certain it can make an entire class of problems go away, and 3) you don’t expect weird corner cases to ever show up in a future project that break the model ...then it’s worth considering.

#1 yes, just like any code you write, right?

#2 yep, this is the same thing as complexity/time trade off

#3 maybe? you can still have edge cases that you can't solve with your DSL but that doesn't invalidate its usage if the benefits from #2 are great enough.

And #4, which is the biggest reason and the reason to use it on a project like this: it provides a more accessible interface to your project for a broader audience of people.


I completely agree (not related to this project, but a rant in Ruby). I used to thing metaprograming and DSLs were the best part of Ruby. Now I think it is the worst part. It makes code almost impossible to inspect, has hidden shared state everywhere, and makes things like stack traces end up saying `at line 66 in method_missing`. Or if you can locate the method, it is running it in `instance_eval` making it really hard to know what the state is when it is run. Ruby is actually a very functional language and now if I write Ruby code it is as functional as I can make it.


I tried using Ansible once and could never escape the fact that anything complex like installing files or raising docker containers requires the use of external modules with actual code and templated YAML. Every time something "templated" shows up in a supposedly "declarative" language it feels like the designers had to add on features from an actual programming language to do what they wanted, because the DSL was too declarative and static to accomplish anything useful.

For example, look at this Azure deployment template:

https://github.com/Azure/azure-quickstart-templates/blob/65d...

Notice all the inline function calls. They basically modified JSON with their own domain-specific "functions" like "concat" and have an entire section dedicated to "variables" because in standard JSON this is not possible to express. Already this sounds like a scripting language, except terribly watered down and specific only to Azure services.

As a personal anecdote, I once made the dumb mistake of choosing a static config file instead of a dynamic one when I was developing a mod system for a game. The problem became that there were things like function callbacks that I wanted to add in, so that meant I ended up writing inline "pointers" to a place where a Lua callback existed as an identifier, instead of inlining it as Lua code, then it went through an unnecessary transpilation step to Lua data structures. My mistake was assuming that the DSL was expressive enough for my needs, which included loops, inline function callbacks and code generation, when clearly it was not.

Sometimes the effort people expend to make declarative configs work out are significant. The OpenAge project (an engine rewrite of Age of Empires II) uses a declarative language called nyan[1] which describes the changes of things like unit health or cost. It's entirely custom-made for the engine.

The moment that I realized that declarative configs were not for me was when I realized that this declarative language, which the author wrote an entire PhD thesis over and was specifically designed for the purpose of game modding, would still not be expressive for the things I was envisioning. In the end Lua, a general-purpose language that had existed for decades, was the better choice. There was no need to muck around with writing new languages or munging the declarative data into the shape I wanted - the data could just be output from a script.

On the other hand I understand if having a Turing-complete language for configuration is a bad thing because of security or too much expressiveness that hinders static analysis because of unseen edge cases. It depends on if the "scripting" features are hacks intended to get around the fundamental limitations of DSLs or a deliberately constructed featureset.

Also the reason I became so attached to declarative configs in the first place was the prospect of writing an editor frontend to interactively create new data entries. That's probably the reason Azure went with JSON instead of a programming language - they have a template editor in the web portal for filling in the parameterized variables the config declares. This is probably an ease-of-use tradeoff so people don't need to program to deploy things. As someone who uses scripts as configs, how to properly write an editor for them escapes me. I was thinking of having to parse the scripts into an AST and use heuristics to discover where data is inserted, but of course you can program anything so this won't always work.

Still, in my opinion I would choose something like Lua any day over the nth domain-specific proprietary reimplementation of 2% of JavaScript on top of JSON.

[1] https://github.com/SFTtech/nyan


The whole point of this is the scripting language, there are already lots of other browser automation tools out there.


A scripting language is not a goal in itself (although in the case of a DSL, it often is unfortunately because of the coolness factor), solving a problem is.

Here the problems it tries to solve are:

1 - to have a nicer API to do automation

2 - for non tech saavy users to be able to create tests

My take on this is that DSL are a wrong answer to this.

1 can be solved with a better lib, with a better API, or a dedicated env.

2 is probably not solvable: automatic testing it hard, you need to be tech saavy to do it.

But let's say you still want to solve 2, a better approach would be to solve 1, then solve 2 by creating a GUI that let users record their actions and generate code from 1.

Such API and GUI exist, as you said, but they could be improved by tenfold.

It's boring work though, and working on a DSL is much more cool.


> A scripting language is not a goal in itself

Agreed, I think this is a case where people forget “what is the problem I’m trying to solve” and instead get lost in a means not an ends.


Depends if the goal was to make a scripting language and at the same time tackle a problem (or not). Some people like building stuff for the hell of it. A language by itself is an interesting non-trivial project.


I actually kind of really like this DSL, I think it is going to be easier for my QA team to use this, than asking them to use javascript.


Seriously, how is this DSL better? With JavaScript you get method completion and debugging. Are parentheses really so terrible?

You can setup a DSL in scala.js and you can get the best of both worlds (though, parentheses are fine for me so I would just use one of the many fine existing JS libraries).


> With JavaScript you get method completion and debugging.

a) now your QA team needs to know JavaScript

b) method completion is crap when you don't know the language.

c) "You can setup a DSL in scala.js and you can get the best of both worlds" OMG You want to add Scala to the mix too? AND write your own DSL from scratch, and take on its maintenance to support your QA team's needs instead of leveraging an existing one?

your solution:

1. teach the QA team Javascript interaction with custom scala created dsl

2. have the dev team spend time creating a dsl

3. have the dev team devote some of its resources to maintaining the new DSL

their solution:

1. use english-like DSL much easier to learn than JS

2. that is already created

3. that someone else maintains

both solutions are going to have limitations in that what you want the DSL to do will be more than the DSL can _currently_ do.


The other choice is that your QA teams knows this DSL tho. Which is the point: eventually most DSLs converge on the complexity of programming languages and you’re left asking: why not just use a well known programming language in the first place?

We’ve beat the Ansible example to death but it’s a really good one. It started as something simple and then with every edge case came the need for increasingly complex logic until it resembled a programming language just with super funky syntax.


a-c) I didn't mean that QA or whoever learn Javascript or scala.js. (though I'm not as scared by the idea as others)

The library authors can use those the create a better DSL (or as I call it: "just a good API"). the cognitive load on the users is the same, only it's easier to setup up proper tooling

in javascript you can make the exact sample api he defined only with `await` and some parentheses

in scala you can setup API that looks like: `browser show page`, users don't really learn scala just write the same commands they otherwise would (I'm not saying you should do this. You could, if you really hate parentheses for some reason, but there is a way about it without inventing your own ecosystem)


1) if you are on a qa team writing automation, there is a high chance you already know javascript.

source: was qa automation engineer for a few years. I realize it is purely anecdotal, but nearly all of the QA people I worked with knew javascript, even the manual testers.


My experience here is different. The majority of manual QA I've worked with do not have experience with automation, nor do they know JavaScript.


I know right. It looks so nice. I want to pet it.

But it's a trap.


These are actually valid points for any DSL creation. I have been working on DSL for a few years. More precisely I'm working on a DSL tool that allows people to create "simple DSL that looks like english" so that normal people can use it. Here are my thoughts on those arguments.

Indeed complexity is there for most real domains. But DSL is meant to be another abstraction layer on top of the complexity. My lesson is constraint is the most important as this lays the foundation of its usefulness. I don't mean you should not have things like branch or loop. You certainly could add them, just in a domain friendly way that doesn't hurt the readability and writability of your DSL.

In order to tackle arbitrary complexity, the DSL itself should be designed with extensibility in mind so that technical people could easily add language constructs or vocabularies by using script or general purpose language. Further, those features should be able to be turned off for some scenarios. For those inherently complex stuff, they should be left to general purpose language anyway.

Tooling support is another big problem. In my opinion, DSL is never just the tiny language, it is about the language and tooling. However the tooling requirement is often not as standard as general purpose language. Domain users normally don't need an IDE(an editor should be generally required) or debugger. Rather, they want something that can be seamlessly integrated with the host application.

And more over, different people (even in the same domain) may have different requirements on DSL maintenance, eg, governance, versioning. This often leads to a case by case customization. I do not have a good answer for this other than the general advice: treat DSL and tooling as a whole and make the API as easy as possible for integration.

Edit: For anyone interested in my DSL(still work in progress), here is a glimpse:

http://www.typezoo.com/docs/workflowrules/editor-2.gif


Absolutely the current version seems very limiting, but as they start adding more and more features towards Turing completeness, it will become just as complex as a normal Turing complete programming language. Which in many ways undermines the original promise.




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: