4 ms·
I think of API design like little languages. Got data structures, functions that operate on them, and a job to do with those functions. Anticipating the useful
by butterisgood 4y ago
I think of API design like little languages. Got data structures, functions that operate on them, and a job to do with those functions. Anticipating the useful ways an API might need to be used is difficult so keeping it small to start is generally advisable. Plus if you’re wrong in some ways you have a lot less to refactor.
- PartiallyTyped 4y agoI share the sentiment; in the end, all abstractions are just that, little languages, perhaps even dialects within a broader language that defines what constructs you may use while remaining "correct". I am working on a project at work that may involve some kind of language, and the language essentially came up because we need a way to define an arbitrarily large abstraction, effectively behaving as an intermediate layer between multiple different front-ends and a backend.
- worldsayshi 4y agoI agree. In a way, all applications have a sort of implicit Domain Specific language in them. You have a bunch of things (nouns or types) and you can tell the application to work with those things in certain ways (language). When I learned Haskell at University there was a lot of emphasis on EDSL (embedded domain specific languages), where haskell allows you to define grammars inside haskell. There are many examples of EDSL:s in other langauges but Haskell takes things a bit further. I think there could be a good point in allowing such approaches in more languages. I heard that Rust has ADT:s, which is a good building block for EDSL:s. It might make things a lot clearer, or it might make things over engineered. I'm a bit on the fence about it. It probably makes things more manageable in the long run.
- worldsayshi 4y agoLate edit: (*language or business logic) The point of Building an EDSL could be to isolate the business logic from everything else. This should be a big benefit since for most cases it should be possible to make everything else from off the shelf commodities.
- contravariant 4y agoIf done well most code is just extending the language you're writing it in to make it easier to say the things you need. This is perhaps clearest in lisp because there is no syntax to get in your way (kind of the opposite approach to operator overloading). Perhaps the most interesting way you can approach this is by designing the language first and then figure out how to implement it.
- butterisgood 3y ago> Perhaps the most interesting way you can approach this is by designing the language first and then figure out how to implement it. Yeah, I'd say if you're not creating a "domain" in which solving the problem at hand is easier, you need to get back to the drawing board. That's true for language and API design.
- hyperpape 4y agoThis really isn't the same. If you're just building up objects/data structures in your host language, and calling functions/methods on them, then you're not creating a language. It doesn't matter how slick/fluent or whatever else your API is, you're just working in the host language. To have a reasonable claim that you're writing a language, you'd need to write something with a different syntax and/or model of execution, and somehow embed it in your language. Arguably regexes and SQL count, though the perennial problem there is that to the host language, they're just opaque strings. None of this is to say your APIs are bad. Embedding one language in another is hard--that's why they're so often just opaque strings. Beyond that, as this article points out, embedding a new language gives anyone working with your code a significant obstacle. For most things, little languages aren't the right tool--standard imperative/functional programming goes a really long way.
- deleted 4y ago[deleted]
- naasking 4y ago> This really isn't the same. If you're just building up objects/data structures in your host language, and calling functions/methods on them, then you're not creating a language. It doesn't matter how slick/fluent or whatever else your API is, you're just working in the host language. It can be. They're called EDSLs, "embedded domain specific languages". The point is to embed the language semantics in the host language via judicious choice of data types, and then methods implement semantics-preserving transformations on them. The more expressive the type system, the more expressive the languages you can safely embed in the host language, and you then have all the debugging capabilities and libraries of the host language at your disposal. This pattern is very common in Haskell, Oleg is well known for doing this with OCaml [1], but you can also do this in typical OO languages like C#. Arguably C#'s IEnumerable<T> interface is such an EDSL for set programming, and here's a simply typed lambda calculus [2], here's an SKI combinator calculus [3], here's a stack-based language [4], and here's a logic programming EDSL based on µKanren [5]. [1] https://okmij.org/ftp/ML/#DSLs https://okmij.org/ftp/ML/#DSLs [2] https://higherlogics.blogspot.com/2008/09/mostly-tagless-interpreters-in-c.html https://higherlogics.blogspot.com/2008/09/mostly-tagless-int... [3] https://higherlogics.blogspot.com/2013/09/combinator-calculus-edsls-in-c.html https://higherlogics.blogspot.com/2013/09/combinator-calculu... [4] https://higherlogics.blogspot.com/2009/01/embedded-stack-language-for-net-redux.html https://higherlogics.blogspot.com/2009/01/embedded-stack-lan... [5] https://higherlogics.blogspot.com/2015/02/kanrennet-featherweight-relational.html https://higherlogics.blogspot.com/2015/02/kanrennet-featherw...