It's hard to say from a single quote from a single person. I dare say most developers confuse difficult with complex.[0] His coding style may have been brutally simple, even if that meant very hard. He also could have been a bad programmer.

I often take a look at a problem from multiple perspectives in order to try and find ways of minimizing the number of special cases or minimizing the number of states in the (perhaps implicit) finite state machine. This is often harder than just gut-feeling my way through the most intuitive ad-hoc coding solution.

For instance, if something has an optional timeout, I strongly prefer to write it as a non-optional timeout that defaults to something absurdly large (but not so large as to uncover multi-billion-year overflow bugs in libraries I'm using), usually 100 years. Maybe that's the hard way of doing it, but it gets rid of special handling of the optionality. I'm sure some colleagues would describe this as "the hardest way" to write an optional timeout, but it objectively has fewer code paths to reason about and test. Some people really hate seeing code that doesn't treat the no-timeout case as a special case, because they just find it uncomfortable to switch perspectives. They really want to code it up as they most naturally think about it, not in the way that yields the least twisted code.

In another case, one of my colleagues wrote some minor error recovery logic for a distributed system. I politely told him that his solution had too many implicit states and would get stuck if messages were delayed between systems. I proposed a simple 4-state machine: ok, trying_to_resovle, resolved, and taking_too_long_to_resolve. But, he was the one originally assigned the task, I didn't have any real authority, and it wasn't worth a fight. He said the way he wrote it was "easier" and "more natural." A few months down the road, his solution got stuck and never alerted us that it was taking too long to resolve the error, because messages got delayed between systems. In an afternoon, I whipped up my original proposal: since the recovery action is idempotent, when you go into the recovering state, just blindly fire off the recovery action every x seconds until you either get confirmation of resolution, or after y seconds give up and alert the humans that the problem might not be resolved. As far as I know, my 4-state FSM solution is still in production years later. I'm sure the author of the original felt a 4-state finite state machine was "the hardest way to write it."

In a third case, we have a pretty slick internal publish-subscribe system, but the error handling is just level-based: the subscriber provides a callback taking a boolean that indicates if the publisher has just gone from "bad" to "okay" (true) or "okay" to "bad" (false). Publishers have an upper time limit of inactivity after which they'll publish out a size zero message, so if a subscriber doesn't get any messages in that maximum idle period plus some configurable leeway, then the subscriber needs to assume the publisher has died and go into error mitigation/recovery/alerting logic. It's a pretty simple two-state FSM. The start state is the "bad" state. Every message results in the current time being recorded as the latest timestamp, and if the current state is "bad", transition to the "ok" state and pass true to the health status callback. If there's not an existing timer, create one for transitioning back to a "bad" state. When the timer goes off, check the latest recorded timestamp, and see if you really should transition to a "bad" state and call the health status callback with false. Otherwise, calculate the next timeout based on the latest heartbeat and reset the timer. The problem is that it starts out in the "bad" state, so in order to handle the case of publishers being dead at subscription time, all subscribers need to implement their own timer logic, and a lot of subscribers either don't try to handle the case or handle it incorrectly. I spent a while trying to convince the main developer for the pub-sub system to switch to a tristate FSM: start, bad, and ok. If you use 100 years for the default time to transition from the start state to the bad state, you'll get backward-compatible behavior for subscribers that just assume their first health status callback must be their initial notification that the publisher is live. The other state transitions were all really easy to work out. I sent him an email with a pretty state transition table showing all 4 possible state transiions, what triggered them, and which transitions triggered which health status callbacks. It's really dead simple: 3 states, 4 transitions, and it greatly simplified code on the subscriber side and stopped forcing all subscribers to implement their own poor solutions, and it was 100% backward compatible if default parameters were used. He kept on pushing for various ad-hoc solutions with more implicit states and state transitions because his gut feeling solution was easier for him than thinking in terms of a 3-state finite state machine. We went through a couple back-and-forths with me pointing out flaws in his ad-hoc proposals, and him not pointing out any flaws in my FSM, but just complaining that it was "complex". But, he didn't really mean "complex", he meant "hard"[0] because he wasn't accustomed to thinking in terms of state machines. With the extra corner cases and implicit states in his ad-hoc proposals, his solutions were more complex by an objective complexity metric. But, I'm sure he'd complain that my 3-state, 4-transition state machine was writing it "the hardest way."

I also strongly prefer to put throttles with very high limits in cases where we don't think throttles will ever be necessary. When the network admins are yelling at you that you're killing the network is no time to have to code up a throttle instead of just changing a configuration. I've had people argue that putting in throttling logic is too complicated. When some middlewear daemon got absurdly slow, I've also had to tell those same people "The middlewear admins are screaming. If the middlewear daemon's memory usage hits 3.75 GB, we need to kill your programs to keep the middlewear from falling over." Sometimes a colleague complaining about complexity is really trying to simplify things to a dangerous degree.

[0] https://www.infoq.com/presentations/Simple-Made-Easy/