[HN Gopher] What I have changed my mind about in software develo...
       ___________________________________________________________________
        
       What I have changed my mind about in software development
        
       Author : henrik_w
       Score  : 52 points
       Date   : 2023-09-10 16:12 UTC (6 hours ago)
        
 (HTM) web link (henrikwarne.com)
 (TXT) w3m dump (henrikwarne.com)
        
       | jcpst wrote:
       | It would be interesting to know how long the author has been
       | developing software.
       | 
       | For me, this is the kind of stuff I questioned in my first few
       | years. After I productionalized a few real world systems for a
       | business, the whole "dev street cred" thing lost it's appeal. It
       | wasn't about some imaginary "dev purity" thing anymore, it was
       | about being efficient and making sure I was contributing to the
       | bottom line.
        
         | SoftTalker wrote:
         | Maybe. I have been developing for over 30 years. I still use
         | emacs, use logs and printf for debugging, and have never even
         | looked at ChatGPT. I'm willing to admit I may be set in my ways
         | but I get my work done.
        
           | jiggawatts wrote:
           | Nearly 40 years here -- I exclusively use IDEs and debuggers
           | and have done so since the early 1990s.
           | 
           | Computers aren't digital pencil and paper. They're levers for
           | the mind. If the 3 GHz processor just sits there idling,
           | waiting patiently to copy some bytes from one buffer to
           | another, it's being wasted. It could be checking the syntax,
           | looking up documentation, or chasing memory references in the
           | debugger _so I don't have to._
        
           | bsder wrote:
           | Programmers had a very nice thing called "web search". Then
           | advertising and spam ruined it.
           | 
           | From my point of view, ChatGPT is simply an anti-spam
           | algorithm which is finally restoring "web search" back to
           | being useful.
           | 
           | The problem is that _there is no money in that_. So,
           | everybody is trying to apply all the ML /LLM/ChatGPT stuff to
           | absolutely _anything_ in the hopes of making some money.
        
           | jcpst wrote:
           | Good point. They're all just tools and patterns. The actual
           | tools used _could_ save some time, but experience plus the
           | capacity to reason about software is a bigger deal.
           | 
           | The article just made me think of some devs that I've worked
           | with that were obsessed with particular tooling (insert
           | comment about a hammer and everything being a nail).
           | 
           | I do keep an eye on emacs. It turned into mainly my org-mode
           | editor, but the v29 article that hit the HN front page
           | recently has me curious about trying more dev work with it.
        
         | mellosouls wrote:
         | _It would be interesting to know how long the author has been
         | developing software_
         | 
         | It's on the About page:
         | 
         | "I have been programming professionally for more than 30 years"
        
       | 0x445442 wrote:
       | Unit testing private methods via public interfaces is accidental
       | testing and leads to overly complex and brittle test code. The
       | author's first instincts were correct here.
        
         | isityouyesitsme wrote:
         | Exactly.
         | 
         | I worked in a place that disallowed friend functions and
         | classes generally, but explicitly for unit testing. I never
         | wrote another private function. Instead, there was an explosion
         | at the tiny-free-function-that-could-have-been-a-private-
         | function factory, and the parts ended up everywhere.
        
         | SoftTalker wrote:
         | How is it accidental? The code can only do what its public
         | interfaces expose. This indirectly (not accidentally) exercises
         | the private methods.
         | 
         | If all the public interface test cases pass, isn't that enough?
        
           | isityouyesitsme wrote:
           | Whether or not it is enough depends on the context. Some
           | cases require 100% condition and decision coverage. In these
           | cases, it gets to be very difficult to achieve that unless
           | you are directly testing the functions you write, not through
           | a caller.
           | 
           | But even deeper, it is "accidental" because you are not
           | testing contracts on the public APIs, you're testing the
           | private functions through a layer higher. When the
           | implementation changes, you have coupled your tests so
           | tightly to the implementation that they are useless for
           | regression testing. If not, then you actually aren't testing
           | the private function at all, you're just hitting some parts
           | by coincidence.
        
           | mvdtnz wrote:
           | I don't necessarily agree, I think it's situational but I
           | think that the dev community as a group has swung too far to
           | the "only test public interfaces" side lately. It ignores
           | some important realities in favour of ideological purity.
           | 
           | Sometimes there are well-defined processes for performing a
           | task, and that task is performed in only one place in the
           | system. Therefore the details of the process can be kept
           | class private inside of the only consumer. That doesn't mean
           | that the processes should never be tested. If the task is
           | cumbersome to set up or runs slowly then there is good reason
           | to test the internal parts of the process which can be tested
           | with dozens, hundreds or even thousands of permutations of
           | input data cheaply and efficiently. Always relying on the
           | large-scale tests to hit every combination of inputs for a
           | well understood subroutine can be inefficient.
           | 
           | You could make the argument that this well-understood process
           | could be broken out into its own class/package/module and
           | tested with its own public interface, but if there really is
           | only one consumer then that's kind of a strange trade-off to
           | make in many cases.
        
             | 0x445442 wrote:
             | In the vast majority of cases, The Enterprise, private
             | methods are little to no use anyway. Whenever I'm faced
             | with updating a code base that has Draconian code coverage
             | metrics in place I'm more apt to make a private method
             | public than futz around trying to figure out mock magic to
             | test the change
        
             | Joky wrote:
             | > You could make the argument that this well-understood
             | process could be broken out into its own
             | class/package/module and tested with its own public
             | interface, but if there really is only one consumer then
             | that's kind of a strange trade-off to make in many cases.
             | 
             | That's how I develop in general: a "component" does not
             | exist because it has multiple-clients, but because it is a
             | conceptual piece of logic that makes sense to document and
             | test in isolation. It allows to define what is the public
             | API of this component and what isn't. This is how software
             | scales and stays maintainable over time IMO.
        
               | mvdtnz wrote:
               | I don't disagree, I'm just saying it's situational. The
               | trade-off doesn't always make sense. But I typically
               | develop in much the same way as you do.
        
           | 0x445442 wrote:
           | There are a number of issues. First, the fundamental unit
           | under test is the method/function, not the entire call stack.
           | Second, complexity starts to grow when there are code
           | coverage gates in place.
           | 
           | When I see tests that are orders of magnitude larger than the
           | units they're testing and contain mocked references that are
           | used 7 stack frames deep I know the author had a fundamental
           | misunderstanding of how to write helpful and maintainable
           | tests.
        
         | jcpst wrote:
         | This perspective is really interesting to me. I'd be interested
         | in knowing what people find problematic with it.
         | 
         | I used to unit test all the components individually. But these
         | days I test with most of the componentry wired up, only mocking
         | the i/o layers. I end up writing fewer tests, they have been
         | less brittle, and refactoring is easier.
        
           | 0x445442 wrote:
           | If you want to expose issues in a code base's architecture,
           | don't allow mocking frameworks and see how complex and
           | lengthy unit tests become.
        
             | pc86 wrote:
             | Yes if you eliminate an entire class of testing
             | infrastructure, tests become harder to write because you
             | end up poorly implementing that infrastructure in every
             | class.
             | 
             | How does this show you "issues in the code base's
             | architecture?"
        
         | waynesonfire wrote:
         | if your private methods are complicated enough that you're not
         | able to achieve sufficient coverage through public interfaces
         | it's time to refactor. make the private code a library that you
         | can test in isolation.
        
         | IshKebab wrote:
         | I agree. It's also _not_ always possible to sufficiently
         | stimulate a private function using public methods.
         | 
         | He was right to change his mind about the other things.
         | 
         | I was also skeptical about remote working, and while I think it
         | is worse in most ways than office working, it's not _a lot_
         | worse, and the lack of commute is sooo big a benefit that
         | overall it 's totally viable.
        
       | 29athrowaway wrote:
       | With IntelliJ, spellchecker + linter + static analysis +
       | duplicate code detection + etc = basic quality as opt out feature
       | 
       | VS Code and other setups make those opt in.
       | 
       | Meaning, when you see a bunch of typos and really poorly written
       | code you know it is from one of the DIY setup people.
       | 
       | So then you have to move all those checks to the next stages like
       | SCM hooks and CI.
        
       | mplewis wrote:
       | I wish that my programming languages had a "public for testing
       | only" scope. Despite the rigorous arguments of the Properly
       | Factor Your Public API crew, I still find myself in real-world
       | situations with functions that should not reasonably be used
       | outside of the module, but that I still find valuable to cover
       | with unit tests.
        
         | wavemode wrote:
         | C++ has "friend" classes, a quirky feature I've never seen in
         | another language. But which solves this very problem.
        
         | MikeTheRocker wrote:
         | Kotlin has the internal access modifier which can be useful for
         | this
        
         | mvdtnz wrote:
         | This exists (in kind of a hacky way) in C# with the
         | ExternalsVisibleTo attribute. It exposes methods and classes
         | only to specified assemblies (like your unit test assemblies).
         | 
         | https://learn.microsoft.com/en-us/dotnet/api/system.runtime....
        
           | no_butterscotch wrote:
           | This exists in many Java based languages, an annotation above
           | a method: @VisibleForTesting or some such.
        
           | gregoryl wrote:
           | You can actually stick this in your csproj. I'm on a phone,
           | so bear with me, but roughly
           | <InternalsVisibleTo Include="assemblyname" />
           | 
           | Which means you can do stuff with msbuild props, like auto
           | including a `$(assemblyname).Tests` into your projects.
        
         | zem wrote:
         | yeah, that one stood out to me too. i would be tempted to make
         | the stronger statement that it is always strictly better to
         | have your private code unit tested, and it is only the
         | limitations of languages and test frameworks that make people
         | reach for ways to test them through the public API.
        
           | pvorb wrote:
           | But on the other hand: if it's worthwhile testing your
           | private methods, shouldn't they maybe be refactored to a
           | public/package-private scope, so they can be reused?
           | 
           | If you disagree, maybe an illustrative example would help. I
           | couldn't think of one where I want to test a private method
           | in detail that is not worth exposing.
        
       | deergomoo wrote:
       | I've never understood why anyone would choose to debug by
       | printing and logging if they have a good debugger available to
       | them.
       | 
       | My day job is mostly PHP (yeah yeah, I know) and the general
       | attitude towards Xdebug in the community seems to lie somewhere
       | between apathy and active avoidance.
       | 
       | To me, a debugger is such an invaluable tool not only for
       | identification of bugs but also for familiarising oneself with
       | new code. The value of being able to not only trace execution
       | from start to finish but also to _modify_ state in a running
       | program is immense, and gives me a small taste of what Lisp folks
       | rave about.
       | 
       | Littering print statements everywhere feels like banging rocks
       | together when there's a perfectly good lighter in your pocket.
        
       | pc86 wrote:
       | Overall a pretty good article, however I do feel like the author
       | misses the mark on a couple points.
       | 
       | > Unit testing private methods.
       | 
       | As someone else pointed out this leads to accidental testing. I'm
       | not a test zealot, I think 100% coverage is a fool's errand, and
       | I think TDD is an abomination, but well-structured, well-thought-
       | out tests can be a game changer when used appropriately. Testing
       | things by accident has inevitably lead me to finishing some piece
       | of work then spending half a day or more tracking down why some
       | test failed inexplicably.
       | 
       | > Using an IDE.
       | 
       | I think a better point here is to get really good with whatever
       | tool you use. If you know every incantation in vim you're going
       | to be amazingly productive. If you know every keyboard shortcut
       | in IntelliJ you'll be as effective, but probably not much more.
       | The person who knows vim or emacs in and out will beat the person
       | clicking around in an IDE every day of the week.
       | 
       | That being said some of it is spot on in my admittedly limited
       | experience (only about 13 years or so, in a handful of
       | industries, never FAANG-level scale). The point about commenting
       | problem areas in the _domain_ has really changed my approach to
       | comments. I don 't write any comments about what the code is
       | doing unless it's a "here be dragons, don't change $X unless
       | you're free the rest of the week" kind of warnings. But I comment
       | extensively why the business or regulation requires A or B to
       | happen instead of the more straightforward C.
       | 
       | The ChatGPT bit as well matches my experience. For well-defined
       | things where it's hard for ChatGPT to make the answer up, and
       | easy for you to verify if it does (or at least low-damage), it's
       | worth the $20/mo IMO. I tried using it to learn CDK and while I'm
       | not sure it saved me any time, it did save me from having to
       | trawl through AWS documentation.
        
       ___________________________________________________________________
       (page generated 2023-09-10 23:00 UTC)