← Back to context

Comment by PaulHoule

7 days ago

From my viewpoint the benefit of low-code is that the average business application is a matter of people filling out forms. If you want to radically lower development time you have to solve all the problems

https://worrydream.com/refs/Brooks_1986_-_No_Silver_Bullet.p...

For instance, a 2025 no code platform is likely to have "one click" deployment of a cloud application. That's great if you can accept that but if you require "on prem" this is either disqualifying or requires you to build an environment on prem that can host whatever it is they generate, which could be more trouble than building an application the old fashioned way in an environment you already know how to run.

A conventional analysis is that you should be able to generate a CRUD application out of a schema: you need a little bit more than something that looks at a SQL schema and creates a form to INSERT, UPDATE or DELETE, but that's a start.

One problem is that people write schemas that suck despite there being a body of "commonsense knowledge" about how to the world works. I had a year when I fixed a tremendous number of broken applications and one insight I got out of that was that whether it was a student who went from being an applicant to being enrolled to being an alumni or a pallet that would live in a logistics network and then enter a "reverse logistics" network and be inspected and possibly repaired to be returned to the logistics network the same data model of an object going through a number of states with state transitions was general and much better than the 15+ date columns that were added haphazardly to those columns.

Another example that kept turning up was that the ticket "1 phone number for a customer is not enough, support 2 phone numbers" is inevitably followed by "2 phone numbers is not enough, support 3 phone numbers" -- it saves time to work the proof by induction up front and just support N phone numbers up front. But talk that way and people think you're a lunatic like Doug Lenat.

Deployment, code generation from schemas, and schema generation from meta-schemas are part of the solution but if you can't solve 100% now getting that last bit is ultra-hard mode because all the essential complexity hidden by the framework is suddenly in your face.

> Another example that kept turning up was that the ticket "1 phone number for a customer is not enough, support 2 phone numbers" is inevitably followed by "2 phone numbers is not enough, support 3 phone numbers"

Zero. One. Infinity.

https://en.m.wikipedia.org/wiki/Zero_one_infinity_rule

YAGNI, handle a singular case, and once you have multiple treat it like a list.

  • In the case of the phone number or email it is just so frickin' predictable what will happen.

    Adding multiple non-list fields is seductive because going to the list is a "structural instability" that requires using different coding techniques.

    Right now I really like https://www.react-hook-form.com/ for forms that have list values. Back in the day there were a set of techniques that seem forgotten (like how the Egyptians built the pyramids) that some developers knew and others didn't.

    It isn't hard at all to make a no-JS form where you had an "add" button next to a list of values. When you click on that button the POST data contains everything in the form as well as the key/value pair for that particular button (and not other buttons) so the back end can tell which button was pressed and redraw the form with another field. Delete can be handled the same way. If your form is not junked up with 50MB of trackers and ads and metadata for every social platform it is really fast, it was really fast even on dialup.

    With a handful of helper functions and a "router" that can display different forms depending on what you enter you can make powerful no-JS forms but that knowledge didn't quite reach 100% penetration before Angular came along, but developers who came on after that never learned it.

    • I must say, React Hook Form offers a good way for React to interact with forms. There are many things to dislike in that ecosystem but that lib is excellent.

Change management, designing schemas for being amenable to change management, having systems that can migrate data with an understanding of what historical context in which that data got into the system (was it imported from a source with a nuance that was fine before you changed the form, but now makes less sense with the updated meaning and positioning of the field?)... all of this is what makes software hard, whether low-code or high-code!

One of the ironic things, to bring it back to Figma, is that giving designers and stakeholders Figma in all its glory becomes a justification for having engineers on the project, because you can't realize those exciting design visions with just Airtable and the like. Those engineers aren't useful because they can write code; they're useful because they'll (hopefully!) think through those change management and schema design considerations, building something that will be maintainable in the future. It's a good thing to have a design tool that incentivizes a level of foresight before launching a product that's meant to be best-in-class.

>> an object going through a number of states with state transitions was general and much better than the 15+ date columns

It amazes me that anyone would write a schema with a dozen date columns, but I've seen such things. Once you're dealing with a large database of something like that, it's tempting to just add one more column rather than pitch why you should refactor the whole thing.

I try to keep my schemas relational as possible. Actions and immutable records should obviously be stored in separate tables from the objects they reference. However, this does make the UX form design / CRUD process less amenable to simple solutions where forms are just generated right out of a schema.

Your phone number example highlights this. In general of course you want to store contacts in a separate table from customers. But that means you're probably going to need a separate contacts sub-form within your customer form, rather than just inline phone fields. Then form will need to be required or inlined for any new customer before the main customer form can be saved. Stuff like that.

Over the last 15 years or so I've built and refined my own form generator, really a DSL for designing forms that fit this type of thing. In its more basic use cases, each form lives as a row in a database, with each form_item linked to it in a separate table. The form runs a pre-fab query that expects N inputs that it binds to :variables (usually in WHERE or HAVING clauses) and then renders a pre-populated visual form with various input types like dropdowns, checkboxes, calendars, etc (based on those form_items, which can all be styled, required/not required, required based on other answers, etc). Each form_item has its own standard validation or custom validation function on both the client and server side. The form knows which table it wants to write to and which bound variable is the id field it's going to target for update. Sending it a blank id field renders the form with nothing populated and then does an insert instead of an update when it's submitted. It's very slim, about 500 LOC of Typescript and 700 LOC of PHP, including most standard kinds of validations on both ends. I've always toyed with the idea of releasing it it for people to use, but here's the rub: If you want to do anything involving writing to more than one table, you need to write a custom final function for those additional insert/updates.

So, it's a lovely system, but someone coming to it naively would run the risk of designing schemas that were not expressive enough, to try to keep the CRUD system happy. And I think this is just an inevitable problem with all low-code solutions: They don't handle multi-dimensional data the way you want a clean schema to handle it. (And neither do users).

  • I've made automated form editors, companies I've worked for have done it. They had data nesting, with no custom functions for handling it. For example I've made a fully customisable menu editor where you could add sections, sub sections, prices to items, prices to sub items, prices for picking 2 out of X items in the menu. All sorts of crazy (optional) nesting. All saved in different tables. Took me like 2 weeks. I felt very clever at the time. Frontend was all in jQuery too!

    They all saved to relational databases with multiple tables. One form editor (which wasn't mine), allowed you to add new columns (this was in the on-prem days and back then they avoided future collisions by prefixing the custom columns with ex_).

    The problems you listed above are solveable. You don't need custom functions, you need clever property naming. Most ORMs have to solve them too.

    So nested data is not actually a problem for lo-code solutions, it's a solvable/solved problem.

    And I STILL regularly leave that sort of data denormalized. I write multiple date columns (e.g. created, lastUpdated, etc.). I still write mobile + work numbers as columns for plenty of apps.

    Why? It's simple YAGNI. For many apps it's quicker and easier to denormalize the data and keeps the code much, much simpler.

    Plenty of apps that I've seen that have been going 15+ years haven't normalized that data and it's fine.

    The problem comes when no-one refactors and keeps adding them.

    But it's extra work and it's "dangerous" work, potentially data destroying if you get it wrong.

    You get no thanks, as other devs will moan it's more complicated to use, and if you slip up you might get fired.

    So most devs take the easier and safer option and just add a new column.