← Back to context

Comment by hintymad

5 years ago

IBM used to push the adoption of their business process software for exactly the same reason. They imagined that "business process experts" use UML to construct the entire business process, and then the software (based on WebSphere Application Developer, an Eclipse-based IDE) will generate all the execution code, including deployment scripts. The irony is that the UML itself becomes more complex than code, and dozens of layers of exception trace were simply incomprehensible to engineers, let alone to "business process experts". To add insult to injury, IBM mandated generating tons of EJBs. Even thinking of that induces migraine.

P.S., It's surprising that those who advocate that UML is better than code didn't understand the essential complexity would not go away simply because we switched a language, as essential complexity lies in precisely specifying a system. Neither did they understand that that a programming language offers more powerful constructs and tools to manage complexity compared with UML.

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.

      41 replies →

    • "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...

      13 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/).

      6 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.

      1 reply →

    • > 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!

      1 reply →

    • > 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.

      7 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.

      8 replies →

    • 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.

      1 reply →

  • 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.

      2 replies →

  • 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

      7 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.

  • 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.

What sometimes gets forgotten is that even a programming language _is_ a model! And it is a model that fits exactly all the details that are necessary to construct an actual program with all the little special cases.

Modeling all constraints and runtime behaviors in UML is cumbersome and hard to understand. UML could be used for showing larger building blocks or complex flows (e. g. with sequence diagrams), but it is a bad fit to model a complete program in it.

> The irony is that the UML itself becomes more complex than code...

I forgot the law's name but the said law states that "a machine of a certain complexity cannot build a machine more complex than itself". So, a car factory is more complex than a car itself. Similarly a code generator cannot produce something more complex than itself.

This is why you need to merge things of certain complexities to build something more complex.

  • > I forgot the law's name but the said law states that "a machine of a certain complexity cannot build a machine more complex than itself"

    Isn't this disproved by the evolution of reproductive organisms? That's not necessarily more complex of course, but it's pretty obvious that over a large enough time scale successive machines can become more complex.

Could the problem simply be that UML was poorly designed for the job?

Just because certain information has an essential complexity doesn’t mean that different representations are equivalently complex. There’s an essential complexity to the layout of the London Underground, but it would be considerably worse if you had to represent it with plain text files instead of maps or diagrams.

I agree that UML was wrong-headed and simply ignored this complexity instead of addressing it seriously, but I wouldn’t be surprised if it turned out that some diagram-based programming language would be useful for something.

  • Simulink, labview, and gnu radio are all fairly well adopted though they all have their problems. They are all notably not oop, at least not idiomatically. In fact, as most blocks are stateless other than their configuration, you might say the paradigm is closest to functional. UML, with the exception of flow charts was very OOP centric. In a world where I still come across people who use OO as a synonym for "good" I can see why they created it that way, but a tool that shapes your design space can be limiting.

    The lack of detail in the models means autogenerators have to have lots of configuration for each item in the diagram. People would brag that 95% of their code was autogen, and I would realize they had spent dozens of hours figuring out ways to use checkboxes and menu selections to generate the code they wanted. Instead of typing it. And all the hideous autogen vode was a nightmare to step through in a debugger. Large labview projects aren't any better really, but they are popular.

    • > UML, with the exception of flow charts was very OOP centric. In a world where I still come across people who use OO as a synonym for "good" I can see why they created it that way, but a tool that shapes your design space can be limiting.

      To be fair, that can’t be the only reason UML sucks, or even the main reason, because the same is true of Java, and while Java sucks, it’s a much better programming language than UML.

      I think a lot of it really does come down to a denial of essential complexity. If you designed a visual programming language in such a way as to actually accept and handle essential complexity you’d be on a better track.

      > The lack of detail in the models means autogenerators have to have lots of configuration for each item in the diagram. People would brag that 95% of their code was autogen, and I would realize they had spent dozens of hours figuring out ways to use checkboxes and menu selections to generate the code they wanted. Instead of typing it. And all the hideous autogen vode was a nightmare to step through in a debugger. Large labview projects aren't any better really, but they are popular.

      I haven’t worked with these systems you’re discussing, but it sounds like people would be better off handwriting more of the code and only using the visual tools for the part that they’re actually better for. In much the same way that a Wikipedia article about elephants includes photographs of elephants instead of merely relying on long-winded textual descriptions of their appearance, while still having lots of text for the sorts of things text is good for representing.

      I think maybe GUI interface builders or HyperCard might be another example of this hybrid approach. I think some incarnations of SmallTalk included similar ideas.

      2 replies →

    • What I have found with GNU radio is that pretty soon, you wanna drop out of the 'graph' view, because you want to dynamically reconfigure your graph.

      1 reply →

  • > Just because certain information has an essential complexity doesn’t mean that different representations are equivalently complex. There’s an essential complexity to the layout of the London Underground, but it would be considerably worse if you had to represent it with plain text files instead of maps or diagrams.

    In general yes. I was only commenting on the assumption that UML can be of a general-purpose programming language, at least in the domain of business automation, or the idea that sufficient modeling can replace coding given the current technology.