You tell me if you want to be involved with a long lived and non trivial collection of spreadsheets.
The point is that you can do 80% of the presentation by wiring things together and only rely on coding for the most complex tasks.
It runs your car engine.
(As a nit, I suspect that Simulink is known and deservedly disliked by the vast majority of people with non-software Engineering degrees, given the omnipresence of Matlab in academic contexts.)
But Simulink does continue to rule its own roost. I think the users see themselves more as engineers than as software developers. And engineers are more inured to using awkward tools.
Plus the soul of academia is openess and sharing (perhaps trending towards closed IP and privatisation).
I agree with the author's point, if you replace Ruby with something less awful (Deno, Go, etc.)
Compare that to my personal experiences and that of my colleagues who work heavily with Rails: We show up to a new job at any level of seniority, spend a week or two learning the codebase, and immediately have a firm grasp of all the major components of the application. And I want to stress _firm_ grasp, since everything from the model structure to the ORM to where you can expect to find tests is standard.
Obviously no framework or convention will hold perfectly in the extremes
Some of the older stuff built around rails overdid the meta-programming. Makes unraveling things a little more difficult, but you generally know where to look.
And every time I see a nontrivial state machine using a state machine gem, I know I’m in for a world of hurt. But I know exactly what mistakes I will be fixing. :)
That said other than managing and sorting lists of work to do, I break the limits on sheets and excel all the time so for anything with customer scale data I can't use it.
For the first 5 years of selling courses I handled affiliate payouts by sorting and summing rows in a spreadsheet. It only took 5 minutes once a month. I eventually automated what I used to do manually with a script that reads the CSV file because I like coding and it was fun to me, plus I wanted to remove one point of human error.
I think the takeaway from the narrative here is knowing when to switch from the low code platform and call it a PoC. I’d have cut that off around the point that the custom lambda came into play. That way you’ve used the low code environment for what it’s good at, creating something “they” can react to and easily explore basic functionality. While at the same time you’re taking those learnings and building the more robust solution.
Based on my experience, I'd suggest the pivot point occurs before even starting: it should pivot around who is building and maintaining the system. If you have the experience needed to quickly develop a solution in code, do it in code. If not, because this is a non-technical team without technical resources, do it in low code. Simple as that.
Same with bash vs python. People say you should switch from bash once you have more than 100 lines or so. But at this point you already have some complexity in bash which makes the switch to python non trivial. So you usually end up patching the bash script in small increments as needed. It gets messier and messier but nobody wants to/can spend the effort for a full conversion
For most simple scripts, Python's standard library is more than enough. File operations, JSON manipulation, HTTP requests and argument parsing are all available without external packages.
Regarding Python apps, have you tried using pipx to install them? That would eliminate most dependency problems, which usually arise from sharing the same environment (potentially including conflicting dependencies) across different apps.
Allow internal tools to be built with regular frameworks, while making it easy to add gitops, SSO, secrets management etc which are required for internal tools.
In context it's obvious that what OP meant is that they wouldn't want to build in a language without statically-checked types. That there are languages that provide even fewer statically-analyzable guarantees than Ruby does not make Ruby a suitable candidate.
True. But it has boundaries. Strongly typed cannot be used for langs with implicit nulls. You need to do better than stock C, C++, Java or Go to be able to use the term.
Rust, Elm, Haskell, Kotlin and OCaml come to mind.
That's, frankly, an insane boundary.
According to you, all mainstream languages are untyped? Seriously?
They should say that then. "Dynamically typed language" is not much harder to say or write than "typless language", but is correct instead of being incorrect. And that is a well defined term :)
More generally, advocates of dynamically typed languages seem to want their languages to be considered typed because there's a developing consensus that typed is better. Unfortunately for said advocates, that consensus was not developed in contrast to languages like Forth, it was developed in contrast to languages like Ruby, so changing the definition of a type system to accommodate Ruby doesn't actually get you credibility in the new "cool kids club". You're better off arguing why dynamic is better than static than you are trying to enforce a particular definition of types. No one is going to be persuaded that Ruby meets their needs just because you made them use your definition.
Yep; that's the only reason I don't use Rails.
I'm building "ActiveRecord but with type(script)" at https://joist-orm.io/ and have our own internal "kinda Rails w/GraphQL" going internally--so far we're at ~450 tables and still "feeling good" (no n+1s ever!), but definitely a long way to go before AirBNB-sized problems.
I'd go with Kotlin/SqlDelight or Rust/sqlx (or even jOOQ) these days to avoid having to deal with the overhead of an ORM.
I am curious now: which language doesn't have types but has a separate compile-time?
TCL also seems to have a compiler: https://www.tcl.tk/software/tclpro/compiler.html
In my opinion RBS files are a horrible design decision and split the Ruby community between a typing system that people actually want to use (Sorbet) and a typing system we’ll tolerate because it’s official but a pain in the ass (RBS), leaving both ecosystems to whither. Sad :-(
If the tool lets you make a circle button and change text in it, then that’s all you have to worry about.
Like the article said, my experience is that they're Great!™ until they're not, at which point you're painted into a corner.
When you configure 10 controls and then you have to do another 10 but slightly different - with code you can mostly copy, paste, modify with search and replace and you are done.
With low code tools usually it is just the same work again and even if you can duplicate stuff with an option in the interface adjusting stuff goes one by one.
Table-to-table mappings are often very mechanical, with a set of simple exceptions or deviations, such as adding one column or skipping one column.
There is nothing fiddlier in this world than repeating these steps over and over with a GUI tool where you have to individually click each column mapping link to open its "properties" one... at... a... time... for hundreds of tables with dozens of columns each.
In my view, mainstream languages like Java should offer static metaprogramming for library authors to make tooling like Rails possible and more approachable in IDEs.
The manifold project[1] has something like this for SQL, but it’s obviously providing its own static metaprogramming layer over Java. Shrug.
1. https://github.com/manifold-systems/manifold/blob/master/man...
Low code became less relevant because 1. LLMs solved many of the problems low code solves with better control over the output, and 2. you can’t use many low code platforms as an output from LLMs or other types of models (yet).
Rails became less relevant because Ruby is dynamically typed, and this poses a challenge for LLMs due to hallucinations. You don’t want to find out at runtime what things were complete bs from the model. Static typing isn’t a panacea to hallucinations but it’s a significant enough advantage, especially against such a dynamic language as Ruby. Even mere mortals struggle to understand the magic in meta programming DRY golf that many in the Ruby world have chosen to embrace.
EDIT: Any down voters care to explain why you disagree?
“LLM”s are a constantly updating product, the new DeepSeek coder model with GPT-o1 like reasoning and chain of thought just came out, and its a lot superior than LLM models from even 1 month ago, especially when trained on internal docs, and files, and synthetic LLM generated metadata on those files, all accessible under an effective hybrid search engine.
It’s perfectly usable with Dynamic languages like JS and Python, and perfectly doable to write bug free effective code, is one is restrained and thoughtful in its use, which builds up as muscle memory over time anyways.
Especially if one considers linters and type hints enabled in js (as ts) and python type hints, then it becomes even more doable, if you’re insistent on static typed only language code with LLM.
I agree there is plenty of space for improvement on the IDEs side, they need to start fetching code of dependencies and documentation dynamically, get the relevant context and pass it in the prompt to the LLM, so that they can use real code and not what the model remembers from training a certain library does.
Has it? I don't think many here would agree it is the new norm
> better control over the output
LLMs are notorious for inconsistent output. Deterministic code gen is predictable. The control of a SaaS style low-code project may be limited, some offer to eject the codebase for you. There are numerous open frameworks, like Rails, where you have full control. It's about how you define control. Using a magic box like an LLM to generate code inconsistently comes with a lot of headaches. Why not choose the predictable magic box like Rails?
> Any down voters care to explain why you disagree?
Talking about downvoting typically earns more downvotes because it is against the posting guidelines
Yes: https://survey.stackoverflow.co/2024/ai/#sentiment-and-usage
Anecdotally, my entire engineering team chooses to use LLM assistance because they feel more productive with it
> Talking about downvoting typically earns more downvotes because it is against the posting guidelines
I’m fine with the down votes. I asked because there were no comments, which makes for a pretty boring discussion. Now there are some comments. Thank you for leaving yours
I’m not sold on the importance of static typing though. I’ve had great results with Ruby and Python with 4o, o1, and to a limited degree Copilot.
One of the biggest benefits of Ruby is how simple testing is. The language is so dynamic that mocking/stubbing and intercepting or whatever is dead simple stupid.
So the “static types prevent you using LLM hallucinations” does not hold for me. I’m going to write tests covering the method (which the LLM will probably help with), and I’m going to get an undefined method error.
The types mismatching can really help you spot mistakes early on instead of at runtime, plus with the LLM generating trivial boring types is very straightforward.
The same effect is visible in Rust too and you'll quickly catch APIs that don't exist or that are being used incorrectly - albeit LLM understanding of Rust is really bad compared to other mainstream languages
(I think I'm aligning with his point in the article. No-code really does not offer much long term. And, IMHO, no-code will never truly be no-code, so why not start with "Yes! to code!" and build from there)
IMO, I think it hits an excellent balance between rolling-your-own framework and no-framework-low-code. Rails itself handles so much configuration and wiring up so you that most of the code you do have to write is business logic.
Lambda functions and firebase are convenient and compelling but come with their own tradeoffs that are not as well-tested in the real world compared to rails.
If you're doing a single big project, Rails is less attractive. The upfront cost is amortized over just one project, and the magic makes it a bit harder to stray from the beaten path when you need that.
They build layers and layers of code to "isolate" rails and end up with big ball of mud. Once you do that you have to keep wrapping and adapting, and commanding, and querying and it takes a gang of more than 4 developers to maintain a feature set that could be done with 1 good rails dev.
Code is liability. Features are the asset. Well written rails has one of the best bang for the buck for lines of code per feature.
Rails is amazing for greenfield projects. It will automatically do things for you which will greatly reduce the amount of boilerplate you need to write as long as you follow the framework's conventions.
However, Rails has a less than stellar reputation from those who have maintained long lived projects which use it. Rails' conventions encourage the use of fat models where business logic is implemented in the models themselves. With the default scaffolding Rails provides, every single model and all of this business logic ends up in the project's app/models/ directory without any separation between different features. Because the default doesn't cleanly separate business logic with well defined boundaries this means that Rails apps tend to evolve in a way where everything starts to become tightly coupled with everything else. When the business requirements for the application inevitably change this tendency towards tight coupling between models makes it difficult to make major changes to existing code.
I've also seen hacky workarounds used in Rails based apps which exist to make complex business logic work (e.g., saving one model doesn't implicitly trigger hooks for business logic on other related models). These hacky workarounds usually break the conventions Rails uses and ends up requiring extra boilerplate to be added elsewhere in the application.
Some developers try to avoid this by hand rolling more architectural layers (e.g., "Java/Go/Node.js/OOP like") on top of Rails to try prevent this, to varying degrees of success. Other frameworks (e.g., Django) try to encourage developers to separate different features into distinct modules to try and prevent them from being tightly coupled with each other.
Agreed that tech debt and bad architecture is everywhere. However, from my experience there is a difference in how much work it takes to evolve a project towards something that's less of a nightmare to work with.
What programmer “believes” in “low code” solutions?
But once all that is ready to go, it is about as fast as low code in my experience.
The main difference in practice is that most software that markets itself as "low code" obscures how it works and tries to lock you in to charge rent. Though to be fair, there is generally not much of a market for proprietary/non-OSS libraries and frameworks anymore, so if you want to monetize your library/framework low-code (or an API) is probably the way to do it.
Aside from that, I do think the "low code" label can be genuinely helpful as a way of communicating towards semi-technical users that the software they're using is intended to be usable with their level of technical sophistication. IMO this has been a perpetually underserved market, and it's growing over time especially as computer science/programming gains popularity in schools. There are a lot of people out there who understand basic programming and took maybe a couple CS classes in their life, and want to do something entrepreneurial or practical for their non-SWE jobs, but aren't skilled enough to dive right in to doing things the way experienced SWEs would do it.
In my view there are certain aspects of app building that's hard. Some of it is in code, some of it is in design, some of it is in domain modeling. Every once and awhile you get stuck and your low-code solution is suddenly paralyzed at that one point. ChatGPT unblocks you until you REALLY need a programmer.
Low or no code did not make sense until ChatGPT.
Then the client-server world dominated the desktop, plus we needed automated backups and source control and tests and scalability and auditing and hosting and security and other really important things that never properly made there way into Access. Presumably Microsoft didn't want to cannabilize SQL Server sales and chose not to invest in those things that would have actually made it an MVP for building home-grown apps.
I'd argue that it was Cloud and improved monetization opportunities rather than ChatGPT which made the current iteration of low/no-code more popular, although ChatGPT certainly helps (I'd argue that past a certain level of complexity/code sized, LLMs also stop working properly). Most low/no-code tools include hosting, which is a must for anything meant to be served on the Internet, and before public cloud took off, this was a lot more complicated to offer for free or a low-cost. There's also a much bigger market for SaaS and it's easy to take payments over the Internet now, which incentivizes semi-technical to build software to be served over the Internet rather than their desktop (and also makes it easier to build the low/no-code tools themselves).
> until you REALLY need a programmer
This is the thing I was getting at, there are a lot of people who know how to program but are not super-skilled at it, and I think a lot of software engineers don't get this. Think back to when you were just learning to program and how frustrating it probably was to do "basic" things like set up your dev environment or ship a website for the first time. For the people using low-code, it's not that they can't do these things, it's that they'd have to spend a lot of time looking things up and learning how do it, which is a major time investment (and frankly require a lot of persistence/patience which I think professional SWEs self-select for, because the learning SWE learning curve is brutal for most people) that they'd rather not make. You can argue that past a certain degree of complexity that the investment is worth it, but in many cases it probably isn't, and in others it's possible they'd not have made it to the point of outgrowing low-code at all if they had to do everything from scratch.
It's not much different from how we as programmers use things like Cloudflare or AWS Lambda. Could we run and manage our own DNS or scaling? If we really need to learn it, we probably could if we set our minds to it. Is it possible we could outgrow those tools if we start on them? Definitely. But even when we know how to implement our own scaling or DNS we might still reach for these tools just because they're so convenient to get something working quickly, and most of the time we don't outgrow them anyway. Low-code is pretty much the same thing except it has a lower technical barrier to entry (eg you don't need to know how building/deploying software works) and often is easier to outgrow.
The reason Access eventually died off is that it wasn't designed as a multi-user database. You could run Access on a network file share but performance would suffer (especially with concurrent access by multiple users), and you'll be running the risk of database file corruption. Microsoft Access did support a client-only mode, where Access is used for the forms, queries and application code, but the actual data is stored in Microsoft SQL Server — but setting up and maintaining a database server was probably too complicated for the type of contexts in which Access became popular.
The key point is that most of the usage of low-code products in the past was basically an instance of Shadow IT. In order for a Shadow IT product to be successful it generally needs to be easy to use, easy to distribute (or access) and have a capable free (or effectively free) version. Access and Excel had it all. They were easy to use for beginners (although complex applications required skill). Distribution was extremely simple in the corporate intranet age: you just had to place your Excel or Access file on a network share. They were part of Microsoft Office, so everybody had them on their computer "for free". If a product fulfills the conditions above, entrepreneurial employees will start using this product to address viable needs that your IT department lacks the resources to solve with a more robust solution.
Often these Access apps became popular enough that it had to be officially taken by the IT department, where IT programmers invariably cursed the buggy hack of an application they had to maintain. I don't know the statistics, but I assume a great number of these would just be rewritten as a traditional client/server or web application.
Both your comment and a sibling's mention features that Access either didn't have or didn't do well. However, there were low-code/scripting workarounds for all of these, which were in fact used in many places. It was scalable if you were just knowledgeable and persistent enough to keep chasing your goals. In addition, the backend didn't have to be SQL Server, it could just be another Access database.
I myself created a 'sharded' Access-only implementation (admittedly a fairly simplistic one) that supported over 300 concurrent users. The trick was to keep record locking to a minimum by training users to click a 'save record' button when they were done filling out a form (which defaulted to an offline state)-- all the data was then uploaded to the central database in a few milliseconds, and the connection was immediately closed. Kind of mimicking old webforms. It worked.
> IT programmers invariably cursed the buggy hack of an application they had to maintain
This was really the biggest problem. Only apps designed by people who were pretty good at what they were doing avoided this.
Sometimes the thing really is just the thing. The real thing is plenty of low code systems are just garbage. But Salesforce is the size it is because it's a successful "low code" system.
It handless authentication, storing if auth tokens, can run periodic jobs without managing any infra.
Its great.
> the advantage of 'low-code' is an essentially flat learning curve, if you have expertise in the field you're being asked to prototype in your strongest stack will be faster and better.
It's at least actionable by developers who might feel tempted by these tools for a throw-away project.
i am building all my sites on the same generic backend, that has all the features any website would want, object storage, user management, access control, sync and async messaging like IRC, XMPP, email..., database, various APIs, the works. for most websites i don't even have to touch the backend code anymore. it's like a database. when did you last have to make changes to your DB?
i had one customer who had a demo of a complex app without a backend. the frontend was fully functional but no data was being saved. we were able to integrate that frontend with our reusable backend and we had the whole thing actually working in a very short time without any custom coding beides adding things to the API and adapting the frontend to use it.
It really depends how much flexibility you need: if you have to experiment, change on the fly, possibly pivot then the initial investment is usually justified with code. If your requirements are fixed and fit within the existing functionality then a no code platform might be best (for example if you’re building an app version of an existing site that’s close to templates)
How I wish this was true. Code is a joy to set up using the new shiny tech and people get promoted before the pain to modify comes bite them.
However, implementing anything significant that's expected to be extended and improved, particularly when there are users that request changes, improvements and new features, low-code "is like climbing a tree in order to reach the moon". You'll will very quickly run out of tree and further progress becomes almost impossible.
To a lesser extent the same thing also occurs with web development frameworks, but the limits are less constraining and there are often mechanisms that allow you integrate your own code, that implements whatever it is that the framework doesn't provide.
Low code, frameworks, and "build it totally from scratch", can all be a valid solutions, but the right choice often depends on a bunch of specific considerations (technology, user & quality expectations, organizational capabilities & constraints, etc.)
My recommendation is to keep an open mind about alternative technologies and approaches, and to pick solutions that are appropriate for the environment in which they will be developed, extended and operated. And that requires experience, which you normally don't have in the early phase of your career (e.g. good judgement comes from experience, and experience comes from bad judgement)
When you need to get to something that the framework doesn’t expose, Ruby makes it easy to get to it without having to rewrite the framework, extend a class and replace it in multiple places or fork it just to use your modification.
This applies to the entire gem ecosystem too.
Over the years this ability has saved me numerous headaches with only a few lines of code. IMO it’s the real super power of Ruby.
For example the redis gem updated to return an int from exists() instead of a bool like it did before. This doesn’t raise any exceptions because all ints work in if statements. They just always return true. Silently breaking all of the code using it. You can read all of the change logs and search your own code base, but will constantly run in to situations where another gems code is using the method that just changed.
As well as the fact that almost every method has one param “options” where the available options are never listed in the documentation and are impossible to find without reading the source code.
Rails itself I quite like for being an all inclusive framework that just works out of the box, but untyped languages should be avoided at all costs these days when we have much better options like typescript.
I guess rails works alright at the start, but eventually your app gets so big that it becomes a nightmare to verify updates before they roll out.
What really blows my mind though is that they did it as a minor patch release. Combined with Ruby having no type checking and allowing nonsensical stuff like if statements that always return true.
You introduce a new one, using a different signature and mark the old one as deprecated, and keep it around until as long as reasonably possible.
That's why they offer refunds!
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT
WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT.
I think you make a good point, and were I maintaining redis gem I wouldn't have approved a contract break like that. Even in a typed language, changing the return type of an existing function is IMHO not something you do, especially once you hit v1.0.
But you make a good point that a compiler in a typed language would have at least notified you at build time of the breakage. Personally I'm willing to give that up for the benefits, but I can understand why someone wouldn't.
If you have great test coverage then strong types are superflous, if strong types help you then your tests are not good enough.
The idea that test coverage is a replacement for static types is nonsensical. I won't insult your intelligence and say that by great test coverage you meant testing the shape of your inputs, because only an idiot would say that would serve as a replacement for something that is done automatically by a compiler, but sometimes minor naming mistakes (like `job` instead of `jobId` when you're passing an ID and not an instance of `Job`) will make it past code review and will place a totally unnecessary mental burden on the next programmer who has to look at the code and figure out what exactly he's looking at. With static types there is no need for that, it's right there in the code.
And because tests do not test the detailed shape of inputs and output it becomes easier to try out a quick refactor of your code later, without having to change a zillion signatures just to experiment a little. Agility matters.
You misunderstood my point about the `job`/`jobId`, though. It would be correctly typed, and wouldn't break anything. But it would not be immediately clear for a developer working on that code in the future if it was an instance of Job or the ID of a job, and there would be no type information that immediately makes that clear.
I don't feel like the point you are making with regards to changing the signatures is true, either. If you're changing the shape of some data structure, or adding/removing parameters, then you would also have to make those changes in a dynamically typed language, it's only when you're changing the types of the parameters that you have to make a change, but that's really not that big of a deal, since your development environment should helpfully point out the places you need to update as you change them. I value code that's easy to makes changes in, but I value code that someone else can quickly pick up more.
My day job involves working on a PHP app that's been around since the 5.x days. So it's a mixture of "new code" which has typehints everywhere (PHP nomenclature for runtime type-checking, but static analyzers can also read the signatures and alert you before runtime, which is the real benefit IMO) and "old code" where everything is an array, but to figure out what's in the array you've been passed, you have to look at the 3 functions that call the function you're looking at, and even then sometimes you have to back up 2 or 3 steps up the stack to find where the array is created, and even then you're not 100% sure if that `userEmail` member is present all the time or only in certain circumstances.
With strong types, we pass a UserModel object, and everyone immediately knows what they can and cannot do with it.
I remember in college trying to write some Selenium scripts in Python to do some scraping, and my biggest frustration was not being able to identify the return type of anything. The language wouldn't tell me, the built-in python IDE (IDLE?) wouldn't tell me, so the best I could come up with was something like `print(typeof(x))` (or maybe it was a function to print the properties/methods? it's been a while, I forget) every time I called a new function and running the tool, which was a painful experience to say the least. A few months later I ended up doing something similar but in C# and the difference in productivity was night-and-day.
Now I need to fix a small bug in a library. Rather than wait for the library to be fixed I can monkey patch the fix into the library until it's fixed upstream. Trying to do that with a strongly typed language, you typically need to jump through all kind of hoops or end up fixing the problem outside your library or put some shim in between the broken library and your code. And then once the fixed library comes out you need to undo the code fixes on your side rather than just delete the monkey patch.
Sure I understand the benefits you list, but for me the effort put into strong typing, typing the stuff, changing it each time, just doesn't seem a worthwhile trade off because it's very rare for me to encounter a problem caused by a wrong type. Perhaps I would feel differently if I had to work on a poor code base with many people, but I don't.
This. I found a typed-Ruby in Kotlin (OO-core with lots of FP niceties; code even looks similar to Ruby in many cases as type inference it quite good).
Kotlin + http4k (analog to Rack+Sinatra) + JTE's KTE (or kotlinx.html) + SqlDelight (or jOOQ; fuck ORMs anyway: also ActiveRecord) is a dream to work with.
I'm not sold on TypeScript. Yes it helps but it allows for very messy code.
Your critique here isn’t even a critique of Ruby in these use cases, it’s a critique of any dynamically typed language.
The Ruby functionality I mentioned could easily bail you out in this situation by allowing you to monkey patch the redis gem to restore the old functionality until you were ready to get around to fixing it in your codebase or until you determined that the other dependent gems had been updated.
If anything, this is a great example of exactly my point about the flexibility of Ruby.
I wrote this a while ago. May be the future is a No Code tool with AI that generate enough of an App to allow Low Code edit with the help of AI while the whole App itself is still a full Ruby Rails App that allow Real Code modification in the future by professionals.
What has completely changed the field is LLMs. We now have employees of every sort building small Python scripts which actually work. Even installing Python and getting it up and running is something the LLMs help with. Obviously almost all of it is terrible, and none of scale, but for 90% it, it never has to run outside the personal computers of the employees who write it. Now the challenge becomes keeping the knowledge (and scripts) when employees change jobs. Though to be fair, the knowledge bit was always a challenge.
Do you have any idea how much I made in Fintech converting spreadsheets that'd exceeded the TA's ability to hack/keep it all in their head and/or quit?
Favourite included a single cell that had, I am not kidding, something like 150+ nested if statements.. and there was a dateTime bug in it somewhere :D
A friend did very well positioning himself as a data engineering consultant that could come in and quickly improve poorly thrown together data pipelines, wonder what the equivalent is for these :)
Yay! for non-deterministic financial modeling.
Also was really fun trying to explain to the folks who hired me why I couldnt get the results they wanted to see.
[1] https://support.microsoft.com/en-us/office/remove-or-allow-a...
Here's to hoping we both never have to dip back into that world again :D
I wish!
"This was written by Bob, who's a certified genius. Unfortunately Bob left us to go backpacking across Chile. Can you make just this one tiny change for us?
...
What do you mean, billing for a full day? Bob used to be able to dive right in and make changes like this in 5m!"
Bad coders leave managers with wrong expectations and saddle us with their smoldering piles of garbage and now we have to convince Mr. Manager why we it's impossible to match Mr. Monkey's pace.
We are literally stuck paying off someone else's debt, and it's soul crushing, because you know Mr. Manager won't understand anything technical, and the true culprit, Mr. Code Monkey is already long gone, and we are the sucker holding the bag, getting blamed for late features and slow delivery.
The life lesson I learned is: don't pickup someone else's code, you'll assume all liability.
...
I've worked quite a bit in civil engineering and GIS, and most places I've worked at have made very good use of a 'low-code' tool called FME for automation and ETL tasks. I even reach for it myself for many tasks, even when I am fully capable of doing exactly the same task using for example Python. For the right tasks it is simply the most productive solution.
That being said even with these tools you still need to know how to 'program', at least conceptually, and it's not like just anybody can pick up a tool like this and be productive. The basic concepts of control flow and algorithms still apply and work the same way.
https://www.tensing.com/en/software/fme
Tensing looks like they specialize in GIS.
For what it's worth I seem to recall base licenses started at roughly $3500 per user for the desktop version of their software last time they had a price list.
Such a model is not easily monetized which is why you don’t often see this model in the wild. Draftbit is one company I’ve seen that uses this model: https://draftbit.com/pricing. Note I am not affiliated and have not used the software just find it interesting to see this model actually out in the wild.
But you have to really accept this limitation as a feature, just like you need to accept that inventing pieces or moves is not an option when you get frustrated during a match of chess. As soon as you fall into the coder mindset of "If only I could go one level down", you immediately switch into having 0 upside while having all of the downside. You fight the tool and then there's a ton of things that would in fact be simpler if you just wrote it starting from the correct level.
I would argue, just as with coding, this is mostly a matter of discipline. Having boundaries is part of the real world problem solving. Being able to work within them is a skill.
The same I'd say for dynamically typed languages (and their frameworks like Rails): initially works quite well until you hit the limits.
Once your app is big and there is a team, the efficiency dwindles. Refactoring becomes really hard. Unit test for the rescue, but they also take time to write.
Have you used or seen it used successfully?
Just to learn from, not to knock it down.
We went through that era already. We called them RAD tools, and they targeted the same sort of strange, mythical end user profile. Someone so technically capable and apt that they could navigate a dizzying domain of deeply buried checkboxes, property fields, and sprawling relationships & side-effects, but who was also simultaneously unable to understand source code or program structure.
When using them you would quickly hit a point where making changes to relatively simple things would take mounting an archeological dig of GUI controls that would have otherwise been a few simple find & replace operations on code in a regular environment.
We inherited some Informatica ETL workflows once at work. Nice at first glance with good logging, but peel back the surface a little bit and it was a dizzying level of hidden complexity. Some of this was business logic which was inherently complex, but it was so deeply buried in menus and abstractions with no easy diffing or version control...
Like the comment starter mentioned - who are these tools designed for?
The king of low-code, spreadsheets, are still quite popular as well.
While any "low-code" is marketed as a WYSWG, business friendly solution platform, what it actually is is a way for the business to get access to capabilities IT otherwise gatekeeps as "domain expertise", but fails to actually produce with.
Case-and-point: IT quotes an organization $75 million for 30 projects in fiscal year 20nn. By 20nn+1 IT has completed 5 projects for $75 million. Sick. Org gets "low-code" on their own dime for $1 million, hires a couple "business systems analyst" for a little less, and in 20nn+1.5 has completed 25 projects. In 20nn+3 IT looks incompetent, gets pissed, cries foul, the "business systems analyst" are ingested into IT and taught Java and CRUD circa 1998, and the life-cycle continues.
That doesn't stop a cyclical swing towards RAD/no-code/AI when people forget this and then a swing back when we remember.
No code platforms manage to get around this.
Another use case - I work for a 'non-tech' consultancy. Clients typically won't like paying us to spin up some flask/django/rails app, but are happy to pay us to spin up some sort of no-code thing for them (perception is that it will be easier to self-support, which is also probably the reality compared to me developing some sort of rails app and then leaving the company).
Usually it’s replacing a spreadsheet, so either the information can be manually keyed in or can be imported from various reports. Sometimes you even get into screen scraping, sometimes scheduled reports that are getting dumped to a drive and getting imported… basically any way that avoids needing to get permission from the IT team.
Usually decades of problem-solving have led to an absolute mess of blurry ownership and accountability.
This in turn leads to corner cutting and a road completely covered in Chesterton fences…
Tearing arbitrary fence down leads to consequences out of project scope, no one can answer questions, and no one can prioritize - this is a business problem, and no amount of fancy code (lo/hi/full/lo/left or right) will help.
If you run a bigger company and rely on IT and ERP flows, well, it’s a part of your core and you’d better treat it as such!
The costs of the IT department exists because we have experience on the real costs of implementing production grade software.
For minor throwaway apps, there is always excel and MS access.
I would say especially in modern day guy in some cases: I have not seen anyone happy changing modern code (nextjs or so) that has not been touched for 5 years. The 'just drop in a new component' won't work because 9 billion dependencies had updates and break everything (seems modern devs in the npm ecosystem have serious issues keeping things compatible even across minor versions); that issue was never there with delphi; you just make the change; either in code or gui. Many components I used for 2 decades to create and fix applications without the pain I feel these days. Unlike others apparently, I have no interest in actually maintaining applications: I want to make them and if no changes are needed, I don't want to update them; security fixes are meant to be compatible with what there already is, so that's just a recompile. It's not anymore though so it causes work and work costs money. It's not very nice unless you get paid by the hours then it's brilliant.
Commenting on your general use of rad tools, the rest you say i agree with. I see (i googled a bit) that things like Outsystems are RAD tools now, and yes, those are hell on earth to work with (we did a massive project with it and everyone basically thought it was terrible).
https://i0.wp.com/blogs.embarcadero.com/wp-content/uploads/2...
It's a bit of a different perspective as you describe.
> I have not seen anyone happy changing modern code (nextjs or so) that has not been touched for 5 years.
Yeah... even if you do faithfully update dependencies it isn't straightforward. The sort of stuff I work on is mostly used internally and overall is fairly simple as far as the UI goes. So, for a while now, I have done away with most dependencies where I can and switched to vanilla JS, HTML and CSS for this sort of tooling. Not only does this help me with future maintaining of these tools, it also makes the whole development process a lot smoother as there is no building involved.
I very much realize that I am in a somewhat luxury position here as I don't do client facing applications and most of them are fairly simple. But that's also my point, all too often I see very simple single purpose applications that make use of a complete ecosystem of modern frameworks where the same can easily be achieved without them.
I still haven’t used anything as easy and powerful as those tools were even if they were Windows only and lacked easy distribution.
„low code” appeals to people - who are not technically capable, whose numbers are big - who think if they can get rid of this complex writing stuff they will be able to do stuff. Those people are on all levels of seniority so if CEO mandates stuff, company will do that.
Unfortunately essential complexity of an application does not go away and I have seen those people struggling, cursing and shooting themselves in the foot.
proper software dev tooling has all the right solutions for handling complexity like version control, CI/CD, unit/integration testing - no low code tools implement that.
But if people hear my solution „let’s teach you proper dev tools” they are pretty much uninterested.
Rails built on all of that. Ruby brought two useful thing to the table (well, borrowed from Lisp) which was meta programming and the ability to use its syntax to build so-called internal DSLs: domain specific languages which were just building on top of Ruby's own syntax instead of needing a new one. Rails is basically a DSL for building web based database applications with server side model view controller style UIs.
Once MVC moved mostly client side with single page javascript applications and rich mobile applications, the MVC bits and bobs became somewhat redundant. And of course the rest of it is basically a nice but otherwise unremarkable ORM framework that you can find for other languages as well. I was never that impressed with it to be honest and I'm not a big fan or ORM frameworks in general. Server side MVC is still somewhat relevant if you are into server side rendering (which reinvents what world + dog was doing twenty years ago) but otherwise not that relevant for most REST APIs.
IMHO the last two decades have been a bit unremarkable for UI development. It seems a lot of things plateaued in the nineties. The average UI projects are still fairly labor intensive for what they do; which is mostly just building a lot of form based crap to input data in some database. We had perfectly usable and relatively idiot proof visual UI builders that did that sort of thing thirty years ago. From a functional point of view, the resulting UIs more or less did the same thing. Was that great code, not necessarily. But it did the job. And most "modern" react/rails/django/whatever code isn't a whole lot better. If you discard the lipstick on a pig that is CSS, you are left with essentially the same UI components and primitives (buttons, checkboxes, text fields, etc.). We had all of those decades ago. You don't need a mustache twirling hipster web ninja to reinvent those wheels.
The qualify of software worldwide is about to begin to plummet as developers get lazy and start trusting AI generated code. That's super dangerous. Never trust it.
yeah if you need kimball style queries i.e olap then yeah use postgres with rails etc
I guess they are harder to grok after the initial ease of use: performance is harder to reason about; things can suddenly grind to a halt even though you 'didn't do anything different' etc.
And once I switched from trying to teach python, to just using click-clicky through Zapier or alike, people started to be way more productive without having to deal with us pesky programmers directly. Zapier does have big limitations, but people got creative on how to overcome them. Python would've consumed all their mental energy leaving no room for this. And they did create some hard to maintain horror in the UI, yet it had lower cost thanks to people's self sufficiency.
The article's conclusion says:
> Also, if you’re not a programmer, then absolutely, low code is great. But if you’re reading this article, you’re probably a programmer. So, why are you even thinking about it?
And I would like to add: If you _are_ a programmer, then absolutely, coding is great. But otherwise, why are you even thinking about it?
It’s no more productive. I don’t know why people treat it like it’s more productive than other things.
Curiously, what makes Rails more interesting to me right now are LLMs: Rails is so stable that you can trust the models to know about (most) features, which makes ai assisted development so much more effective.
It’s mostly the ecosystem making it popular these days. Same reason Python’s a juggernaut in several spaces—the ecosystem, not the language or tools (or, in Rails’ case, framework). You can slap a few gems together and have a site with all the basics (user accounts, admin, OAuth, file uploads, user roles, et c) in minutes. The gems are widely-used enough that they support most things you might need for whatever-they-do, and you probably won’t run into some feature that you really need but has been broken for two years and nobody realized it because nobody’s using that feature.
(For the record, I’ve sworn off rails after seeing so many codebases that were total dumpster fires that I decided it attracts too many budget-minded-to-a-fault companies and owners for me to want to work with it again, plus I fucking hate ungreppable magical defined-nowhere metaprogramming symbols and magical imports that leave one unable to figure out WTF is happening without running the code, but I can see why it’s popular)
Isn't this what people thought about Oracle Forms before it going the way it did?
They instead said "if you need to write your own little CRUD apps, use our APEX instance that we support and have backups for."
Sounds like an effective solution. Even though some people might build a great application, but someday they might leave, and nobody knows how to administer this.
You can still write bad PL/SQL code, but at least everything is centralized and stored in a single database where you have an admin making sure that everything is fine. For other developers, it is straightforward to make small changes because 95% of the complexity just lies in the data model and the database code. You don't need to adapt to a specific infrastructure, frameworks and other dependencies, etc.
It also makes it so easy to create opportunities for SQL injection if you don't have careful coders. And it is also a great target for DoS attacks.
Having said all this, it really is the only low code platform I would ever consider using, in spite of it being Oracle's.
This is not the case. If you bind values with :ITEM_NAME and use compiled statements (never dynamic string concatenated ones with "execute immediate') there is no chance of SQL injection.
You can also inadvertently leave a page public.
Adonis.js is just that. I have never used it beyond a quick test though so I can't say what it is like in production.
(Not that I'm a fan of low code or anything.)
Building the Multiwoven product based on Rails has been incredibly helpful in balancing rapid development with the ability to scale and customize as user demands evolve. It provides a structured yet flexible foundation, allowing us to adapt quickly without compromising on quality.
It’s about knowing when to leverage low code for speed and when to transition to more robust solutions for long-term scalability.
For example, is AWS Amplify or Firebase low code?
Uses excel and excel like formulas for stuff. Not bad for power users that can/want hack their app together.
Otherwise, "there's nothing more permanent than a temporary solution".
Like a farmer hacking together some stuff for their needs instead of waiting for official solution.
Power users automate their way to gain efficiency when programmers are busy doing their stuff.
Every item is faster to implement and less configurable than the next one.
Until the set of features you need to implement fit your current choosen setup, you're good. If you need to dig deeper, you'll be in pain.
You may get some relief with some hooks.
I've experienced my fair share of pain with RoR, it's definitely not a magic bullet.
I was amazed at things like Rails Admin a decade ago but overall it does way too much for what I typically need.My sweet spot is a low level server, eg. node.js + express (actually, rust + axum these days).
Also, I don't see what is wrong with the outcome that at some point you have to rebuild with code. You have spent not very much time to develop a prototype that was able to get some feedback and come up with new ideas. Maybe that very revolutionary idea about the reservations app the author describes would never have imagined if they didn't have a prototype to play with?
And don't even get me started on the risks of traditional software engineering. How many projects never even got to a viable prototype because devs decided to rewrite everything in flavour-of-the-month every 3 weeks?
this part sounds pretty fanciful, my experience is at the worst six months for new library in your chosen language, and that you can generally talk them out of; 1-2 years rewrite fever in some is almost overwhelming.
on edit: in short I think even the least self-aware dev is not going to do rewrite cool new tech every 3 week, maybe once but not twice. So sounds a bit hyperbolical.
Exactly, low/no code solutions have their limitations, but I think the space they're useful for is — "they" need a simple CRUD app so they build it themselves in No Code solution, figure out what they really want & what the pain points are and _then_ bring on board a developer if it needs expansion, but with a real todo list in front of them.
Or (just as useful to the business user), realise it's not what they need and bin the project before engaging a dev at all.
When you try to replace an entire language and multiple libraries with visual editor, you end up with something really complex, and often beyond your user's abilities to learn with the limited time/attention they have.
Most backend, integrations, automations require some degree of business logic, which requires algorithmic thinking, and this in turns requires engineers - there aren't many people who 'think algorithmically' and can't code. Engineers, in turn, hate low code frameworks, as they are useless on the CV and annoying to work with for reasons mentioned by others here. Proprietary s*ht tech that always, inevitably, leads to custom code.
And, it's expensive. We had mulesoft, outsystems, boomi and replaced it all with general purpose stuff shaving approx. 9M/yr in license costs. We have lost no velocity, and the great thing about the alternative (in our case: simply standardizing the toolset and going with GCP 'serverless' stack) is that its super easy to find devs who will willingly work on that. That hasn't been our experience with the low code frameworks.
Essentially I prefer staying at the "you need to be a coder" abstraction level, but the general tooling nowadays makes becoming one very easy. Once you mentally lift the requirement that something needs to be configurable by some non-technical end user or even needs an UI at all, 90%+ of all dev effort can be saved directly. Plus there are no showstoppers in capabilities or usual barriers like too bad performance/config hell of "no code"/"low code" I encountered quite often. And if you don't use the latest webdev fads, things can be maintainable for decades (looking at Go compared to NodeJS).
Rawdogging basic programming (yes, also no framework if possible) made more "business" projects first succeed (and then stay alive easily) much more than either a web framework or any kind of lo-/no-tool, at least the things I encountered in the wild. Even bad spaghetticode monstrosities can now uploaded to an LLM and refactored into sanity quite efficiently.
The worst kind of projects (with lots of pain and regret) have been either JS-based, mis-used framework projects (including rails!) or Salesforce setups. Often you're stuck in a dead-end here.
Sqlite for quick and easy postgres for scaling.
For simple frontends I just use the built in go templates.
If I need complex frontends for larger apps I use sveltekit/svelte5 for frontend data I just export a single instance of a class that has state/derived fields for data and an isInitialized field that returns a promise for loading the data. Then methods for reloading data, changing data or any actions I need.
So all i have to do is await classInstance then use the class data in whatever way I need. Everything is reactive and simple due to states. you can use and update the fields directly like regular js but with global reactivity built in.
The data automatically loads the first time the module is imported. due to how esmodule files work. I just have a classInstance.LoadData() after the export.
Svelte5 isn't as good with LLM's but with some small instructions about how states, derived, and effects work it works pretty well.
Again, some people might not care about that but it seems kind of a biggie to me.
I personally use a code generator to generate more than 90% of the C++ and Javascript code that a typical biz client/server application needs. Protocols, Database support etc. Using libraries to do what isn’t application dependent.
And when I occasionally (rarely) need a new feature not supported by the code generator or libraries, I simply add it as needed.
I highly recommend building your own code generator/libraries. Yes it takes a bit more time up front, but you get a solution that is tailored and perfectly shaped to your (team) needs. And you don’t end up depending on some open source project that has been abandoned or changed in a direction that you don’t agree with.