6 ms·
I have taken to calling certain features "Turing Complete" (in a joking-but-not-really way). Most often they are seeking some kind of enterprise customizability
by pjungwir 11y ago
I have taken to calling certain features "Turing Complete" (in a joking-but-not-really way). Most often they are seeking some kind of enterprise customizability: "workflow", survey skip logic, custom reports, white labeling, etc.---basically the same places where you risk falling into the Inner Platform Effect trap. I'm curious how other people tackle requests for these. Usually it starts out with something basic ("email the admin if it's two weeks late", "skip this page if they answer that way", "use the most-recently entered birthday to compute age in years and months", "let people change the logo"), but I can see where it's going.
It seems to me you can either field these requests as they come in and get a hodge-podge of strangely-interacting features, or you can build some kind of general-purpose scriptability from the start. (Or you can follow the iPhone and 37 Signals and do it one way only, but often that is not an option.) So I've started to wonder about simply embedding a Javascript interpreter with access to a well-defined API into your application objects. Then people can do whatever they want! Of course this assumes savvy users, perhaps 90% an internal "services" team. But JS is easy to embed, e.g. therubyracer, was designed to be secure (no network/file/shell access), and is the most widely-known of all programming languages. What do other people think? Crazy?
- krupan 11y agoReading your comment reminded me of Steve Yegge's, "The Pinocchio Problem" and also his, "The Universal Design Pattern." How much configurability/programmability should you put into your system is an interesting topic.
- arethuza 11y agoMost high end "enterprise" products (CRM, ERP) have entire weird development eco-systems embedded within the product - complete with their own languages, database access mechanisms etc. What I actually find quite interesting about some of these products is the way they are architected to support multiple overlapping customizations from 3rd party vendors, customer specific customizations and the "core" of the application itself. e.g. I've worked on an ERP project that had the base product, customizations within the product, very complex integrations with other systems and over ten 3rd party products that ran on the ERP systems own platform. That was fun... :-)
- mfenniak 11y agoAt Replicon, a SaaS timesheet provider, we started supporting Python scripting a couple years ago. At first, it was a component of the application we called "pay rules", which are basically the rules that determine how much regular time, over time, double time, etc. an individual is being paid based upon their timesheets. These rules are very different from locale to locale, and at times can be very complex. The scripting started pretty simple; one script type. It has access to all of our web services, and runs "as the user" but under a specific fixed permission set. The permission set limits the script to read-only services. It is passed simple data: a timesheet reference, and a user. It returns simple data: an array of dates, pay codes, and amounts to be paid. The scripts run under IronPython, so we're able to use .NET's security to prevent the script from accessing the file-system, network, etc. As an additional precaution, the scripts are run on isolated servers that are firewalled to only have network access to the web services servers, and importantly not the database servers or the Internet. Whenever a timesheet is updated, the pay output for that timesheet is marked as "needs recalculation", and the script is executed in a background task. It was an ugly roll-out. Our first large customer ran into a ton of intermittent errors, which resulted in stale data calculations being used in actual payroll runs. But we fixed these problems quickly, and it's been incredibly smooth after that first month of hell. And it was very successful. Its success lead to using scripts more and more for other parts of our application, which gives us some incredible per-tenant flexibility while maintaining a single core application. We've followed a few major rules that have helped: (a) Scripts always do read-only operations; they can never access services that write data. This makes development of the scripts simple because they can be executed with no side-effects, which we leverage in the form of a script simulator that we provide in the UI. (b) Scripts always have simple inputs, simple outputs. This is tricky every time we create a new type of script. We've found that the less we feed into the script as an input, the more it has to use services to retrieve data, which is actually a fantastically flexible approach. And the same with data output; it needs to contain the results of a calculation, which the script host then does stuff with. (c) Background execution is far better than interactive execution. We design for background calculations now, making the UI show that "this is being calculated", and preventing certain operations while data is stale. This makes it easy to scale up and down our script servers, and the occasional badly written script doesn't have much of an impact outside of the specific tenant trying to use it. Overall, the approach IS somewhat crazy. It's a lot more work than just implementing your product the way you want it to work. But for "enterprise customizability", it rocks.
- lomnakkus 11y agoI don't think there's any particular issue (as such) with things being TC. I mean, we've been doing TC DSLs and EDSLs for ages now. As you note, I think the key here is to be disciplined about it. Even though it can be hard, I would probably advocate a sort of gradual approach, but with full-on rewrites/finding a new host language when deemed necessary. Oh, and I just have to put this in here, because it's so deserving of a meme of its own... Edwin Brady of dependently-typed Idris fame(?) advocates a different and more, IMO, useful term: Pacman Completeness. If you can implement Pacman in $LANGUAGE, it's Turing Complete enough.
- lmm 11y agoI don't favour anything that puts more Javascript out there, but I agree with the more general point: if you're going to embed a programming language, better to embed a real, well-designed one than an ad-hoc custom one. This is also why I find the likes of drools and cucumber utterly wrongheaded. (More generally, there's an antipattern of turing-complete configuration files - often when an organization has convinced itself that "code" needs to go through a long testing and deployment cycle but "configuration" doesn't). If you already have a programming language, use it.
- simoncion 11y agoHow do you feel about Lua?
- lmm 11y agoBy the accidents of history I've never actually used it. I've used TCL and Python in similar "embed in C" cases (which worked pretty well); these days I'm mostly on the JVM.
- twic 11y agoDrools yes, but Cucumber? Cucumber isn't a programming language, it's just a sequence of steps. There's no logic, iteration, calling, etc. There's substitution of table values into steps, but that's no more programming than a mail merge.
- lmm 11y agoTests end up needing logic, and so Cucumber ends up splitting the flow of a test between two files in different languages. I should probably have complained about HTML templating that allows a template to call into functions (or have logic in it itself), that's a bigger and clearer example of the problem. I think the underlying principle here is that the more powerful languages need to be outermost. Having a powerful language call into a weak language to do something that needs to happen safely works well. Having a weak language call into a powerful language just results in a worst of both worlds - all of the danger but less of the power.