• swordsmanluke@programming.dev
    link
    fedilink
    arrow-up
    62
    arrow-down
    2
    ·
    5 months ago

    Have you ever been in an old house? Not old, like, on the Historic Register, well-preserved, rich bastard “old house”. Just a house that has been around awhile. A place that has seen a lot of living.

    You’ll find light switches that don’t connect to anything; artwork hiding holes in the walls; sometimes walls have been added or removed and the floors no longer match.

    Any construction that gets used, must change as needs change. Be it a house or a city or a program, these evolutions of need inevitably introduce complexity and flaws that are large enough to annoy, but small enough to ignore. Over time those issues accumulate until they reach a crisis point. Houses get remodeled or torn down, cities build or remove highways, and programs get refactored or replaced.

    You can and should design for change, within reason, because all successful programs will need to change in ways you cannot predict. But the fact that a system eventually becomes complex and flawed is not due to engineering failures - it is inherent in the nature of changing systems.

    • EatATaco@lemm.ee
      link
      fedilink
      English
      arrow-up
      21
      ·
      5 months ago

      My 100 year old house has marks on the floor that look like it was worn from a door swinging. Very distinctive arc pattern. Like it was there for many years and was under frequent use.

      The problem is that there’s no door there, just a wall, which is also the edge of a dormer…so if there were a door there it would just open out onto a sloping roof.

      Every time I register it I contemplate why it’s there and wtf happened.

      • brandon@lemmy.world
        link
        fedilink
        English
        arrow-up
        16
        ·
        edit-2
        5 months ago

        There was most likely a closet or other crawl space storage area there. My house has closets like that but luckily full height entries to them so we can actually step in. I’ve seen other houses with 1/2 or 1/3 height doors leading to under-roof crawl spaces for storage.

    • bort@sopuli.xyz
      link
      fedilink
      arrow-up
      9
      ·
      edit-2
      5 months ago

      the fact that a system eventually becomes complex and flawed is not due to engineering failures - it is inherent in the nature of changing systems

      it is not. It’s just that there will be some point, where you need significant effort to keep the systems structure up to the new demands {1}. I find the debt-metaphor is quite apt [2]: In your scenario the debt accumulates until it’s easier to start fresh. But you can also manage your debt and keep going indefinitily. But in contrast to financial debt, paying of technical debt is much less obvious. First of all it is pretty much impossible to put any kind of exact number on it. On the other hand, it’s very hard to tell what you actually should do to pay it off. (tangent: This is why experienced engineers are worth so much: (among other things) they have seen how debt evolves over time, and may see the early signs).

      [1] https://tidyfirst.substack.com/p/the-openclosedopen-principle

      [2] https://blog.pragmaticengineer.com/tech-debt/

    • rollerbang@sopuli.xyz
      link
      fedilink
      arrow-up
      4
      arrow-down
      1
      ·
      5 months ago

      You can and should design for change, within reason, because all successful programs will need to change in ways you cannot predict

      You’ve yourself here. You can not predict how it wull change. Which means that whichever design for change you’ve made, may just as well completely miss the future utilization

      Which doesn’t mean that we shouldn’t design for change at all… Just saying.

      • swordsmanluke@programming.dev
        link
        fedilink
        arrow-up
        5
        ·
        5 months ago

        Just saying.

        … Saying what, exactly?

        I said that we should

        • design for change
        • “within reason”
        • because we can’t know what exact changes are needed.

        And you argued… The same thing? Just in the reverse order?

        • Serinus@lemmy.world
          link
          fedilink
          arrow-up
          1
          ·
          5 months ago

          Seems like he’s worried you’ll Java everything up, which can be valid.

          I think a good, easy example is whether your application should allow a selection of databases or be tied to one database.

          You can make arguments for either, often (but not always) regardless of your use case.

      • sebsch@discuss.tchncs.de
        link
        fedilink
        arrow-up
        4
        ·
        5 months ago

        As long as loose coupling, and separation of concerns are well tinkered into your application you minimise risks of breaking everything on a restructuring.

        If you have for example shared state leaking everywhere into the program, your most probably doomed on the slitest changes.

        I am not saying you’re wrong, but there are ways to mitigate the risks even without knowing what will happen in the future.

  • wise_pancake@lemmy.ca
    link
    fedilink
    arrow-up
    54
    ·
    5 months ago

    This is so true.

    Even if you do design clean modular code and document it, you’re getting a question a year from now about how it works, or someone just duct tapes on top of it.

    • BakedCatboy@lemmy.ml
      link
      fedilink
      English
      arrow-up
      35
      ·
      5 months ago

      I’ve even experienced this in the 3D printing community, where I design a highly parametric model and put lots of effort into making all of the major dimensions and qualities parameterized and dynamically adjustable, with lots of bounds checking and value clamping, with all the parameters at the top of my scad file with comments explaining what each variable does.

      And then someone comes along to remix my model, says I don’t want to install openscad, and just scales the entire output stl to change the dimensions, squashing all the features of the model in the process (instead of having the size gracefully adjust with all the features moving around to account), and leaving anybody starting from their work with a hard to remix mesh with no parameters.

    • FMT99@lemmy.world
      link
      fedilink
      arrow-up
      18
      ·
      edit-2
      5 months ago

      Or business decides all specs and design decisions that were made last quarter were actually garbage and yes we do want to be able to manually override every step of the carefully designed state machine. We’d like to be able to manually change all calculated sales data, but also the data needs to remain in a consistent state at all times. Oh and while you’re there, we decided the commission calculations will use a different system from now on. We expect it to be online by the end of the week, thanks.

      • FizzyOrange@programming.dev
        link
        fedilink
        arrow-up
        2
        ·
        5 months ago

        This can work for junior devs who aren’t stuck in their ways. Unfortunately there are too many “senior” devs who are happy making crap. It’s hard to fight them constantly to do things properly (e.g. write actual commit messages rather than just “Fix #836”) so using tools like linters where possible is definitely a big improvement.

    • _NoName_@lemmy.ml
      link
      fedilink
      arrow-up
      8
      arrow-down
      1
      ·
      edit-2
      5 months ago

      The ‘document’ part also seems to be insanely hit-or-miss from my amateur experience. Self-documenting design/code is… well, not. Auto-generated documentation is also usually just as bad IMO. Producing good documentation really is a skill in and of itself.

      Also small personal opinion: If your abstraction layers or algorithms are based off a technical concept, you should probably attribute that concept and provide links to further research, to eliminate future ambiguity or in case your reader lacks that background. Future you will probably thank you and anyone like me who immediately gets lost in jargon soup will also be thankful.

  • armchair_progamer@programming.dev
    link
    fedilink
    arrow-up
    43
    arrow-down
    2
    ·
    edit-2
    5 months ago
    public class AbstractBeanVisitorStrategyFactoryBuilderIteratorAdapterProviderObserverGeneratorDecorator {
        // boilerplate goes here
    }
    
    • bort@sopuli.xyz
      link
      fedilink
      arrow-up
      10
      ·
      5 months ago

      ============ Top 5: =============== HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor: 97
      AbstractAnnotationConfigDispatcherServletInitializer: 52
      AbstractInterruptibleBatchPreparedStatementSetter: 49
      AbstractInterceptorDrivenBeanDefinitionDecorator: 48
      GenericInterfaceDrivenDependencyInjectionAspect: 47

      ============ Factories: ===============
      DefaultListableBeanFactory$DependencyObjectFactory
      ObjectFactoryCreatingFactoryBean
      SimpleBeanFactoryAwareAspectInstanceFactory
      SingletonBeanFactoryLocator$BeanFactoryGroup
      ConnectionFactoryUtils$ResourceFactory
      DefaultListableBeanFactory$DependencyProviderFactory
      ObjectFactoryCreatingFactoryBean$TargetBeanObjectFactory
      JndiObjectFactoryBean$JndiObjectProxyFactory
      DefaultListableBeanFactory$SerializedBeanFactoryReference
      AbstractEntityManagerFactoryBean$SerializedEntityManagerFactoryBeanReference
      BeanFactoryAspectInstanceFactory
      SingletonBeanFactoryLocator$CountingBeanFactoryReference
      TransactionAwarePersistenceManagerFactoryProxy$PersistenceManagerFactoryInvocationHandler
      AbstractEntityManagerFactoryBean$ManagedEntityManagerFactoryInvocationHandler

      https://gist.github.com/thom-nic/2c74ed4075569da0f80b

    • Serinus@lemmy.world
      link
      fedilink
      arrow-up
      2
      ·
      5 months ago

      Okay, here we go. I’m going to spit out some bullshit and home someone corrects me if I’m wrong. I’ve looked for some explanations and this is what I’ve gotten.

      Are you ready?

      The Factory Pattern.

      My understanding is that the purpose is a function to return any of several types of objects, but a specific type, not just an interface or whatever they might all inherit from.

      I think most languages now have something like a “dynamic” keyword to solve this issue by allowing determination of the type only at runtime. (To be used with extreme caution.)

      But most of the time I see the Factory pattern, it’s used unnecessarily and can only return one specific type. Why they would use a Factory pattern here and not just a plain old constructor confounds me.

      Am I off base?

      • FizzyOrange@programming.dev
        link
        fedilink
        arrow-up
        1
        ·
        5 months ago

        Yeah most uses of the factory pattern are unnecessary and it’s mild code smell IMO. If your factory only returns one type you should definitely just use that type’s constructor.

  • Skullgrid@lemmy.world
    link
    fedilink
    arrow-up
    30
    ·
    5 months ago

    You avoided writing spaghetti code.

    Congratulations! Now maintain this piece of shit lasagna that takes place over multiple layers of abstraction and repositories.

    • AwkwardLookMonkeyPuppet@lemmy.world
      link
      fedilink
      English
      arrow-up
      19
      ·
      5 months ago

      So many developers don’t seem to understand the point of modularization and add lots of abstraction just for abstraction’s sake. It’s hella frustrating to take over a project like that.

    • lobut@lemmy.ca
      link
      fedilink
      arrow-up
      6
      ·
      5 months ago

      Onion architecture. Ports and adapters are other names for it, I think.