1. 2

    Company: Icon Systems, Inc.

    Company site: https://iconcmo.com

    Position: Full-stack web developer

    Location: Moorhead, Minnesota — on site

    Description: Icon Systems does management software for churches and non-profits, keeping track of people, donations, and fund accounting. We’re a (very) small team, so everyone does a bit of everything. We’ve been serving churches since the early 90s, and are now looking for another full stack web developer to join our team in northwestern Minnesota.

    Tech stack: PHP & JavaScript

    Contact: see website or message me

    1. 6

      If you want a really good user interface then give it modes like how Vim has them.

      This is the first thing they told me NOT to do when doing GUIs at university. In fact, it is said that Ctrl-C/Ctrl-V is so popular, because it’s modeless. I think there’s actual research that shows that modes in GUIs are bad, for various reasons but it’s been a while since I studied HCI.

      1. 3

        That’s what I’ve read, too, especially in Jef Raskin’s The Human Interface. I suspect the copy/paste work was from Larry Tesler, who reportedly had “NOMODES” on his license plate?

        That all said, I definitely see that all the software I use actually has quite a few modes…and, when trying to make software for people, people tend to like having modes (at some level) to “guide” them around a process. Is that because they don’t want to spend the time learning a new interface as compared to something that is familiar? Or because of a different valuations between long-term efficiency as compared to the initial learning curve? I don’t know. :-)

        Out of curiosity, from when you did study HCI, do you have any recommended texts or resources?

        1. 3

          Maybe the disrepancy here is due to how a broad concept a mode is. I believe the problems are there. Wikipedia has a section about mode errors in user interfaces.

          There’s certain kind of behavior that is terrible, but it’s not entirely captured by vilifying modes (well, if we’re precise then it is though).

          1. Notification pops up when you’re trying to do something and you click the notification away accidentally, while also messing up whatever you were doing.
          2. Something steals the focus while you’re writing a command.
          3. A prompt grays off everything else in front of you, the answer causes an irreversible change, but to answer it you’d have to look up something first.

          I’d be quite furious if Vim abruptly shifted --INSERT-- to --VISUAL-- when I’m typing text. That has never happened though.

          So maybe the rules of good modes can be captured in this way:

          1. The mode changes immediately upon an user request of mode change.
          2. The mode never changes due to an external action.
          3. The mode always displays itself properly.
          4. The mode change is an irreversible action in itself.
          5. The volatile internal state that is destroyed on exit from the mode is identifiable for the user.

          I’d think this may be good enough to be added there into the post. What do you think?

        1. 4

          Most functional languages fit this category. Clojure is a good example of a language that provides great tools to avoid naming transient variables with its various threading macros.

          1. 3

            It’s not really a functional language, but fwiw this is also common in modern R code via magrittr pipelines.

            1. 1

              You still have to name functions.

              1. 3

                If you want recursion you’ll have to name functions, unless you want to write out the combinator from first principles every time. (Naming the combinator fix would be cheating!)

              2. 1

                That’s a good point…I hadn’t thought of that, and I use method chaining all the time! Do you find in Clojure that it is difficult to debug the intermediate states of a “thread” (not sure what term is appropriate here) such that intermediate variables would be more convenient? (I guess I’m thinking from a perspective of JavaScript’s method chaining, which seems similar…and it is somewhat frequent that I need to log intermediate values in a .map.reduce.filter chain.)

                1. 4

                  In the standard library, you can debug -> using another (-> doto prn) and you can debug ->> using (#(-> % doto prn)), although I usually use taoensso.timbre/spy for this. A simplistic solution to work for both ->, and ->> is (defn debug [x] (prn x) x).

              1. 21

                All the stack based ones: Forth, Cat, PostScript, etc

                1. 2

                  I only recently saw my first example of a stack-based language. My thought was that it seems terribly difficult, as a programmer, to keep in mind what the stack contains at any given point in time. Is that something one gets used to over time?

                  1. 8

                    I found it fun, when learning Forth, to actually work things out using a physical stack of index cards and a pencil. But yeah, you get used to it pretty quick.

                    1. 2

                      In my experience, words rarely cause more than 7 changes to the stack (like, rot pops 3 and pushes them back in a different order, for 6 changes, while dup pops once and pushes the same thing twice for a delta of one change), so if you get used to chunking in terms of only what a word pops and pushes, you can almost treat it like imperative with implicit args.

                    2. 1

                      I think it is difficult at first but once you get used to use combinator words (common in e.g. Factor) that probably becomes just as obvious as using map and fold in functional languages.

                    3. 1

                      Forth may omit variable names, but makes up for it with many word names.