• ☆ Yσɠƚԋσʂ ☆@lemmygrad.mlOP
    link
    fedilink
    English
    arrow-up
    8
    ·
    9 days ago

    It uses hooks and functional components which are the way most people are doing it from what I know. I also find the code DeepSeek and Qwen produce is generally pretty clear and to the point. At the end of the day what really matters is that you have clean code that you’re going to be able to maintain.

    I also find that you can treat components as black boxes. As long as it’s behaving the way that’s intended it doesn’t really matter how it’s implemented internally. And now with LLMs it matters even less because the cost of creating a new component from scratch is pretty low.

    • Chana [none/use name]@hexbear.net
      link
      fedilink
      English
      arrow-up
      4
      ·
      9 days ago

      Does it memoize with the right selection of stateful variables by default? I can’t imagine it does without a very specific prompt or unless it is very simple boilerplate TODO app stuff. How about nested state using contexts? I’m sure it can do this but will it know how best to do so and use it by default?

      In my experience, LLMs produce a less repeatable and correct version of what codegen tools do, more or less. You get a lot of repetition and inappropriate abstractions.

      Also just for context, hooks and functional components are about 6-7 years old.

      • ☆ Yσɠƚԋσʂ ☆@lemmygrad.mlOP
        link
        fedilink
        English
        arrow-up
        3
        ·
        9 days ago

        I tend to use it to generate general boilerplate. Like say I have to talk to some endpoint and I get a JSON payload back. It can figure out how to call the endpoint, look at the payload, and then generate a component that will render the data in a sensible way. From there, I can pick it up and add whatever specific features I need. I generally find letting these things do design isn’t terribly productive, so you are better off deciding on how to manage state, what to memoize, etc. on your own.

        I also find the quality of the tools is improving very quickly. If you haven’t used them in half a year or so, your experience is already dated. You get by far the biggest bang for your buck with editor integrated tools that can run MCP, where they can run code and look at output.

        Finally, I personally don’t see anything wrong with hooks/functional components even if there’s already a new fad in Js land. The churn is absolutely insane to me, and I frankly don’t understand how people keep up with this. You can start a project in Js, and by the time you finish it the Js world has already moved on to some new bullshit.

        I used to work with ClojureScript when I needed frontend functionality before. There’s a React wrapper called Reagent. It’s basically a better version of hooks/functional components, it worked this way for over a decade. In that time, React itself went through a dozen different ways of doing things. The value gained has been rather unclear to me.

        • Chana [none/use name]@hexbear.net
          link
          fedilink
          English
          arrow-up
          2
          ·
          9 days ago

          Yes I’m sure it can do a lot of boilerplate. I’m just saying I doubt it is very idiomatic. It is essentially a souped-up regurgitation machine drawing from a collection of a bunch of open source code over a long period of time and quality as well as documentation.

          This can be fine for many purposes but if it is for a substantial project that other people will need to maintain I would suspect it is a technical debt generator. As the saying goes, code is read more than it is written. Writing the code is usually the easy part. Producing a maintainable design and structure is the hard part. That and naming things.

          • ☆ Yσɠƚԋσʂ ☆@lemmygrad.mlOP
            link
            fedilink
            English
            arrow-up
            1
            ·
            8 days ago

            I mean all code is technical debt in the end, and given how quickly things move in Js land, it doesn’t matter whether you’re using LLMs or writing code by hand. By the time you finish your substantial project, it’s pretty much guaranteed that it’s legacy code. In fact, you’ll be lucky if the libraries you used are still maintained. So, I don’t really see this as a serious argument against using LLMs.

            Meanwhile, as you note, what makes code maintainable isn’t chasing latest fads. There’s nothing that makes code written using hooks and functional components inherently less maintainable than whatever latest React trend happens to be.

            And as I pointed out earlier, LLMs change the dynamic here somewhat because they significantly lower the time needed to produce certain types of codes. As such, you don’t have to be attached to the code since you can simply generate a new version to fit new requirements.

            Where having good design and structure really matters is at the high level of the project. I find the key part is structuring things in a way where you can reason about individual parts in isolation, which means avoiding coupling as much as possible.

            • Chana [none/use name]@hexbear.net
              link
              fedilink
              English
              arrow-up
              1
              ·
              8 days ago

              I mean all code is technical debt in the end, and given how quickly things move in Js land, it doesn’t matter whether you’re using LLMs or writing code by hand.

              I just explained why design and maintainability are the hard part and something LLMs don’t do. LLMs lead to the bad habit of skipping these things, which junior devs do all the time, wasting a lot of resources. Just like a junior dev writing spaghetti can make a middle manager very happy because it’s “delivered on time”, they’ll eventually have to pay in the form of maintenance far more than if better practices had been used.

              Writing boilerplate React components that fetch JSON from APIs is the easy stuff that takes very little time. If you throw in intermediate things (like basic security) you will likely need to spend more time reviewing its slop than just doing it yourself. And it will likely be incapable of finding reasonable domain abstractions.

              If it’s for a throwaway project none of this really matters, of course.

              By the time you finish your substantial project, it’s pretty much guaranteed that it’s legacy code. In fact, you’ll be lucky if the libraries you used are still maintained.

              If it is a production system with any prioritization of security it will need to be regularly maintained, including with library updates. If a library becomes unmaintained then one either needs to use a different one or start maintaining it themselves.

              So, I don’t really see this as a serious argument against using LLMs.

              There are different ways to make code unmaintainable. It seems like you’re saying writing code in JavaScript means you always do a rewrite when it comes time to do maintenance work (it moves fast!). This is just not true and is something easily mitigated by good design practices. And in terms of any org structure, you are much less likely to get a green light on a rewrite than on maintaining the production system that “works”.

              Meanwhile, as you note, what makes code maintainable isn’t chasing latest fads. There’s nothing that makes code written using hooks and functional components inherently less maintainable than whatever latest React trend happens to be.

              I’m not sure what you mean by this. When I said hooks and functional components were 6 years old it was in the context of doubting whether LLMs are up on modern idioms. You said it wrote idiomatic code, citing 6-7 year old idioms. That’s not great evidence because they are long-established over several major version releases and would be a major input to these LLMs. I mentioned a few newer ones and asked whether they were generated for your code.

              React written with hooks and functional components is more maintainable than legacy implementations because it will match the official documentation and is a better semantic match to what devs want to do.

              And as I pointed out earlier, LLMs change the dynamic here somewhat because they significantly lower the time needed to produce certain types of codes. As such, you don’t have to be attached to the code since you can simply generate a new version to fit new requirements.

              I don’t get attached to code…

              LLMs do the easy part and then immediately require you to do the harder parts (review and maintenance) or scrap what they generate for the hardest parts (proper design and abstractions). Being satisfied with this kind of output really just means having no maintenance plans.

              Where having good design and structure really matters is at the high level of the project. I find the key part is structuring things in a way where you can reason about individual parts in isolation, which means avoiding coupling as much as possible.

              It matters at all levels, right down to the nouns and adjectives used to describe variables, objects, database tables, etc. Avoiding coupling will mean knowing when to use something like dependency injection, which I guarantee LLMs will not do reliably, maybe even not at all unless it is the default pattern for an existing framework. Knowing to use dependency injection will depend on things like your knowledge of what will need to be variable going forward and whether it is easier to reason about behavior using that pattern in your specific context. If using domain model classes, are implementing an abstract method or are they passed the implementation and just know how to call it? Etc etc.

              • ☆ Yσɠƚԋσʂ ☆@lemmygrad.mlOP
                link
                fedilink
                English
                arrow-up
                1
                ·
                8 days ago

                I just explained why design and maintainability are the hard part and something LLMs don’t do.

                Ok, but I’ve repeatedly stated in this very thread that design is something the developer should do. Are you even reading what I’m writing here?

                Writing boilerplate React components that fetch JSON from APIs is the easy stuff that takes very little time. If you throw in intermediate things (like basic security) you will likely need to spend more time reviewing its slop than just doing it yourself. And it will likely be incapable of finding reasonable domain abstractions.

                I have to ask whether you actually worked with these tools seriously for any period of time, because I have and what you’re claiming is directly at odds with my experience.

                If it is a production system with any prioritization of security it will need to be regularly maintained, including with library updates. If a library becomes unmaintained then one either needs to use a different one or start maintaining it themselves.

                Not sure what this has to do with code written by LLMs. If I have a React component it has fuck all to do with me updating libraries in the project. Furthermore, LLMs are actually quite decent at doing mechanical tasks like updating code to match API changes in libraries.

                There are different ways to make code unmaintainable. It seems like you’re saying writing code in JavaScript means you always do a rewrite when it comes time to do maintenance work (it moves fast!).

                No, I’m saying the exact opposite which is that you shouldn’t try to chase fads.

                I’m not sure what you mean by this. When I said hooks and functional components were 6 years old it was in the context of doubting whether LLMs are up on modern idioms. You said it wrote idiomatic code, citing 6-7 year old idioms. That’s not great evidence because they are long-established over several major version releases and would be a major input to these LLMs. I mentioned a few newer ones and asked whether they were generated for your code.

                You might have to clarify which particular fad you’re on currently, because I haven’t been keeping up. However, I do see hooks and functional components used commonly today.

                I don’t get attached to code…

                Everybody gets attached to code, it’s inevitable. If you have a bunch of code to solve a particular problem and it takes a lot of effort to rewrite it, then you’re not going to throw it away easily. When your requirements start changing, it makes sense to try to adapt existing code to them rather than write code from scratch.

                It matters at all levels, right down to the nouns and adjectives used to describe variables, objects, database tables, etc.

                It really doesn’t if you have good interfaces between components. You don’t inspect all the code in libraries you include, you focus on the API of the library instead. The same logic applies here. If you structure your project into isolated components with clear boundaries, then your focus is on how the component behaves at the API level.

                Avoiding coupling will mean knowing when to use something like dependency injection, which I guarantee LLMs will not do reliably, maybe even not at all unless it is the default pattern for an existing framework.

                Again, I’m not suggesting using LLMs to do design. My whole point was that you do the design, and you use LLM to fill in the blanks. In this context, you’ve already figured out what the component will be and what scope it has, the LLM can help create features within that scope.

                Knowing to use dependency injection will depend on things like your knowledge of what will need to be variable going forward and whether it is easier to reason about behavior using that pattern in your specific context.

                Also, things like dependency injection are an artifact of OO programming style which I find to be an anti pattern to begin with. With functional style, you naturally pass context as parameters, and you structure your code using pure functions that take some arguments and produce some result. You can snap these functions together like Lego pieces and you can test them individually. This meshes quite well with using LLMs to generate code and evaluate whether it’s doing what you want.

                If using domain model classes, are implementing an abstract method or are they passed the implementation and just know how to call it? Etc etc.

                Have you written code in styles other than OO?

                • Chana [none/use name]@hexbear.net
                  link
                  fedilink
                  English
                  arrow-up
                  1
                  ·
                  8 days ago

                  Ok, but I’ve repeatedly stated in this very thread that design is something the developer should do. Are you even reading what I’m writing here?

                  Yes, and I’m replying in-context:

                  1. I say that code is read more than it is written and that a boilerplate generator is going to be a technical debt machine that had no thought for maintenance.

                  2. You say that all code is technical debt and don’t engage further with that point.

                  3. I reiterate that design and maintainability are what LLMs are bad at and using them for the easy stuff isn’t exactly a boon.

                  I’ll repeat again: LLMs are technical debt machines. There are ways to have more or less debt, it is not all the same regardless, and LLMs will just repeat patterns they’ve seen before, and these may be bad designs, bad patterns, that are difficult to maintain for any project used or maintained by real people. You will then need to, of course, check the result, which is the thing that is less easy and takes longer, so very little has been optimized.

                  Or this is a throwaway project and all of this is moot.

                  I have to ask whether you actually worked with these tools seriously for any period of time, because I have and what you’re claiming is directly at odds with my experience.

                  Which part of what I said is at odds with what you’re saying? I’ve used and rejected these tools as a waste of time and something to help others avoid.

                  Not sure what this has to do with code written by LLMs.

                  It’s a direct response to what I quoted where you dismiss maintainability concerns by saying all substantial projects are legacy code and you’ll be lucky if libraries are maintained. Is… is that not obvious?

                  If I have a React component it has fuck all to do with me updating libraries in the project.

                  I have no idea what this means. React is a library and it also needs to be updated, not to mention the request hook library(ies) your boilerplate would presumably use. If you are maintaining this project and it has any security aspects you’ll need to update these things over time.

                  Furthermore, LLMs are actually quite decent at doing mechanical tasks like updating code to match API changes in libraries.

                  If you’re updating libraries to ensure security I would hope you’re not just trusting the outputs from such edits. You should review them as if an incompetent junior dev submitted a PR. I’m sure it can do a 90% okay job 70% of the time.

                  No, I’m saying the exact opposite which is that you shouldn’t try to chase fads.

                  But we haven’t discussed fads at all?

                  You might have to clarify which particular fad you’re on currently, because I haven’t been keeping up. However, I do see hooks and functional components used commonly today.

                  So basic modern idioms for an extremely popular UI library are just fads now? I’ve already asked about memoization (using currently documented recommendations) and contexts. You are being inconsistent, here: originally it was doing great writing idiomatic code. Once I question its ability to correctly recognize the need for and implement idioms from library improvements in the last 5 years I’m just chasing fads. Seems like it’s not really thay good at idiomatic code, eh?

                  Everybody gets attached to code, it’s inevitable.

                  Nope. I don’t. The exact opposite is more common with more experience: you get the itch to rewrite. Throw the whole thing in the trash and start over. But this is not a practical use of time 9 times out of 10.

                  If you have a bunch of code to solve a particular problem and it takes a lot of effort to rewrite it, then you’re not going to throw it away easily.

                  Oh I definitely am because I can now see how to remove the complexity and make it more versatile.

                  When your requirements start changing, it makes sense to try to adapt existing code to them rather than write code from scratch.

                  Changing requirements is a design process challenge. It indicates prototyping or gross incompetence if it’s happening frequently. Sometimes that incompetence is out of one’s hands, like a client that refuses to communicate effectively, but it is less about the code and more about social skills and planning.

                  If requirements change it can imply modifying an existing codebase ir throwing it all away to start over. It really depends on what the new requirements are. If suddenly there is a need for a very flexible event-driven strategy, you probably need to start over.

                  It really doesn’t if you have good interfaces between components.

                  It actually really does because it enables capturing and therefore correctly addressing domain problems. Junior devs call meaningful variables “x” and “y” because they can’t see this yet, then take forever during a review ir maintenance cycle weeks later because they are tryinh to figure out the meaning and function if meaninglessly named and organized things. In React these would be the same people putting every component module in a module called “components” even for large projects.

                  “Good interfaces” doesn’t address the points I’m raising at all. The best interfaces cannot fix the wrong abstraction being chosen. If your domain needs to represent accounts but you never represent actions taken directly (e.g. “deduct $34.56”) you will end up with a confusing mess.

                  You don’t inspect all the code in libraries you include, you focus on the API of the library instead. The same logic applies here. If you structure your project into isolated components with clear boundaries, then your focus is on how the component behaves at the API level.

                  Until it comes time to maintain your systems and you find that your domain elements are not represented and you don’t understand the variables because you let a markov process write your components.

                  There is another inconsistency here. What you’re repeatedly getting at is that you want to treat the things generated by LLMs and things you can wall off and regenerate, machine-edit, etc as needed. Implicit here is that you don’t need to actually maintain that code, but actually you do if you have any seriousness about the project. Certainty in function. Security. Ever needing to refactor to add new features. And then this will fall apart because you now have to wade through whatever the LLM generated with all the warts I’ve described.

                  Or this is a throwaway project and none of this matters. No real design elements, no security, no user testing, etc. Which is fine, just not a great endorsement for LLMs.

                  Again, I’m not suggesting using LLMs to do design.

                  Using dependency injection is a basic pattern. While it is part of design, it is also part of implementation and it changes how the rest of a codebase may function. React uses it a lot in its implementation. It is in no way separate from the task of having LLMs write components and they will produce wrong results without taking this into account. And this is just one example.

                  Of course, people can make all of these mistakes. But if they are following an intentional design, they will make fewer of them and therefore need less review.

                  My whole point was that you do the design, and you use LLM to fill in the blanks.

                  These things are not separable a la a black box. The problems I have noted remain.

                  In this context, you’ve already figured out what the component will be and what scope it has, the LLM can help create features within that scope.

                  I’m sure it can with 90% efficacy for 70% of simple features. And then you need to rename half of the things. And write a bunch of tests. And do a security audit. Accessibility audit?

                  Anyways the point was that LLMs don’t actually understand these things, just patterns, so they fall on their face for choosing something like dependency injection. There are many things like dependency injection and it won’t recognize when to use them. You say this is left up to design, but it will be interwoven with implementation, even of components - the thing you’re having the LLM do.

                  Also, things like dependency injection are an artifact of OO programming style which I find to be an anti pattern to begin with.

                  This is incorrect. Dependency injection is a ubiquitous pattern. It’s even used in functional programming. And you’d better get stoked about OOP if you are using JS because just about everything is an object. Including the functions you’re calling to generate components. And if you dive into the libraries you’re using they will be chock full of semi-complex classes.

                  With functional style, you naturally pass context as parameters, and you structure your code using pure functions that take some arguments and produce some result.

                  Can you give me an example of when you have passed a function as an argument to a function? Think about what that pattern entails, how the function is used, how and when it is called, and the name of the method (if applicable) doing the calling.

                  You can snap these functions together like Lego pieces and you can test them individually. This meshes quite well with using LLMs to generate code and evaluate whether it’s doing what you want.

                  Modularity and testability is basically just as easy and powerful between OOP and FP. Though I do want to emphasize that you are actually using a lot of classes and objects. Every time you call a method, for example. “await fetchedData.resolve()” etc etc.

                  Have you written code in styles other than OO?

                  lmao

                  • ☆ Yσɠƚԋσʂ ☆@lemmygrad.mlOP
                    link
                    fedilink
                    English
                    arrow-up
                    1
                    ·
                    edit-2
                    8 days ago

                    I feel like we’re just going in circles here. I really don’t have anything new to add over what I’ve already said above.

                    Can you give me an example of when you have passed a function as an argument to a function?

                    Literally any higher order function lmfao.

    • Jorge@lemmygrad.ml
      link
      fedilink
      English
      arrow-up
      2
      ·
      8 days ago

      I hadn’t heard of Qwen. I have only used Deep Seek, and not much. What are Qwen’s advantages over Deep Seek? And is there any other model from BRICS countries I should look for? Preferably open source.

      And do you recommened a local solution? For which use-case? I have a mid-range gamer laptop. IIRC it has 6GiB VRAM (NVIDIA).

      • ☆ Yσɠƚԋσʂ ☆@lemmygrad.mlOP
        link
        fedilink
        English
        arrow-up
        3
        ·
        8 days ago

        I’ve found Qwen is overall similar, their smaller model that you can run locally tends to produce somewhat better output in my experience. Another recent open source model that’s good at coding is GLM https://z.ai/blog/glm-4.5

        6gb vram is unfortunately somewhat low, you can run smaller models but the quality of output is not amazing.