russ

@russ@programming.dev
0 Post – 21 Comments
Joined 1 years ago

every time i'm playing some old guilty pleasure that isn't 'actually good' (think: just wanted to play a jock jam for a moment), i worry about the influence on next week's discover weekly....

Feedback loops are super important! For momentum, for reducing burnout, for implementing/debugging, everything. I think of it mostly as a tooling problem - the point of maintaining and improving your tools is to maintain/improve your feedback loops.

For me it's about this question: How quickly and easily can you verify that the code is doing what you think it's doing?

This is what I love about writing Clojure - you can write and evaluate abritrary bits of code (functions, expressions) without leaving the editor. Invoke a keybinding to send the current expression to the running repl, and the resulting value is returned, and can be interactively explored/walked in the editor. It makes for a fun interactive dev-loop, and is a nice way to design a solution to some problem. (A caveat is that getting into a working repl is non-trivial, as it's dependent on your editor+plugins. It takes a bit of learning and unfortunately isn't beginner-friendly.)

Vim and emacs are also excellent for improving you feedback loops - both take some investment and some discomfort in the beginning, but ultimately you get out what you put in, and soon you can imagine and realize better workflows without much effort (adding your own functions, keybindings, hydras, etc). VSCode and other editors are also hackable, to some extent.

Mostly I think it's important to hack on your tooling on a regular basis, at least once a week or so.

My old boss used to say he expected us to keep 'sharp knives' (as in cooking). I think companies should make time for the devs to work on tooling to improve these feedback loops - it's the hiccups in the workflow that build up and lead to burnout/fatigue. Smooth workflows can actually be energizing instead of energy-draining!

There are a few collections around like: https://github.com/adi1090x/rofi

These things tend to imply dependencies for how they're implemented plus whatever they are integrating. The UX is definitely the right one tho! Rofi is great for working on custom dev tools - you can pass lines in as stdin, it sends back the selected item on stdout, then you exec the matching output command.

I started a project called 'ralphie' to do this with babashka a couple years ago, but later i absorbed that into a monorepo called clawe - you can see the rofi namespace here: https://github.com/russmatney/clawe/blob/3987390ffe538d878045e9d886190542fb111b9e/src/ralphie/rofi.clj#L146-L156

2 more...

This was a cool talk on teaching programming gradually (with a lang called hedy) at last year’s strangeloop: https://youtu.be/fmF7HpU_-9k - might be some useful takeaways for you in there

1 more...

Types and unit tests are bloat that increase the maintenance cost of whatever code they are involved in. Most types force premature design/optimization. Most unit tests lock up some specific implementation (increasing cost of inevitable refactors) rather than prevent actual bugs.

Nil-punning in clojure has spoiled me rotten, and now every other language is annoyingly verbose and pedantic.

18 more...

Nice work!

Tauri is great. I haven't built a proper app with the nice native backend features, but i wrote a wrapper for passing a url on the command line, which lets you run an arbitrary web app like it's a native one: https://github.com/russmatney/clove

Very happy to have something lightweight!

Just to share a perspective from erlang/elixir: pattern matching to filter for only happy-path inputs and the principle of “letting it fail” (when the inputs don’t match the expected shape) works really well in some paradigms (in this case, the actor model + OTP, erlang’s 9 9s of uptime, etc). In that kind of architecture you can really only care about the happy path, because the rest is malformed and can be thrown away without issue.

Fair! Naming is hard, but maybe that’s no excuse for not defining a thing

I think of this as interactive development, or repl-driven development. You can work this way today in Clojure (frontend, backend, and lately even for scripting via babashka), and with lisps in general - the syntax lends itself to sending expressions to the repl and returning values to your editor.

It’s really the best way (my favorite, at least) to program that i’ve found for exactly the reasons you mentioned - it’s excellent for debugging and ensuring the behavior of small functions with minimal overhead.

Types are frustrating because they lock things up and they don’t guarantee behavior, which is really all a program cares about. I feel similarly about unit tests… it’s extra code locking up your behaviors, so make sure they’re what you actually want! A general problem with types is that you have to commit to some shape early, which can lead to premature design and basically some arbitrary DSL when you just needed a couple functions/transformations. Feels like the problem of OO at times.

On the other side, the trouble (beyond people generally not wanting to read/learn lisps, which is unfortunate) is that repl-driven dev requires that you take care of your tools, which means there’s a tough learning curve and then some maintenance cost for whatever editor you want to use.

At a career-level scale, in my opinion, the investment is well worth it, but it’s a tough thing to figure out early in your career. I expect most devs with a couple years of js/python see types and feel like it’s a huge relief, which is real, and maybe types make sense at a certain team size…

I think people should spend time in several different languages and paradigms - it makes the ones you go back to make more sense :D

It was pointed out to me i should add OOP. Burn it all down!

I’ll warn that it’s a bit of a mess in there! I use it daily on my machines, but i feel it’s not super approachable yet. But feel free to grab ideas or ask any questions, it has some cool features!

Sorry, I liked this hot-take setup and I’m shooting from the hip a bit. Maybe i actually mean objects/classes, not types? Can’t everything just be a bag of key-values, like in clojure?

I have been building mostly prototypes (games and wm-tools) for a year, so most of my context is getting things working to see if they are useful rather than locking them down.

I thought about my argument a bunch, and while i have alot of complaints, it all sounds like non-specific whining to me, so i’ve decided to give up.

types and unit-tests have their place. Fine! I admit it! i was pushing a hot-take I’ve had on a few occasions, and I’m glad to see this programming community is alive and well! If you need me I’ll be in my clojure repl.

Maybe you could dig into a few open-source clients to see how they work with it?

E.g. someone shared a basic lemmy viewer in godot the other day: https://github.com/sevonj/gdlm - it’s rough but probably not too much to read through. Was posted in /c/godot: https://programming.dev/post/48482

100%! It was mind-blowing to realize lisps are actually syntactically simpler than all the non-lisps so popular today

Takes a bit of love from editor standpoint unfortunately, so most devs will just never attempt that hurdle

Very happy to share this hot-take :) Definitely code-base and team-size are a huge factor, and I mostly work on my own projects, so each project is very different. still, I expect to get downvoted into oblivion by the last decade's influx of typey-langs and -devs.

I think most love for types is folks being happy they don't need to assert on the input to every function, i.e. static analysis and reduced unit-tests. It's hard for me to not see types as asking folks to pre-design their entire system (by defining types first!), before you've even started writing a few functions, which are actually what the system should codify (behaviors, integration tests). It's also frustrating b/c types don't guarantee that the system does-the-thing, only that the type-system and compiler are happy, so it's like pleasing the wrong boss, or some metaphor like that.

I like to work with behavior directly in functions, which should be the same regardless of the type passed in. Unfortunately most dynamic languages have their flaws (js,python,etc), so this kind of opinion suffers b/c of those languages... similar to type-favoring opinions suffering b/c of langs like typescript.

Nil-punning makes me very happy - that's a hill I will actually die on. Almost every project i've worked on, there's no reason to go out of the way to specifically handle every case of not the right input or oh-no-it's-null! Whenever you have null, you just return null from this function too, and guess what, everything's fine - no need to crash and blow up b/c one thing wasn't there. Mostly this is a complaint about things completely crashing for no reason, rather than being incomplete (i.e. some data missing) but still working for the user.

Anyway, lots of different use-cases, and use the right tool for the job, etc etc. types and unit tests are useful for some things.

3 more...

I think you’re right re:oop - let’s throw that in there too.

One problem is naming things - bad names/naming conventions can start things off in a bad direction, so you spend forever figuring one out… but do you really need this thing you’re naming after all?

Maybe the hot-take is more like: All code is bad, so less code is better…. what should we drop first?

Indeed, the problem with gui apps is when you can’t script them!

I always loved alfred on osx, then loved scripting rofi on linux, only to come back to osx years later and find alfred can’t be invoked with stdin options. It’s damn shame….

We used to call this ‘Code is Cheap’ at my last job - you’re spot on about the value of it

Plus the post-gamr analysis tools are great! Tho a bit odd discovery-wise.

I suppose i should at least caveat by saying i don’t by any means advocate for all dynamic langs over statically typed, and i agree types/unit tests are necessary for most languages. So please don’t make me write python over rust!

You can get the benefits of types/unit-tests via static analysis on a per-function basis with clojure and a library like malli, and for me that hits a minimalist sweet-spot.

2 more...

Sounds like a frustrating issue - feels like salesforce shouldn’t be enforcing that number vs string in the first place, because it could just get coerced later on. But, it’s out of your hands for sure, and there are tradeoffs for them making their API “easier” to work with.

And yeah I’m being a bit obstinate in this hot take - it’s easy to get away without types when working on smaller projects and in more modern languages, especially for low-stakes dev tooling. In larger projects, types can help improve confidence during large refactors.

I just want less code to maintain in general…