Oriel Jutty :hhHHHAAAH:

Indoor European. Knows #regex. Writes #code (in #C or #Haskell or #Perl or #JavaScript or #bash). Not a fan of racism, sexism, transphobia, or bigotry.
100% OPSEC.

Kompatibel mit handelsüblichen Klemmbausteinen.

  • 0 Posts
  • 58 Comments
Joined 3 years ago
cake
Cake day: November 6th, 2022

help-circle
  • First off, I don’t know you and I’m not accusing you of anything. But the document you wrote says what it says, and I’m standing by what I wrote.

    “Only release every two weeks.”

    No. Nowhere did I say that. In fact, the team I wrote this about worked on a 1 week sprint.

    OK, cool. Make it “only release once per week” then; it doesn’t change my point: The article defines “sprints” as a deployment schedule. What kind of software are we talking about here? A website or similar provided “as a service” over the internet? Then why stick to a rigid one or two week release cycle? Or a traditional “run locally” application? Then weekly updates are much too frequent, I’d say.

    (I did note the date on the post, but it didn’t strike me as relevant. My first contact with “agile” was in 2013 and our deployments were a manual process (later automated), but we did it without downtime and we never waited until the end of the sprint to release 20 finished tickets at once. In fact, I’ve never worked at a place that treats sprints as release cycles.)

    “This includes bugfixes”

    This is true. It’s is primarily because deviating from the commitment you made with the company to have x jobs done by the end of the sprint necessarily means being unable to meet that commitment.

    No, I’m not talking about going bug hunting, I’m talking about releasing the (already developed) bug fixes. Again, if we “think of sprints as a deploy schedule”, then even bug fixes developed on day one of the sprint still need to sit around for a week or two.

    Are we here to get work done, or throw everything out the window to sit around and talk through a 6-person meeting whenever something goes wrong?

    Now it’s my turn to say “nowhere did I say that”: When I mentioned root cause analysis and working on underlying issues, I meant actually doing that, not having a 6-person meeting. (Why would I ever hold a meeting?)

    Consider the following analogy: On day one of the sprint, someone trips over a power cable, twists their ankle, and takes out a server. By the rules set out in the article, we would plug the server back in and apply pillows and ice packs to the ankle (i.e. fixing the immediate issues). But the rules wouldn’t let us ask who ran a power cable through the middle of a room, or move the power cable out of the way, or find a different power source for the server. We would have to wait one or two weeks for the next sprint to start and until then just live with the tripping hazard. (And in software there can be many “tripping hazards”, particularly when a team has undocumented, organically grown, manual processes.)

    “If it can’t be done in 4 hours, it can’t be done at all.”

    That’s a gross misrepresentation. What I said was that a job must be limited to roughly 4 hours of work. If that job is going to be more, then you should break it up to allow the work to be spread around.

    That’s the same thing I said. Tasks that can’t be broken up into less-than-four-hour units of work can’t be done. How is that a misrepresentation?

    “Don’t document things.”

    I didn’t say that.

    “[…] developers have only 3 responsibilities over and above writing code throughout the sprint. [daily stand-up, sprint retrospective/planning, figuring out WTF the client wants] Note what isn’t in that list: […] Documentation”

    And no, this isn’t about commenting code. The article explicitly calls things like wiki documentation an “exercise in futility”. Later on, the “Documentation” section explains how to transfer knowledge to new developers: Have them work on various “components” and let them figure it out themselves (i.e. reverse-engineer the code). Knowledge only exists in people’s heads: “[…] if Daniel gets hit by a bus, the project can go on because Aileen, Charlie, and Aisha have all spent some time poking at the payment engine.” Written documentation isn’t even considered as a possibility.

    “The job of a software developer is to crank out code and nothing else, especially not design, testing, or documentation”

    It should not be a surprise that one would expect software developers to develop software. If you want design, you hire a designer.

    OK, let me just quickly hire a network protocol designer, data structure designer, algorithm designer, API designer, and software architecture designer. Sure, some people would consider that to be part of software development, but not you, apparently: You’re doubling down on the “software development = cranking out code” thing.

    Now, I haven’t been doing this for 27 years, but some places where I worked defined software development much more broadly: Programming, QA/testing, UX and UI design, user studies, requirements gathering, internal and external documentation, it all fell under the “software development” umbrella.

    Testing is part of the process though, and I never said otherwise.

    You did: “developers have only 3 responsibilities over and above writing code throughout the sprint” and none of them is testing.

    “Don’t even think about ethics.”

    FUCK THIS. Don’t you dare suggest to me that I wouldn’t demand ethics of everyone I work with.

    “[…] developers have only 3 responsibilities over and above writing code throughout the sprint” and none of them is thinking about ethics.

    Engineers have a responsibility to do right by the world they live in, and nothing I’ve mentioned in that post would suggest otherwise.

    I suggest re-reading the “Talk Less, Code More” section. (You could also call it “Think Less, Code More”.) It emphasizes the smooth flow of simple tasks to be coded up, piece by piece, from “todo” to “finished” with a minimum of hassle. Where in that process is there room for friction in the form of thinking about (let alone questioning) the bigger picture?


  • There’s some insane ideas in there, like:

    • Only release every two weeks.
    • This includes bug fixes.
    • Emergencies can be dealt with immediately, but any root cause analysis or deeper work on underlying issues must wait for the next sprint.
    • If it can’t be done in 4 hours, it can’t be done at all.
    • Don’t document things.
    • Don’t write bad code. (Also: You must use classes and methods, and variable names must be words.)
    • Rigid adherence to the “agile process” is required.
    • The job of a software developer is to crank out code and nothing else, especially not design, testing, or documentation.
    • Don’t even think about ethics.








  • BEFOREHAND: close door, each window & exit; wait until time.    open spellbook, study, read (scan, select, tell us);write it, print the hex while each watches,    reverse its length, write again;    kill spiders, pop them, chop, split, kill them.        unlink arms, shift, wait & listen (listening, wait),sort the flock (then, warn the "goats" & kill the "sheep");    kill them, dump qualms, shift moralities,    values aside, each one;        die sheep! die to reverse the system        you accept (reject, respect);next step,    kill the next sacrifice, each sacrifice,    wait, redo ritual until "all the spirits are pleased";    do it ("as they say").do it(*everyone***must***participate***in***forbidden**s*e*x*).return last victim; package body;    exit crypt (time, times & "half a time") & close it,    select (quickly) & warn your next victim;AFTERWORDS: tell nobody.    wait, wait until time;    wait until next year, next decade;        sleep, sleep, die yourself,        die at last
    





  • Yeah if you just ignore all the other control characters you had to add instead then you sure saved on parens. Bravo!

    Yes! Exactly! Thank you; that was my whole point.

    Your whole argument is basically treating parens as something different from other syntax characters, which is a nonsensical argument. If you’re going to compare syntax then you have to compare all the syntax you have.

    I’m not trying to compare syntax in general. All I’m doing is refuting the original claim, which was that Lisp doesn’t use more parentheses than other (“conventional”) languages. It does.

    All that stuff about syntactic noise, granted. I mean, I don’t agree personally, but it’s irrelevant to my point.


  • Let’s take a step back. I feel this discussion has got off track a bit.

    The original claim was that Lisp’s reputation as having lots of parentheses was undeserved because it uses the same number of parens as other languages that use () for function calls; Lisp just puts the parens in a different place.

    My objection was basically that Lisp also uses parentheses for what in other languages is a declaration, a statement, a block, an operator, etc so just looking at function calls doesn’t give you the whole picture.

    You said that “Lisp” is actually a family of languages, that Clojure uses fewer parens than other Lisps (I object: still more than non-Lisps), that there are macros for infix expression syntax (I object: non-standard/3rd-party solutions that only help with operators), that parens don’t even matter because of structural editing tools (I object: irrelevant, the discussion was about the number of parens, not whether they “matter”).

    I also disagree with “the total number of parens in your examples is about the same”. This is a micro-example, so when the original Lisp (Clojure) code has 4 pairs of parens and the C-style (JavaScript, Perl) version has 2, that’s twice the parentheses to me, not “about the same”.

    I’ve tried to find a slightly bigger code sample, so I clicked around in the Clojure standard library. Here’s a chunk of clojure.string: https://github.com/clojure/clojure/blob/ade22645ba5dbf4c0d8115b19938af96d6fb4cd5/src/clj/clojure/string.clj#L275-L317

    (defn ^String trim-newline  "Removes all trailing newline \\n or return \\r characters from  string.  Similar to Perl's chomp."  {:added "1.2"}  [^CharSequence s]  (loop [index (.length s)]    (if (zero? index)      ""      (let [ch (.charAt s (dec index))]        (if (or (= ch \newline) (= ch \return))          (recur (dec index))          (.. s (subSequence 0 index) toString))))))(defn blank?  "True if s is nil, empty, or contains only whitespace."  {:added "1.2"}  [^CharSequence s]  (if s    (loop [index (int 0)]      (if (= (.length s) index)        true        (if (Character/isWhitespace (.charAt s index))          (recur (inc index))          false)))    true))(defn ^String escape  "Return a new string, using cmap to escape each character ch   from s as follows:   If (cmap ch) is nil, append ch to the new string.   If (cmap ch) is non-nil, append (str (cmap ch)) instead."  {:added "1.2"}  [^CharSequence s cmap]  (loop [index (int 0)         buffer (StringBuilder. (.length s))]    (if (= (.length s) index)      (.toString buffer)      (let [ch (.charAt s index)]        (if-let [replacement (cmap ch)]          (.append buffer replacement)          (.append buffer ch))        (recur (inc index) buffer)))))
    

    Total number of pairs of parentheses (not counting doc-strings): 45

    My translation of the code to JavaScript:

    function trim_newline(s) {    for (let index = s.length; index > 0; index--) {        let ch = s.charAt(index - 1);        if (ch != '\n' && ch != '\r') {            return s.substr(0, index);        }    }    return "";}function blank(s) {    if (s == null) {        return true;    }    for (let index = 0; index < s.length; index++) {        if (!Character.isWhitespace(s.charAt(index))) {            return false;        }    }    return true;}function escape(s, cmap) {    let buffer = "";    for (let index = 0; index < s.length; index++) {        let ch = s.charAt(index),            replacement = cmap(ch);        buffer +=            replacement !== undefined                ? replacement                : ch;    }    return buffer;}
    

    Total number of pairs of parentheses: 15

    That’s about a factor of 3. Now, you can argue that I shouldn’t care about the parentheses, but my point is simply that they’re there and you can’t really avoid them if you write in anything resembling idiomatic Lisp.


  • I disagree with pretty much everything you write here, but especially this:

    First of all, you have exact same amount of parens as you would in a mainstream language like Java, C, or Js.

    My Perl example uses “mainstream language” syntax. Apparently that doesn’t count because it’s Perl (scary! mental overhead! write only!), so here’s exactly the same thing in JavaScript:

    function hypot(x, y) {    return Math.sqrt(x ** 2 + y ** 2);}
    

    … or

    const hypot = function (x, y) {    return Math.sqrt(x ** 2 + y ** 2);};
    

    … or

    const hypot = (x, y) => Math.sqrt(x ** 2 + y ** 2);
    

    Note how none of these involve four layers of nested parentheses.


  • OK, my code snippets are Common Lisp. But note that none of them involve list/vector/set literals. I was thinking of [] for array indexing and {} for code blocks.

    As for infix macros, sure, that’s not hard to do, but it’s not built into the language and there being “plenty of libraries” is part of the problem: They’re all subtly different, none are standard, and I suspect most people don’t use them anyway. (Plus there’s fun little design issues like whether a*x + b should parse the same as a * x + b, and if it does, then how do you refer to a variable called a*x from an infix environment?)

    It doesn’t solve the main issue anyway. Take this snippet from the “infix” readme:

    (def hypot  (fn [x y]    (infix sqrt(x ** 2 + y ** 2))))
    

    It ends with a cluster of )))) (reinforcing the “lots of parentheses” impression) and all of those parentheses mean something different: From the outside in, we have the end of a symbol definition (def ...), the end of a function (fn ...), the end of a macro invocation (infix ...), and the end of a function call sqrt(...). It definitely isn’t just “the same number [of parentheses] as any other language that uses parentheses to make function calls”.

    Compare e.g. these versions written in Haskell:

    hypot = \x y -> sqrt (x ** 2 + y ** 2)
    

    … or Perl:

    sub hypot($x, $y) {    sqrt($x ** 2 + $y ** 2)}
    

    … or if you want to separate the function and symbol definition parts:

    *hypot = sub ($x, $y) { sqrt($x ** 2 + $y ** 2) };