This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2024-01-18
Channels
- # announcements (4)
- # babashka (13)
- # beginners (8)
- # chlorine-clover (1)
- # cider (5)
- # clj-http (12)
- # clojure (157)
- # clojure-dev (14)
- # clojure-europe (26)
- # clojure-nl (2)
- # clojure-norway (69)
- # clojure-uk (6)
- # clojuredesign-podcast (21)
- # clojurescript (7)
- # core-async (4)
- # datomic (170)
- # editors (1)
- # hyperfiddle (45)
- # java (7)
- # joyride (1)
- # leiningen (43)
- # lsp (7)
- # malli (24)
- # music (1)
- # off-topic (22)
- # pathom (16)
- # portal (31)
- # re-frame (1)
- # releases (1)
- # shadow-cljs (36)
- # squint (4)
Is there such a thing as too much automation? Is there a point when you should stop trying to handle errors? How can you figure that out? In our latest episode, we discover when giving up is the way to get ahead. https://clojuredesign.club/episode/107-idempotify/
One thing I've learned over time is to reduce the scope of what the software actually encodes and balance that with "standard operating procedures" that users understand. This can sound like a bit of a cop out, but I think it really does lead to better software. Often, we're building for people who already have a workflow and already know how to do their jobs: the software we build are tools to increase a user's effectiveness by letting the computer do what it's good at and removing that burden from the user, allowing them to focus on what they're good at. Concretely: I work on a system that allows meteorologists to depict high impact weather and generate products for consumption by the public (or for certain products, pilots). The goal then is to let the meteorologist focus on the weather and the messaging instead of fiddling with message format or image layout. So where does the SOP argument come in? Often, we'd get requirements where they say "the software should disallow us from doing X." You ask why, and it's because they (meteorologists) don't do that. Okay. You never ever do that? Or you tend not to do that? Those are very different: is it a fundamental violation of business rules and international standards if you can do that thing with the software? You'd be surprised (or maybe not surprised) at how often it ends up that the right thing to do is either nothing at all, or just a little warning indicator that something the user entered is odd. Imagine listening to the requirements saying "the software should disallow" and then discovering they couldn't issue a really bizarre tornado warning because the software wouldn't let them 😕
To connect to the question directly, I've tried to shrink the pit as much as possible by removing entire categories of problems from the software when possible. Another example that may be interesting:
Our server for collaborative editing of weather events (think Google docs for weather) is backed by an external data management system that's the source of truth for the organization; if that connection is lost, our server can't do much. Originally, we dealt with a connection loss by retrying and the suspending client communication until state was correctly resynchronized. There were so many corner cases to have to deal with, and a large chunk of the logic was basically the same as the startup logic. So, we took a page from Erlang and simplified: when the connection is lost, we shut down. Separately, we had started our process with run-one-until-success
, so it would automatically be restarted when it shutdown due to error. Now we've got one flow: starting the server, connecting to the data management system, and syncing system state.
One of the hardest muscles to build is figuring out when to say "this isn't the problem my software needs to solve." Even with examples of having done it, I mess it up so often. It really does benefit a lot from the "second system" experience
@U5FV4MJHG @U0510902N do you find that fiddle files help you get this right more often? Like, by "feeling" your way to a solution, you're more likely to constrain the problems that your software needs to solve? In a sense, I suppose this is basically just the whole idea of reducing/removing sources of incidental complexity (i.e. the complex parts that have nothing to do with the business)
this is gold: "this isn't the problem my software needs to solve" Everything you said resonates with my view. As software creators, we are not isolated implementation machines. Instead, we are part of a living organism that's trying to accomplish a goal. That's why I don't think it's a cop out to rely on SOPs or simpler solutions that mimic actual workflows. It's building the right thing, and it often ends up being less code. And that's a huge benefit. Less code means fewer bugs.
I don't know if fiddling moves the needle in this case. Yes, you are feeling your way to a solution and so any code is better informed by the real world. But the quick feedback and dopamine hit of frequent success might lead you to try solving more than is necessary.
Ah, yeah that's a fair point. There's no real structure or boundary to the exploration beyond what you impose on yourself, so it's just as easy to say "what if I also..." as it is to say "I've found the core of what I need"
That was Kent Beck's whole thing with TDD: limiting what you write to only what passes the tests. The problem, of course, is constraining the tests to only those that really and truly solve the business problem. I liked your comment in one of the recent podcasts about not taking the human out of the loop because someone needs to fire the silver bullet 😄
No matter the secret sauce, someone needs the discipline to "do the right thing"
I think being more reluctant to build too much is more a function of how many times you've built something grand in the past only to have it go unused.
Ditto 😂
That was why I was curious about the fiddle files and their connection to "second system." I can't think of any green field I've worked on that didn't turn to mud after a while. I think that's just inherent to the job: you can't be entirely reactive (or put another way, you have to be somewhat predictive), and you always have incomplete or inaccurate knowledge.
> you always have incomplete or inaccurate knowledge Yes x 100. This is one reason why fiddling is so effective. It helps you learn about your dependent systems and the problem you're solving. Unfortunately, it doesn't help you with the non-technical incomplete knowledge. That's only reduced by interacting with humans (customers, coworkers, project managers, etc).
The dopamine hit is a good point to be cautious about. Every technique and tool seems to have some way to shoot yourself in the foot, and knowing it up front can help avoid it
> That's only reduced by interacting with humans (customers, coworkers, project managers, etc). > You mean software development is a social activity!? 😱
A significant aside from the current topic, but the shift to remote does make me wonder how good those interactions will be, at least in the short term. Sitting next to someone feels way better than slack, for example.
Absolutely! I mostly enjoy remote work (been so for about 6 years), but there's nothing like walking over to someone and hashing out requirements or a bug.
@U04RG9F8UJZ I'm enjoying this discussion. I'm glad you replied! I agree with what you're saying. One way I view it is that software is inherently a constraining activity. We take all the possibilities and reduce them down to a finite few. Do I have enough real-world information to know that I'm not cutting out useful (even if unusual) behavior? Keeping software extremely narrow helps me avoid over constraining without adding complexity (lots of cases). One beauty of a REPL-connected editor is that every expression is an entry point. You can automate little parts, keep them simple, and even skip steps (aka call the "human function"). Very little is constrained. You can focus your effort on things that make a difference or need more clarity. You have something to show for it right away too! With little commitment, you have a high reward, and something simple to work with. It's the ultimate form of saying "no" over and over until you know why to say "yes" and commit.
To connect to the question directly, I've tried to shrink the pit as much as possible by removing entire categories of problems from the software when possible. Another example that may be interesting:
Our server for collaborative editing of weather events (think Google docs for weather) is backed by an external data management system that's the source of truth for the organization; if that connection is lost, our server can't do much. Originally, we dealt with a connection loss by retrying and the suspending client communication until state was correctly resynchronized. There were so many corner cases to have to deal with, and a large chunk of the logic was basically the same as the startup logic. So, we took a page from Erlang and simplified: when the connection is lost, we shut down. Separately, we had started our process with run-one-until-success
, so it would automatically be restarted when it shutdown due to error. Now we've got one flow: starting the server, connecting to the data management system, and syncing system state.