@maryrosecook I'm glad this post showed up in our Slack feed- really cool topic! As I'm sure you've noticed from the volume, variety, and impressive comments in this thread, improving approachability/usability for software development is an exciting (albeit broad) effort, and there is a lot of amazing work underway. In the area of declarative programming specifically, there's a lot still to do, but as a community we're getting really close. That said, there is far too much work to do here for any one team to do it by themselves.
To be successful, or at least to expedite the process of democratizing software development, I believe we need to establish a common set of semantics for describing _what software is_. And the first step towards that is deconstructing functions-- or perhaps more accurately: "subroutines".
The rest of the Sails.js core team and I have been working on this problem for quite some time now, primarily as a reaction to having to build plugin system after plugin system in Sails as the framework's user base grew, and getting frustrated with every plugin system being a little bit different. After we had our first working prototype of the tech that would become Treeline, we extrapolated and open-sourced the machine specification and related utilities as a way of exposing building blocks for other devs to reuse for their own projects.
To add a little background, machines are stateless building blocks; nothing fancy. They're more or less equivalent to asynchronous functions in JavaScript, just highly specified. In particular, machines encapsulate definitions of their inputs, their exits, and whether they are "cacheable", just "idempotent", or neither (and therefore have side effects). Machines are oftentimes implemented as JavaScript functions-- although part of the project's philosophy is that what's important is the _usage_, not the implementation.
Each of a machine's expected inputs may be required or optional (with a potential default value) and declare a type schema. Each of its exits may optionally declare a return value, and if so declare a type schema for it. In addition, machines have strict conventions for meta properties (e.g. the machine `description`, which summarizes the machine's behavior when run, is ~80 characters or less of English, written in the imperative mood and in sentence case with ending punctuation)
This can be used to generate documentation, code for interactive form elements, or in the case of the default machine runner, runtime type validations.
But most important of all, once a piece of code is written to the machine spec and open-sourced, it can be used by any tool or platform which consumes that spec (think USB).
As an example, in Treeline we use machines as draggable/droppable components that you can compose into what we call a "circuit"; which can _itself_ be used as the implementation of another "composite" machine with its own inputs and exits (vs. an "analog" machine; i.e. a machine implemented with JavaScript code). We are planning to publish the circuit spec and related tooling for composite machines later this year. In the mean time, the analog machine spec is stable and ready to use. Around 500 MIT-licensed machines are available today on NPM, with generated documentation hosted on the Node Machine registry.
Hopefully that was a helpful first look- if I can help explain further or if you'd like to discuss the project roadmap, just hit me up on Twitter. It's really awesome to see so much new interest and progress in this tech, and particularly in the context of education. Excited to see where you go with CodeLauren!
Just checked out the node-machines.org and theJsDot presentaion there. Many parts of it has paralells to things I'm playing around with[1].
What are the reasons for not going with an established concepts for the machines? Like contracts for specifying pre-conditions (input requirements) and post-conditions? Or Promises for error vs success scenarios?
@maryrosecook I'm glad this post showed up in our Slack feed- really cool topic! As I'm sure you've noticed from the volume, variety, and impressive comments in this thread, improving approachability/usability for software development is an exciting (albeit broad) effort, and there is a lot of amazing work underway. In the area of declarative programming specifically, there's a lot still to do, but as a community we're getting really close. That said, there is far too much work to do here for any one team to do it by themselves.
To be successful, or at least to expedite the process of democratizing software development, I believe we need to establish a common set of semantics for describing _what software is_. And the first step towards that is deconstructing functions-- or perhaps more accurately: "subroutines".
The rest of the Sails.js core team and I have been working on this problem for quite some time now, primarily as a reaction to having to build plugin system after plugin system in Sails as the framework's user base grew, and getting frustrated with every plugin system being a little bit different. After we had our first working prototype of the tech that would become Treeline, we extrapolated and open-sourced the machine specification and related utilities as a way of exposing building blocks for other devs to reuse for their own projects.
To add a little background, machines are stateless building blocks; nothing fancy. They're more or less equivalent to asynchronous functions in JavaScript, just highly specified. In particular, machines encapsulate definitions of their inputs, their exits, and whether they are "cacheable", just "idempotent", or neither (and therefore have side effects). Machines are oftentimes implemented as JavaScript functions-- although part of the project's philosophy is that what's important is the _usage_, not the implementation.
From the perspective of a traditional "intro to programming", an example of a machine is `moveTurtleDown()`: https://gist.github.com/mikermcneil/864b930a67b0d00d3d8b
As a more practical example, here's the documentation for a handful of machines related to string manipulation: http://node-machine.org/machinepack-strings (To try any of them out, just copy and paste the generated sample code into e.g. a Tonic sandbox: https://tonicdev.com/npm/machinepack-strings)
Each of a machine's expected inputs may be required or optional (with a potential default value) and declare a type schema. Each of its exits may optionally declare a return value, and if so declare a type schema for it. In addition, machines have strict conventions for meta properties (e.g. the machine `description`, which summarizes the machine's behavior when run, is ~80 characters or less of English, written in the imperative mood and in sentence case with ending punctuation)
This can be used to generate documentation, code for interactive form elements, or in the case of the default machine runner, runtime type validations.
But most important of all, once a piece of code is written to the machine spec and open-sourced, it can be used by any tool or platform which consumes that spec (think USB).
As an example, in Treeline we use machines as draggable/droppable components that you can compose into what we call a "circuit"; which can _itself_ be used as the implementation of another "composite" machine with its own inputs and exits (vs. an "analog" machine; i.e. a machine implemented with JavaScript code). We are planning to publish the circuit spec and related tooling for composite machines later this year. In the mean time, the analog machine spec is stable and ready to use. Around 500 MIT-licensed machines are available today on NPM, with generated documentation hosted on the Node Machine registry.
Hopefully that was a helpful first look- if I can help explain further or if you'd like to discuss the project roadmap, just hit me up on Twitter. It's really awesome to see so much new interest and progress in this tech, and particularly in the context of education. Excited to see where you go with CodeLauren!