back to article The case for handcrafted software in a mass-produced world

A thought experiment: If the computer business responds to commoditization and globalization like other manufacturing industries do, where does that leave programmers – and users? This piece is the second in a series titled: The future of software. You can read Part 1 over here. The advent of mass-produced software The …

  1. Pascal Monett Silver badge

    "an LLM bot can write new code"

    Maybe it can, but if it hands out the same abominable mess that MS Word dishes out when you wish to save in HTML, then I will do fine without it.

    That said, I have seen the results when asking ChatGPT for a LotusScript function that checks all the documents in a Notes view and I have to admit, while I wouldn't have written it exactly like that, the code provided does work, so maybe, just maybe, there might be a possible future where you could ask WhateverGPT for a functional Windows kernel without the cruft and get something that actually works and respects your computer (and allows you to play your games).

    Here's hoping.

    1. Ken Hagan Gold badge

      Re: "an LLM bot can write new code"

      If you had hand-written the code and fed it to a modern compiler then an assembly language expert might well describe the result as "I wouldn't have written it excactly like that [but] the code does work". In fact, all computer languages are just a way of writing down *requirements* in a computer-readable form and if your source code does not express your requirements properly, you should not be surprised that the resulting program doesn't do the right thing.

      Natural languages, with all their ambiguities, are a truly terrible way to specify requirements and so the first job for most software development projects is to "translate" the plain English requirements of the customer into something at least a *little* bit more rigorous. (<snark>I think this used to be called "analysis", back in the day when people bothered to do it.</snark>)

      There have been many attempts over the years to persuade a machine to generate code in response to some "prompt" or other. I think it is helpful to divide them into two groups.

      The first group is "compilers" and these work quite well. In this model, the "prompt" is in a language with carefully delineated semantics and a careful reader of the prompt can make a reasoned guess whether the resulting output (object code) will actually do what is intended. A key point (though not usually emphasised because it is so stunningly obvious) is that human beings are not supposed to need to read the output.

      There is a second group of code generators, exemplified by various CASE tools over the decades. These have never gained widespread use. In this model, the "prompt" is less well delineated and the human reader is expected to read (and subsequently maintain!) the output. Using LLMs to generate code would fall into this second group and in my opinion are likely to suffer the same problems (and the same long-term fate) as all other CASE tools.

      Domain Specific Languages belong in the first group and have a proven track record. They are a bit harder to produce than simply chatting to WhateverGPT, but the pay-off is correspondingly greater. An LLM's ability to digest the loose language than humans insist on using *might* be a useful component of a DSL design tool. That seems, to me, to be an idea worth exploring. However, if you want reliable software, I still think that the end product of such a design tool has to be a DSL (a prompt language) that has all its semantics nailed down so that you can reason about your code and (ideally) prove aspects of its correctness.

      1. LionelB Silver badge

        Re: "an LLM bot can write new code"

        > <snark>I think this used to be called "analysis", back in the day when people bothered to do it.</snark>

        Steady on. For several years in the late 80s/early 90s, my official job title was Systems Analyst (promoted from lowly software engineer) for a well-known UK national telecoms company. It was the most difficult and demanding job I've ever done. The most valuable lesson I learned was this: talk to the client - the people who are actually going to have to use the system. They know what is needed, in a way that management invariably do not.

        > There is a second group of code generators, exemplified by various CASE tools over the decades. These have never gained widespread use. ... Using LLMs to generate code would fall into this second group and in my opinion are likely to suffer the same problems (and the same long-term fate) as all other CASE tools.

        Fully agreed. In my experience, the problem with CASE tools was that they never quite fitted your scenario, so you ended up fighting the tool when you should have been getting on with the job. Of course management then, as now, thought they were magic bullets.

  2. Steve Davies 3 Silver badge

    Only 36 years?

    You young whippersnapper you. There are some of us with more than 50 years under out belt.

    Us oldies come from a time when every byte counted when it came to memory use. We would craft our progs to fit into the available RAM. Little tricks like changing the addressing modes of a set of instructions could save a few dozen bytes.

    High level languages (even C/C++) takes that away from the developer.

    Now we get endless class libraries (libs that call libs that call libs etc etc etc) and we see apps that need 1GB of RAM just to get going.

    I still code and only rarely do I need to use machine code (on some ancient Hardware... A MicroVAX from the 1980's.) I take pride in crafting the most efficient code I can.

    Progress? Not really and all this AI crapfest is only going to make things worse. Just when we thought that we had got over the habit of copying broken code from places like StackOverflow and using that in apps, along comes the AI shitfest and it will be 100,000 times worse.

    We are doomed I tell ye, doomed.

    1. Caver_Dave Silver badge
      Boffin

      Re: "I take pride in crafting the most efficient code I can."

      "I take pride in crafting the most efficient code I can."

      Do you check the assembler produced?

      Sometimes the most efficient 'C' code does not make the most efficient assembler, as the compiler cannot "use all its tricks" on very good 'C' code and slightly "rough" 'C' code can be optimised into something smaller.

      I write a certifiable deterministic real-time operating system - we have to be aware of such things, when we are proving code to be correct.

      1. LionelB Silver badge

        Re: "I take pride in crafting the most efficient code I can."

        > Sometimes the most efficient 'C' code does not make the most efficient assembler, as the compiler cannot "use all its tricks" on very good 'C' code and slightly "rough" 'C' code can be optimised into something smaller.

        Yup, learned that the hard way. You generally don't want to second-guess a modern compiler; the guys who wrote it almost certainly understand optimisation better than you (or at least I) do - especially when it comes to exploitation of hardware features. I rue the cumulative hours spent faffing with awfully clever pointer arithmetic, only to find that a much simpler (and certainly more readable) array implementation compiles into faster and leaner code.

    2. Rafael #872397
      Windows

      Re: Only 36 years?

      You young whippersnapper you. There are some of us with more than 50 years under out belt.

      Yesterday I was explaining punch cards and Basic to some younglings, and most of them "had heard about C".

      Describing "pointers" was pointless, according to their facial expressions.

      I'm ready to retire! Dulce far niente, I await your sweet embrace!

      Now get off my lawn.

    3. doublelayer Silver badge

      Re: Only 36 years?

      "I take pride in crafting the most efficient code I can."

      But using what metric for efficiency? Because if you're basing your pride on using the fewest possible bytes of RAM, you may be writing inefficiently in so many other ways. Old programmers know this as well if not better than anyone, because sometimes that has to be balanced against the also restricted CPU cycles. In many other cases, programming time or ease of maintenance should take precedence. While there is lots of inefficient code, not everything that uses lots of RAM is inefficient. Quite a lot of it is properly optimized for a world where RAM is cheap and programmer time is not.

      As an example, I've written a program that uses about ten gigabytes of RAM. It doesn't have to do that. About 9.9 of those gigabytes are a lot of caches. I could quite easily load that from disk when needed and run in 100 MB. I don't because runtime is better with that caching. Of that 100 MB, I could probably cut that to 10-20 MB. I don't because the benefit of writing quickly without worrying about the 80 MB is more efficient when I have at least 16 GB in my laptop than spending time optimizing, and because I change this program often. It rarely runs exactly the same way from month to month, so adding extra functions is worth the cost to make that fast.

      1. Mike007 Bronze badge

        Re: Only 36 years?

        I remember back in the day I had a need to render a table on a web page and found that sending an array of data and rendering the table on the client was faster than waiting for a 56k modem to download 500k (compressed) of HTML. It got the size down to about 10k which downloaded in a few seconds, but then your CPU sat at 100% for about 20 seconds before displaying. That was the heavily optimised version

        Today I write nearly everything in JavaScript, computers are a little faster so the optimisation in terms of ease of coding means there are very few projects where I can justify needing to do it in C any more...

  3. Neil Barnes Silver badge

    Old school...

    My ability to remember the 6502 and 8085 instruction sets, and my delight in building small, impractical, and essentially useless programs for my own amusement will stand me in good stead in my retirement...

    I wonder how we went from 'this processor is nice, but it can't easily handle large datasets' to 'ooh, huge, let's fill it up with something pretty but not necessarily useful'?

    1. Steve Davies 3 Silver badge
      Childcatcher

      Re: Old school...

      Parkinson's Law rules ok!

      https://en.wikipedia.org/wiki/Parkinson's_law

      1. Will Godfrey Silver badge
        Unhappy

        Re: Old school...

        Alternatively:

        Shit expands to fill the space available for it's accretion.

  4. Bebu Silver badge
    Windows

    "Small can be mighty."

    Every time I fire up LibreOffice to read some gratuitously .docx encoded text document I am reminded that forty years ago most similar documents were written on mechanical or electric typewriters in single mono typeface. Even during the next two decades documents, especially email, weren't embellished with too much more.

    Wordprocessors originally were small and pretty basic and to be honest were about as fully featured as the majority of user could ever use.

    Now over 95% Word's or LibreOffice's capabilities are unused or unknown to the majority of users (moi included.)

    As for spreadsheets - those using them shouldn't, those who should... should know better.

    Surprising what you could do on a CP/M-80 machine with a subset C compiler and some unix like tools. With a C translation of a modified SWTP fmt program I wrote and printed a fair number of text documents. (Still use groff -mom ;)

    I am hoping "small" will stage a "comeback."

    I don't know what the current Plan9 kernel source runs to, but I would be surprised if it were a million lines. Kernels don't need to be monolithic or humongous but like most software just better designed.

  5. Tubz Silver badge

    Oh the thought Of Microsoft Windows coming with a guarantee, I bet the lawyers will love being paid for loopholes, the first patch Tuesday that breaks it.

    1. Doctor Syntax Silver badge

      It could be a case of being careful what you ask for. Demand software with guarantees and you get no software.

      1. ecofeco Silver badge

        Don't threaten us with a good time.

  6. Bebu Silver badge
    Windows

    "pointer arithmetic that doesn't translate to languages outside the C family"

    I am not sure it is the pointer arithmetic that doesn't translate but rather the primitive concept of pointers.

    My suspicion is the primary source of trouble is C's arrays not being first class objects with the consequent ambiguity between a pointer to an object and a pointer to an array of the same object type.

    Modula-2's conformant arrays was the sort of thing that would have been nice in C89 but, even at that time, I guessed it would have broken too much existing code.

    C's type casting is often inpenetrable even to the veteran and coupled with concurrent pointer arithmetic is invariably beyond anyone's ken.

    1. DanielsLateToTheParty
      Stop

      Re: "pointer arithmetic that doesn't translate to languages outside the C family"

      I'm currently relearning C and, feeling open minded, let AI help me with writing snippets. Genuinely it impresses me that it's able to not only write real code but makes it legible and explains what everything should do. However the downside is while it all looks reasonable sometimes the compiled code just doesn't work, not even with tweaking. To think that bots can grok an ancient codebase well enough to recreate it elsewhere is laughable.

  7. Anonymous Coward
    Anonymous Coward

    Alternative view: make languages better

    Maybe the fact that LLMs can write [some] code is telling us more about programming languages than it is about LLMs?

    As an LLM skeptic, the one pushback I hear that gives me pause is programmers saying "OK, it's not much good for most things, but it is useful for rapidly creating repetitive blocks of code, leaving me to focus on the creative/difficult stuff". And that that sounded reasonable to me until I asked myself: why are we writing repetitive blocks of code? Why do they exist at all?

    The history of programming languages - and the compilers that make those languages possible - has in large part been about making programmers more expressive. And by "expressive" I mean two things: (a) writing more code in fewer instructions, i.e. productivity, and (2) increasing the likelihood that those instructions are correct. This has been going on since the first macro assemblers and autocoders. It has been happening since the first time somebody said "what if we could explicitly write IF...THEN or FOR loops instead of "decrement counter" and "branch if nonzero"? Or "what if strings were first class data types instead of arrays of characters that have to be manipulated with care and precision?". Think how many off-by-one errors were avoided when languages became able to implicitly iterate over the elements of an array rather than writing a FOR loop that explicitly indexed the elements; how many null pointer exceptions were avoided by being able to manage lists with built-in language constructs instead of pointer manipulation; or on a more basic level, how many wasted processor cycles have been saved because programmers don't have to remember that two-dimensional arrays are ordered *like this* in FORTRAN but *like that* in Pascal? And consider the associated unit tests eliminated when you no longer have to worry about the edge case of overrunning the end of the linked list or indexing past the end of an array.

    And yes, programming languages have sometimes taken wrong turns in this pursuit (to avoid pointless controversy I won't name names), but they usually find their way back; I would cite Rust and Go as languages that, each in their own way, are big improvements.

    So... maybe the lesson from using LLMs as coding assistants is this: we should be looking at the code that LLMs can generate and ask ourselves: why can an LLM generate that code? Why can it be generated at all? Why isn't the instruction that the programmer gave the LLM - or at least some formalized version of it - simply embedded in the language, or alternatively in a framework such that the programmer can invoke it themself with a single instruction, confident that it is correct rather than hoping/assuming the LLM generated it correctly this time?

    A quarter of a century ago the creator of a then-popular framework said something to me that completely upended my opinion of code generation: "Anything that can be generated can be generalized. And anything that can be generalized can be pushed down into the framework."

    1. tiggity Silver badge

      Re: Alternative view: make languages better

      @AC

      "why are we writing repetitive blocks of code? Why do they exist at all?"

      Lots of examples.

      A classic would be data validation

      Whether its the very simple stuff, e.g. you have a property* that is a "string", you may decorate the definition with max, min allowed length as a trivial example (and similar "repetitive" code for the other properties in that class)

      More complex, done in code validation can be repetitive

      e.g. address validation - does it have a "postcode" (zipcode for US) - if so does the format match the postcode rules of the country that address is declared for, if it does, is there at least 1 further item of address info (sufficient to allow unique id) to go along with the postcode (in the case of a country where a postcode can apply to multiple properties i.e. non unique id such as in UK)

      Data validation code is repetitive and tedious, but a classic example of why repetitive code blocks do happen (and dull but important code as you really don't want to let e.g. too long data get all the way to database & then have to ripple back a SQL overflow error to end user when it's something you can catch early & means the underlying DB (or whatever storage used) does not dictate data rules)

      * feel free to change terminology for whatever programming language you want to imagine, I have tried to use fairly common OO language terms & data type.

  8. Howard Sway Silver badge

    Use an LLM to translate from C to some Oberon dialect, say

    Why? If your ultimate ambition is for LLMs to do all your programming for you then it won't matter whether it uses functional or imperative languages, or which ones it uses : they all get compiled into machine code eventually, so why can't the LLM just cut out the conceptualising of multitudinous programming languages and go straight to producing machine code?

    Anyway, away from fantasy island where we can all easily dream of machines that magically do anything for us, here are the first lines of a program that a LLM made for me at the weekend :

    #include

    #include

    #include

    #include

    #include

    #include

    I'm still pondering why it felt the need to #include nothing precisely 6 times...

    1. Doctor Syntax Silver badge

      Re: Use an LLM to translate from C to some Oberon dialect, say

      I'm reminded of a tool I used long ago to covert C programs using the old Informix ALL-2 library to use embedded SQL. It ended up with a lot of if statements whcih essentially tested nothing.

    2. mike.dee

      Re: Use an LLM to translate from C to some Oberon dialect, say

      Machine code was designed to be understandable and executed by machines, and it was like this from the beginning. Assemblers were written to make easier for people to write more easily the code using mnemonics and not a series of numbers, and because the old processors and microprocessors were way simpler, was easier to understand their structure. Assembly language is still strongly tied to underlying machine, so soon after assemblers, the first compilers and interpreters were made to make easier for people to write what the calculator had to do. Layers and layers of abstraction were added to try to make easier to express what the machine had to calculate.

      Are the LLM the next step of the ladder?

      There's always the underlying problem that people had to express what are the calculations to do at the end, and in most cases they have no idea of what they want.

      1. HuBo
        Headmaster

        Re: Use an LLM to translate from C to some Oberon dialect, say

        Indeed. And for mathematical calculations, as a species, over centuries, we developed a precise and efficient language named mathematics, perfectly suited for it, but somehow the LLMs say we have to reword all of the statements in it as very long, verbose, and imprecise english sentences or somesuch instead ... how intelligent is that?

        I'd rather use Maple, Wolfram Alpha/Mathematica, or MATLAB/Octave for my math computations ...

    3. LionelB Silver badge
      Coat

      Re: Use an LLM to translate from C to some Oberon dialect, say

      Did you try taking one of those out and seeing what happens?

  9. Doctor Syntax Silver badge

    What about the data?

    It's easy for programmers to think that the value of IT is in the code. The real value to a business is in the data; that comprises all the work in progress, on order, accounts and information held for regularity reasons. Without it the business can't function and can't meet tax or other requirements for keeping records. Backward compatibility is about far more than running your new code on older H/W.

    It's all very well having an LLM tweak code or rewrite it based on analysing the code to work out what it does. But it also needs to analyse the existing data to work out what that tells the business which might not be explicit in the code.

  10. Andy 73 Silver badge

    Testing times ahead...

    It seems to me we've established fairly well that most testing only exercises some subset of functionality, and particularly weakens when we're integrating components.

    We've also established fairly well that existing models are not robust, in that they are prone to get derailed by "the most likely problem" (expecting things that look more like their most common training data than the specific prompt they are responding to), giving answers that we politely call hallucinations, but which could more bluntly be described as "wrong". Lest we forget - they do not reason, despite ongoing attempts at reducing error bars.

    So, whilst the advanced auto-complete we're currently seeing can no doubt speed up the time taken to get an idea down into cold hard pixels, there is little evidence that the output can in any way be trusted. For a sufficiently large system, reasoning about the kinds of bugs that auto-generated code might harbour becomes a significant exercise - and one that we can't magically hand over to imaginary tests.

    So the hand plough gets replaced by the tractor driven plough, which is certainly faster but still requires a more skilled operator to achieve the desired results.

    1. collinsl Silver badge

      Re: Testing times ahead...

      How hard is a pixel on the Mohs scale? Also can it be said to be cold? Surely the screen generating it is slightly warm due to the energy of the generation?

  11. HuBo
    Gimp

    we just add to it. That's why it keeps growing.

    Great article! That bit about bloat reminded me of Lindsay's 2021 piece on the trick-cycling of missed opportunities in additive transformations ... might be inescapably built-into our brains ... like quicksand of the human mind!

  12. Paddy
    Thumb Up

    Look up, not down

    Expend more of the computers capacity in making programming higher-level, simpler, and more correct for us.

    For example I state that I need to access this data in a sorted order, and the compiler might suggest a first data structure and sort algorithm, but feedback from subsequent runs could change that, improving the performance over time. The compiler would be free to use insertion sort as the data is read in - or instead sort before this use; or sort as part of an intermediate action.

    Parallisation should also be automated based on examination of un-or-part-parallised source.

    Use the AI to allow us to think bigger, successfully!

  13. heyrick Silver badge

    There's so much of it that it's no longer practical to study it, restructure it, or fundamentally change it.

    Linux began as one man's project that kind of blew up and took over the world. But if it hasn't, that would have been fine too because it was originally a learning exercise.

    The problem with writing a shiny new OS is, well, it's a massive amount of work. It's something that is cropping up in the RISC OS world because huge chunks of 32 bit ARM assembler aren't going to do anything useful on 64 bit processors. Excepting emulation, it's going to pretty much need a ground up rewrite, which is a phenomenal task even for a dinky OS. But it's just like designing and launching any other brand new OS. There's a long period of nothing (while paid and bills need paid), followed by a lot of hoping that that nothing will become something.

    Say what you like about how shiny Windows is, but it has survived many a year. Who is going to want to bet the company on a brand new OS which is unknown, untested, has no software, and may turn out to have architectural issues unknown at the beginning? And, of course, may take twice as long to write as originally planned (or three times if they try to get an LLM to assist). Or, maybe, the potential users will just be "meh" and stick with what they know and all that effort will have been for nothing.

    I think this is why it's just a continual dance of fiddling around the edges and screwing with the UI to make it look "new".

  14. Electronics'R'Us
    Holmes

    Small...

    In the murky world of microcontrollers and sensors there are often situations where an OS is highly undesirable. Bare metal applications abound in this (vast) world.

    One of my projects was for a very precise 2 axis tilt sensor and the sensor was analog (MEMS devices drift a lot and quite quickly). The drive circuit was reasonably simple but to get the stability of readings some post processing of the data following the ADC conversions was necessary (think 64 tap or more FIR filtering).

    The issue here is that the time between each conversion starting must be as close to identical as possible and interrupts is the way to do it; the kicker is that nothing must get in the way of those interrupts to introduce timing jitter on the conversions (even a small amount of jitter can royally screw up the filtering because the mathematics depends on the time between samples to be identical).

    Add to that the issue of designing timing windows (sampling, processing, re-initialising data structures, reading the ADC data and hardware functions such as DMA to name a few) and it becomes clear that cycle accurate timing is required (for the sampling at least).

    The best code in this situation is small and tight apart from the startup initialisation (where it doesn't really matter). No assembly was required (an accurate oscilloscope is your friend for this stuff). That means no layering of the code (or at least extremely little but none is best). Goodbye several deep layers for function calls.

    In that particular case, everything was done based on hardware timers and interrupts that were provably not interfering with each other and results communicated upstream to an application processor (from a DMA buffer).

    It might surprise El Reg just how many of those types of system exist.

    1. Caver_Dave Silver badge
      Angel

      Re: Small...

      I did the noise and echo cancellation filters for the Nokia 2110.

      Each had to run in an exact number of clock cycles, regardless of the input data.

      All in assembler, I optimised it to the point that there was just one nop between the two filters.

  15. DJO Silver badge

    Contracts cannot override legal rights

    DISCLAIMER OF WARRANTY. The software is licensed "as-is." You bear the risk of using it. Microsoft gives no express warranties, guarantees or conditions.

    That might fly in the USA but in Europe a product has to be "fit for purpose" and no amount of weasel words in a EULA or anywhere can override that.

    1. Neil Barnes Silver badge

      Re: Contracts cannot override legal rights

      And they mis-spelt 'sold'...

    2. jake Silver badge

      Re: Contracts cannot override legal rights

      "That might fly in the USA but in Europe a product has to be "fit for purpose" and no amount of weasel words in a EULA or anywhere can override that."

      You can tell yourself that until you are blue in the face, and yet I'll bet you are still stuck with Redmond products at work.

  16. ecofeco Silver badge
    Holmes

    Custom code has not died

    There are thousands of people still writing custom code for all manner of reasons and making a living at it and will continue to do so until AI code becomes bulletproof. Which is going to be a long time.

    "Coding" (dammit, it's still programming!) isn't like using the game creator Scratch and just plugging in modules.

    1. Liam Proven (Written by Reg staff) Silver badge

      Re: Custom code has not died

      [Author here]

      > There are thousands of people still writing custom code for all manner of reasons and making a living at it and will continue to do so until AI code becomes bulletproof.

      Which is the main thrust of my point.

      Perhaps the rise of vast, mostly-automated codebases is inexorable, but there still is hand-crafted stuff, and it might see a renaissance, spreading back into more visible, general-purpose arenas.

  17. nsimic

    Fundamental problem

    the chain of conclusions in the article has one weak link

    > A human will define an API and some input and output formats, and specify some tests that it works

    this has been tried and failed many times before, just look at BDD, CASE tools, 4GLs just to name a few.

POST COMMENT House rules

Not a member of The Register? Create a new account here.

  • Enter your comment

  • Add an icon

Anonymous cowards cannot choose their icon

Other stories you might like