Comment by karmasimida

5 years ago

Well said.

That is why I am fundamentally skeptical with the current push for Low Code or even No Code. Seems like people just don't really learn from the past.

> Low Code or even No Code

I look at the code I'm writing (mostly C# thesedays) and I consider the _information-theoretic_ view of the program code I'm writing, and I see a major problem is that even syntactically terse languages (like C# compared to its stablemate VB.NET) still requires excessive, even redundant code in many places (e.g. prior to C# 9.0, defining an immutable class requires you to repeat names 3 times and types twice (constructor parameters, class properties, and assignment in the constructor body) which alone is a huge time-sink.

The most tedious work I do right now is adding "one more" scalar or complex data-member that has to travel from Point A in Method 1 to Point B in Method 2 - I wish I could ctrl+click in my IDE and say "magically write code that expresses the movement of this scalar piece of data from here to here" and that would save me so much time.

At least in modern languages like C# 9.0, Kotlin, and Swift (and C++ with heavy abuse of templates) a lot of the tedium can be eliminated - but not in the granddaddy of OOP languages: Java. Still to this day, I have absolutely no idea how people can write Java for line-of-business applications (its bread-and-butter!) and remain sane from having to manually manage data-flow, implementing Java Beans, and manually writing by-hand getter-and-setter methods...

  • > but not in the granddaddy of OOP languages: Java. Still to this day, I have absolutely no idea how people can write Java for line-of-business applications (its bread-and-butter!) and remain sane from having to manually manage data-flow, implementing Java Beans, and manually writing by-hand getter-and-setter methods...

    Because... We don't. IDEs and code generators have replaced a lot of the more stupid boilerplate. Not that there isn't a lot of stupid boilerplate in Java but it's been greatly reduced by tooling.

    Still, I don't work with Java because I like it, I work with Java because it works and has a great ecosystem, the tooling around it make it bearable and without it I'd have definitely have jumped ship a long time ago.

    I'm not only a Java developer, I've worked with Go, Python, Clojure, Ruby, JavaScript, Objective-C, PHP and down to ASP 3.0. Java is still the language that employed me the most and the longest, I have no love for it apart from the huge ecosystem (and the JVM gets some kudos) but it works well for larger codebases with fluid teams.

    • Ward Cunningham once noted that because a programmer can input incomplete, or minimal, code, then push a few buttons to autogenerate the rest, that there's a smaller language inside Java. Since he made that remark a number of other JVM languages have sprung up that try to be less verbose. One of them is Groovy, which uses type inference and other semantics to reduce duplication (or "stuttering" as Go calls it").

      The issue now with Java is that it's such a big language and it's accumulated so much from many different paradigms that experience in "Java" doesn't always transfer across different companies or teams. Some teams hew closely to OO design and patterns, others use a lot of annotations and dependency injection, still others have gone fully functional since Java 8.

      And then there are shops like one of my employers, where a large codebase and poor teamwork has resulted in a mishmash of all of the above, plus some sections that have no organizing principles at all.

      35 replies →

    • > IDEs and code generators have replaced a lot of the more stupid boilerplate. Not that there isn't a lot of stupid boilerplate in Java but it's been greatly reduced by tooling.

      I've been dealing with Java for about four years in an academic setting, not professional. When observing Java code in workplaces, the code bases have universally been bloated monstrosities composed mainly of anti-patterns - but that was hopefully down to the era these applications were written in (J2EE, Struts, etc).

      My experience is that:

      * Auto-generated code is still visual (and debugging) noise

      * Annotations like Lombok's are great, but are "magic" abstractions, which I find to be problematic. They add cognitive load, because each specific library has its own assumptions about how you want to use your code, as opposed to built-in language constructs.

      * Especially for Lombok, I can't help but think adding @Getter and @Setter to otherwise private fields is a poor workaround for a simple language deficiency: not having C#'s properties { get; set; }. I feel the same about libraries that try to circumvent runtime erasure of generic types.

      * Compared to C#'s ASP.NET (core), I find fluent syntax configuration with sane defaults and "manual" DI configuration much more manageable and maintainable than auto-magic DI as in Spring, because at least it's explicit code.

      * Java tooling (and if previous points weren't, this is definitely a subjective stance) just seems inferior and to set a low bar in terms of developer experience - maven or gradle compared to nuget, javac compared to dotnet CLI, executable packaging... As to other tooling, I suppose you're mainly referring to the IntelliJ suite?

      I think C# (and by extension, Kotlin) had the right idea in seeking a balance through removing as much boilerplate as possible in base language constructs. Adding libraries is fine, but shouldn't be a workaround to evolving the language.

      3 replies →

    • AutoValue makes a lot of this easier, but you're right that vanilla Java is quite terse, much more than needed.

  • "The most tedious work I do right now is adding "one more" scalar or complex data-member that has to travel from Point A in Method 1 to Point B in Method 2 - I wish I could ctrl+click in my IDE and say "magically write code that expresses the movement of this scalar piece of data from here to here" and that would save me so much time."

    All of this is possible today and not even that hard (though it's harder than meets the eye, there's a lot of issues that description glosses over that you have to deal with, especially in conventionally-imperative languages). The main problem you face is that the resulting code base is so far up the abstraction ladder that you need above-average programmers to even touch it. (I am assuming that this is merely a particular example of a class of such improvements you would like made.) This is essentially the same reason why Haskell isn't ever going to break out of its niche. You can easily create things like this with it, but you're not going to be hiring off the street to get people to work with it.

    Or, to put it another way, a non-trivial reason if not the dominant reason we don't see code written to this level of abstraction is the cognitive limitations of the humans writing it.

    I know HN doesn't really like this point sometimes, to which I'd ask anyone complaining if they've mentored someone a year or two out of college and fairly average. You can't build a software engineering industry out of the assumption that John Carmack is your minimum skill level.

  • Rich Hickey and Clojure have a low-tech solution for you: use maps. This “wiring through all the layers” problem is basically self-imposed by the use of static typing for data objects. Instead you should mostly pass around maps, validate that the keys you care about are present, and pass along the rest.

    Of course your Java peers aren’t going to be happy about this, so in some ways a new language is needed to establish a context for this norm. But the limitation isn’t physical, not even in Java.

  • I use java8 at my dayjob.

    It's been years since I did any of that, as Lombok and spring boot generate that code for you.

    Immutable classes get a @Value and maybe @Builder annotation, muteable ones get @Setters etc.

    Springs auto wiring for beans is sadly magical however, so much harder to figure out what went wrong if you have any issues...

    • It's weird to me how you find the magic of spring sad while you find the magic of Lombok acceptable.

      Lombok requires that you use a supported build system and IDE and while all the currently relevant ones are supported that is no guarantee. Needs plugins and agents that support your various tools' versions including the JVM itself. I've been in that hell before with AspectJ and the aspectJ compiler vs eclipse plugin (version incompatibilities that made it impossible to work efficiently until they fixed it all up).

      Disclaimer: last company we used Lombok. Current company we are switching certain things to Kotlin instead. data classes FTW for example. I do miss magic builders. Builders are awesome. Building the builder is tedious ;)

      11 replies →

  • > the granddaddy of OOP languages: Java

    I disagree with this statement. Java just happened to become popular due to its C style syntax and various accidents of history.

    Smalltalk is the true grand daddy of OOP languages and none of the issues you talk about apply there.

  • > Still to this day, I have absolutely no idea how people can write Java for line-of-business applications (its bread-and-butter!) and remain sane from having to manually manage data-flow, implementing Java Beans, and manually writing by-hand getter-and-setter methods...

    Lombok, at the very least, eliminates “manually writing by-hand getter-and-setter methods” (https://projectlombok.org/).

    • Thank you. I stopped using Java on a regular basis around late-2009-ish, which was before Lombok became really popular (as far as I know) so it is encouraging to hear that writing Java in-practice isn’t as bad as I feared.

      Still... I feel strongly that Java eventually needs to adopt object-properties and reified-generics for it to stay relevant - otherwise it offers fewer and fewer advantages over competing languages - at least for greenfield projects at first, and eventually it’ll start being _uncool_ and fail to attract newer and younger devs to keep the ecosystem alive. Then we’ll end up with the next COBOL (well, more like the next Pascal/Delphi...)

      1 reply →

    • Lombok ends up having all the costs of using a better JVM language (you still need to integrate it into your coverage tools, code analyzers etc.) but with few of the benefits. I used to use Lombok but in the end it was easier and better to just use Scala.

      3 replies →

  • But when you read a novel, it's full of excessive and redundant code.

    You don't write code for the machine, you write it for your team. It's fine if it's nice and comfortable, a bit repeated and fluffy, rather than terse and to the point.

    Your code is only read by humans.

    • This is exactly my grudge with boilerplate. Code is being read much more often than written.

      I don't care if you hand-coded all those buckets of accessors, or your IDE has generated them -- that's irrelevant to that they're still overwhelmingly useless noise. Which I need to read through, which I need to review in PR diffs, skim in "find symbol usage" output, class interface outlines, javadocs, etc etc -- all that 10 as often as during writing. Somehow I'm expected to learn to ignore meaningless code, while producing it is fine?..

      Remember the point made in "green languages, brown languages" recent post here on HN? The insight for me there was the source of "rewrite it from scratch" urge which should be very familiar to engineers working in the field. It comes from incomprehensible code or weak code reading skills. Either way, boilerplate does nothing but harm.

      So no, while I agree on your point that code exists principally to be read by humans (and as a nice secondary bonus, executed by machines) -- I disagree that boilerplate is "fine" whatever its incarnation. It's not, because it directly damages the primary purpose of code: its readability.

  • > Still to this day, I have absolutely no idea how people can write Java for line-of-business applications (its bread-and-butter!) and remain sane from having to manually manage data-flow, implementing Java Beans, and manually writing by-hand getter-and-setter methods...

    My long-standing view is that Java's strict and verbose OOP syntax and semantics are an interface for IDEs. People who are hand-coding are practically guaranteed to be baffled by the verbosity, but they forget that Java development was the driver for IDE evolution (afaik), such that now we have ‘extract method’ and similar magic that understands code structure and semantics.

    More specifically, OOP works, or should work, as an interface for IDEs that allows to (semi-)programmatically manipulate entities on a higher level, closer to the architecture or the problem domain.

    Like you, I wondered if this manipulation can be harnessed and customized, preferably in a simpler way than giving in to the whole OOP/IDE/static-typing tangle and without writing AST-manipulating plugins for the IDE. In those musings I ended up with the feeling that Lisps might answer this very wish, with their macros and hopefully some kind of static transformations. Which are of course manipulating ASTs, but it seems to be done somewhat easier. Alas, predictably I've had no chance of doing any significant work in a Lisp, so far.

  • FYI for c# you have resharper allowing to add parameters to method and it would automatically propagate passing it through several levels up based on references. Guess sometimes all you need to know are the right tools.

  • > granddaddy of OOP languages: Java.

    Nowhere near. There was a lot of OOP hype in the early 90s with Smalltalk and C++, so Java just went all-in (everything is in a class) on that trend of the times.

  • Could you give a concrete example of your problem in a gist or something? I'm curious if it's solvable in C# as is. Sounds like it may be the kind of thing I'm approaching with reflection and attributes right now.

  • If you're writing in Java, why not write in Kotlin? They're sufficiently compatible you can have Java and Kotlin files in the same directory structure, compiled with the same compiler.

  • Well, in the case of Java there definitely are ways to minimize the boilerplate. Some of the more common ones that i use:

      - Lombok library ( https://projectlombok.org/ ) generates all of the getters and setters, toString, equals, hashCode and other methods that classes typically should have (JetBrains IDEs allow you to generate them with a few clicks as well)
      - MapStruct library ( https://mapstruct.org/ ) allows mapping between two types, between UserEntity and UserDto for allowing mostly similar objects or ones that are largely the same yet should be separate for domain purposes
      - Spring Boot framework ( https://spring.io/projects/spring-boot ) allows getting rid of some of the XML that's so prevalent in enterprise Java, even regular Spring, and allows more configuration to be done within the code itself (as well as offers a variety of pluggable packages, such as a Tomcat starter to launch the app inside of an embedded Tomcat instance)
      - JetBrains IDE ( https://www.jetbrains.com/ ) allows generating constructors, setters/getters, equals/hashCode, toString (well, there are covered by Lombok), tests, as well as allows for a variety of refactoring actions, such as extracting interfaces, extracting selected code into its own method and replacing duplicated bits, extracting variables and converting between lambdas and also implementing functional interfaces, as well as generating all of the methods that must be implemented for interfaces etc.
      - Codota plugin ( https://www.codota.com/ ) offers some autocomplete improvements, to order them by how often other people used any of the available options, though personally there was a non-insignificant performance hit when using it
    

    As far as i know, there is a rich ecosystem for Java to allow treating the codebase as a live collection of a variety of abstractions which can be interacted with in more or less automated ways, as opposed to just bunches of overly verbose code (which it still can be at the same time). Personally, i really like it, since i can generate JPA annotations for database objects after feeding some tools information about where the DB is and allowing them to do the rest, as well as generating web service code from WSDL (though i haven't used SOAP in a while and noone uses WADL sadly, though OpenAPI will get there).

    And then there's attempts like JHipster ( https://www.jhipster.tech/ ) which are more opinionated, but still interesting to look at. I think that model driven development and generative tooling is a bit underrated, though i also do believe that much of that could be done in other, less structured languages, like Python (though that may take more effort) and probably done better in more sophisticated languages, such as Rust.

Low Code/No Code solutions don’t work because the people involved in implementing solutions are rarely engineers themselves. Most (good) engineers have learned through training and/or experience, well, engineering things, like edge cases, error handling, user experience, efficiency, testing, maintainability, automated testing, and a plethora of other subtle and obvious aspects of system design. I know this quite well because I’ve worked with these so-called low-code and no-code platforms and every one of them I have seen end up having to be taken over by experienced engineers who have been brought in to fix (or in some cases completely rebuild) a poorly-designed system. These platforms typically suffer the “last mile” problem as well, requiring someone to write actual code.

  • And there's been the business process engine craze in between. BPEL comes to mind which also has 'visual editors' for the business people to use.

    It's too complex for them and the you pay Software engineers to use BEPL instead. Which is just a worse language to actually program in than the underlying system.

    Or any other number of 'process engines' which give you a worse language to describe your actual process in and then you need to do stupidly convoluted things to do simple things. But hey, we didn't have to code!

    • I worked on a Pega project once. There was nothing in there that the business people would be able to touch, especially after the requirements exceeded the capabilities of Pega’s primitives. One of the local friendly FTEs (the dev work was contracted out) would’ve been happy to use C#/ASP.Net web forms like everything else in the org.

  • > Low Code/No Code solutions don’t work because the people involved in implementing solutions are rarely engineers themselves.

    In my experience these are usually too complex for non engineers to understand and incredibly frustrating for engineers to use.

Some people see past tries at something as proof that something will never work. Others see past tries at someone having the right idea, but wrong implementation.

Imagine how many tried flying before we "invented flight", and how many said "oh how they won't learn from the past".

  • I think that's a fair point. The way I see it, going from requirements (even visual ones) to working system would require strong AI, as any sufficiently powerful visual environment would wind up being Turing complete.

    Which means that no code is either use case bounded or claiming something roughly on par with a break through. The first is common enough and where I imagine most low/no code offerings fall when the hype is stripped away. The hype seems to promise something on par with the second and I think that's where the dismissive attitude comes from.

    • Functional and declarative programming are mostly specifying requirements directly. You don't need a AI to do it, in fact that would be the wrong tool (AI is good for fuzzy problems and inference - not following a spec).

      An extreme example of this are logic and verification systems like prolog and TLA+.

      There is a sweet spot of low code I haven't seen explored yet, which is a declarative system that is not Turing complete. That would be an interesting avenue to explore.

      6 replies →

  • True, but on the flip side imagine how many people tried transmuting lead into gold, thinking the previous attempts simply used the wrong approach.

    • They were right. The previous attempts did in fact use the wrong approach, and people have now successfully turned lead into gold. The only problem is that it’s too expensive to be worth doing.

      6 replies →

    • To be honest we actually figured even this one out.

      It just requires a particle accelerator and the amounts are so tiny that it’s ridiculously expensive. But hey, we can still do it!

  • Either outcome is possible.

    Many alchemists tried to turn copper to gold as well. They might as well think that their predecessors are just unlucky by using the wrong implementation.

    • And they were correct: we do know how to turn copper to gold now; it's just prohibitively expensive.

No Code is mostly a code word for outsourcing. You use their app to get it started, realize it won’t meet your requirements, and then pay them to work on it forever. Unless it’s just a marketing Website.

  • No Code I feel like could be also viewed as a compromise for selling dev tools to mass market. You can sell a "cheap complete*" solution instead for the overhead of also dealing with customer issues / inevitably helping train a dedicated person for them to maintain their app. Then you have customers who need dev tool support as intended

I think this is only partially true. There are aspects of coding which can be abstracted away, either because they're essentially boilerplate or because a simpler description of the solution is sufficient. Ideally if a more complex description is required, one can drill down into the simplified low-code description and add sufficient complexity to solve the problem.

I mean, couldn't many of the existing frameworks be described as low-code wrappers around more complex work flows and concepts?

  • > many of the existing frameworks be described as low-code wrappers around more complex work flows and concepts

    Using frameworks, you are still using the language itself to command the frameworks. For example, if someone claims oneself as a React programmer, nobody would assume that someone didn't know Javascript.

    So to efficiently use one framework, you should master both the language + framework. In other words, the complexity not only remains, but also accumulates.

    But this is contradictory to low/no code's selling point, as they are targeting non-programmers.

    • This only goes so far, though, with frameworks. In my experience, the vast majority of people that make claims about a particular framework do not understand the abstractions they are building upon. In fact it is sufficiently reliable that I have found this to be an excellent hiring signal, to probe how well a person understands the abstractions in frameworks they use, but also to probe how they diagnose and fix holes in their own knowledge.

Everybody promises their no-code solution is going to adopt to the way your enterprise already works, but the truth is you kind of have to go the other way around if you don't want misery.

  • I work at Stacker (YC S20) [0] and the approach we're taking to deliver on this promise is to start with the data.

    That is, we let you take spreadsheets you already use and build more powerful collaborative tools on top of them, without code.

    If you take the premise that a tool has a 'data' part, and an 'app' part, and that the data models the process, and the app more just controls how data is accessed, presented, the UX, etc, you might see why I'm so excited about this approach -- if you take the data from spreadsheets that are already being used to model a process in action, by definition you don't have to change your process at all.

    [0] https://stackerhq.com

    • About 30 years ago one of my managers used to say "get the data model right and the application writes itself" and I have found that to be mostly true. What I have also often found is that people who create spreadsheets in business don't understand data modeling and even if the spreadsheet solves some business problem it's often very brittle and hard to change and adapt or generalize.

      5 replies →

  • Salesforce kinda nailing it (and I say that as Salesforce code crafter, not their no code user).

Some strange comments in here about Low Code, as if they weren’t already successful. There are easily hundreds of apps successfully making use of Low Code to solve problems for people. Some Marketing Automation tools have had them for 10+ Years. Integration tools are also often Low Code.

  • Have any examples? (Genuine question, not an attack!) I've mostly ignored the Low/No Code stuff for a long time.

    • Microsoft's Power Platform is a low code framework which works well, and generates a massive amount of revenue, as does Salesforce and some others. I recently designed and implemented a complex 500 user child protection application with PP that has been live for a year now. It was highly successful, and the time and cost taken to deliver it was far less than the cost of a hand written solution. That said, there is still quite a lot of custom code required for most enterprise level solutions even with the most mature low code platforms. Low code is not a panacea, and the same issues of how to represent requirements and design arise in the low code world as in the high code world. Low code platforms will continue to mature and improve. Maybe AI will catch them one day, but I'd be surprised if that happens anytime soon.

    • In 7 months, over 8,000 apps were created with Budibase. Many of these are either data based (admin panels on top of databases), or process based (approval apps).

      Budibase is built for internal tools so the apps are behind a log in / portal.

    • Microsoft Access and Claris FileMaker have nearly 3 decades of success at low-code.

      I genuinely think they get a bad wrap because the really successful apps you never hear about, but the problematic ones need a real programmer to sort out.

    • Integration - IFTTT, Zapier, Boomi, Jitterbit, Workato, and on and on.

      Marketing Automation - Marketo, Klaviyo, Mailchimp as a few examples.

      Airtable is another that has low-code automation built in

Nonsense, No/lo-code is the polar opposite of UML, No-code is the ultimate Agile, it’s exciting and fun to build with, because it’s alive, because it executes immediately, resulting in a powerful iterative feedback loop. UML is static and tedious to build, because any gratification is delayed so far into the future. I know because I’ve done both, in fact I’ve invested all of my wealth (many millions) into developing a No-code ERP/CRM platform and it’s incredible - will launch this year.

Comparing UML and No-code is apples to oranges. UML is about generic abstraction without actual implementation. No-code is about domain-specific implementation done using simplified high-level visual constructs instead of general-purpose programming languages. In other words, No-code is programming (just not text-based), while UML is modelling.

Low-code/no-code is simply the CASE tools of the late 80s, or the UML->production system fully automated pipeline of the late 90s/early 2000s, given new life and a shiny coat of paint. The same problems apply and the same people keep buying the same damn snake oil.

Once you can specify your procedures, requirements, and constraints in a way that is specific enough for a computer to read and act meaningfully on, the elements of your specification method become isomorphic to constructs in some programming language. So you've replaced typed-in keywords with clickable symbols or buttons or controls -- but you've in no wise reduced the headwork of programming or made the programming go away.

A spreadsheet is a low code app. Less flexible than a general purpose programming language, but still extremely valuable.

If low code apps simply provide more flexibility and maintainability than a spreadsheet, they’re already winning.

I strongly believe that every tool, every invention, can only innovate/be innovative in one area.

As such what we need is to have the right building blocks and abstraction layers which at the end will mean that something like no or low code will work. It will only work when all the tools that underpin it have been crystallised over the years.

This happens on every layer and is fundamentally why we see so much work repeated, but slightly different. Every language makes different trade offs, therefore all the libraries implement the same functionality but just a bit different this time.

Every once in a while something like UML (too complicated, e.g., due to the use of EJBs), Business Works (too slow), etc comes along which has promise and offers value at the time but just misses the boat to survive until the next generation of revised underlying tools.

I think a certain set of problems requires the thinking of someone who knows how complex systems work and where the pitfalls are.

You can even see this with stepped covid restrictions that rely on infection numbers crossing a certain threshold. Most engineers wlould imidiately see the real world consequences that arise from the lack of hysteresis.

Similar things happen with input sanitization, deciding on formats etc.

Some stuff just takes experience. The actual writing of the code is not the problem, the knowledge of what to do and what to avoid is.

They're trying to commodify writing code. It would bring down the cost of programmers significantly. They won't succeed, I think. Instead AI will probably beat them to it.