HN user

rakpol

36 karma
Posts0
Comments21
View on HN
No posts found.

Aah, sweet, someone else who uses Perforce! I've been wondering, do you use version control as:

1. a way to record logical changes to files (e.g. implement two features without making any commits, then when you're done, pick out the files/chunks that encode each feature and create commits out of them),

2. a record of history (e.g. just start writing code and make a commit every time you compile/run tests without unexpected failures),

3. something else?

I've found it very painful to apply my git-adapted workflow to Perforce: I _want_ to just start coding, testing out various possible design choices and implementations instead of only theorizing about them, but can't (e.g. "I wonder if I could factor out these methods + fields into a different class?" Perforce: oh well, I guess I should write it down somewhere to remember for later. Git: branch my current work, spend five minutes sketching an extraction, then realize it's insane and continue working). Am I crazy and just don't realize ow much better the Perforce model is?

Thus the reason I know carpentry :3 but, having programmed for a while, it seems like the hardest problems are converting plain english requirements to source code. At the point that that becomes trivial (and doesn't fall into WYSIWYG editors or graphical languages, which already exist and haven't brought about the apocalypse), wouldn't you just ask the computer to make itself smarter over and over? Or ask it to automate any other profession with stupendous ease?

Isn't cyclomatic complexity just about the number of paths through code? It seems like (statically resolved) nested calls, as long as they don't loop or branch themselves, shouldn't increase cyclomatic complexity.

I was thinking about the issue of nested code the other day -- isn't it (mostly) an editing environment problem? I mean, if my IDE can detect that a method is pure, couldn't it do a little magic (e.g. provide a different coloured background, some dotted boxes, etc.) and show me the inlined code right there? It doesn't seem wise to architect your codebase around the deficiencies in your tools, since one is (hopefully) going to long outlive the other.

Related:

[1] https://dubroy.com/blog/method-length-are-short-methods-actu...

I agree to an extent ... this example is pretty contrived, but when you start getting around ten filter/map/groupby operations in, it gets a little difficult to follow what's supposed to be happening. So typically, my first step towards breaking it out into a method is separating out the individual streams like above. As is mentioned in a cousin comment, it also looks a lot nicer with type inferencing, but alas we are stuck with the verbosity of standard Java 8 for now.

From the perspective of a younger dev, this seems like excellent reading for older devs, who tend to enforce their personal style without deferring to the de facto language standards (or PEP 8 for those working in Python). In fact, perhaps everyone could do with downing a half dozen humble pills and optimize their code for harmonious human interoperability than anything to do with machines :)

As someone who could very easily be on the other side of that code review (and I'm preeeettty sure I'm not in this case?) I feel obliged to at least try to provide a counterpoint :).

So I agree that enormous blobs of unreadable crap are indeed unreadable, and that regardless of how neat and functional your code is, it can still be complete gibberish to most people. That being said, long chains of streams can be broken out quite nicely by using intermediate names:

e.g.

  Comparator<Transaction> descendingTransactionsByValue = comparing(Transaction::getValue).reversed();
  Stream<Transaction> groceries = transactions.filter(t -> t.getType() == Transaction.GROCERY);
  Stream<Transaction> sortedGroceries = groceries.sorted(descendingTransactionsByValue);
  Stream<Transaction> transactionids = sortedGroceries.map(Transaction::getId).collect(toList());
vs. the first code block under "Figure 1" in the linked article.

For me at least, it helps keep code from getting too unruly: you only have one 'thing' you can do in a filter, map or sorted call, unlike in a foreach loop where anything can go. So my thesis is this: using streams I can quickly scan over the function/stream names to get the gist of what it's doing, but using foreach loops I need to closely examine each line to have any idea of what's happening :3 (e.g. people love abusing labeled breaks [1] in our codebase, as well as excessively modifying input parameters w/o documentation, so I might be a bit biased against for loops)

[1] https://stackoverflow.com/questions/14960419/is-using-a-labe...

Your original post mentioned that you thought the author was inappropriately associating low prices with low quality ... that's not prejudice, though, right? That's a bog-standard standard heuristic people in my culture use to establish value (see: putting weights in electronics to make them feel more 'premium'). IMHO, it is genuinely terrifying that melamine made it into so many chinese dairy products. Perhaps the media sensationalized it too much, making the event stand out in my memory over similar local events? Who knows.

I guess what I'm getting at is rushing to the conclusion that xenophobia is the only deciding factor here seems a bit premature, and that the problem itself is likely multifaceted.

Super biased, layman thoughts incoming.

Re. countries vs corporations: countries in isolation make laws for themselves (consumer protection, long-term economic protection, etc.), whereas corporations must abide by the laws of their host countries (hence tax evasion via incorporation in accommodating countries). If two countries start to compete, there isn't really anything that stops them from annihilating one another in disturbing fashions (e.g. erecting walls, slinging propaganda, blockading, etc.) other than treaties. Get enough treaties together and you get the EU.

Yes, but I have ... reservations. Same as with OCaml, I took on a small project with Scala and enjoyed the language, but only after carving out a subset of it that was palatable. Although it fits the bill, I'd be worried that enforcing conventions would become a large burden.

Unlike Frege where I (might? Frege's the only language of the three that I haven't investigated thoroughly) can point learners to essentially any Haskell tutorial and have them vaguely do 'the right thing', there exists a subset of Scala developers who use the language like Java with type inference. With Frege I could, for example, merely enforce the minimal usage of IO or State, but doing so with Scala is more complicated (maybe force the usage of cats/scalaz and their equivalent monads? It's still very easy to not use them, however). If there were an equivalent to F# on the JVM I'd settle on it in a heartbeat, but the dearth of well supported, pure functional languages makes this a tough choice. All in all, I'll probably go with pure4j, but it would be nice to stop writing Java at some point in my career.

Aah, fair point, it is pretty niche. Still, merely going off of their comparative contribution graphs [1] [2] and issue trackers [3] [4], it seems like Frege has a fair bit more throughput: for better or for worse, it seems like more _things_ are happening. Although I'll be the first to admit it's a misleading metric for determining the maturity of a project, it's still something. Imagine finding a bug in Frege: it seems like they merge even small patches from contributors, whereas ocamljava is essentially a one man show. Adopting ocamljava would probably mean forking and maintaining it too, whereas there's a possibility of just contributing to Frege.

That's all just my opinion, of course, and I hardly have enough industry experience to back up its validity! 'Just sanity checking my reasoning :)

[1] https://github.com/Frege/frege/graphs/contributors

[2] https://github.com/xclerc/ocamljava/graphs/contributors

[3] https://github.com/Frege/frege/issues

[4] https://github.com/xclerc/ocamljava/issues

Fair point, but it might almost be worth it just to suggest it just to see what the opposition is like -- if there isn't much, or any, go with Frege; otherwise, fall back to pure4j. I'd imagine framing the decision as picking from two choices would improve the odds of at least one being selected.

The idea behind both would be to introduce it incrementally, carving out parts of the codebase to be rewritten one section at a time.

You're right, though; pure4j offers an immediate and easily obtainable win, so it'd definitely be an easier pill to swallow. Thanks :)

That definitely made the short list! I picked up ocaml for a side project and enjoyed the language quite a bit. However, ocamljava is either dead or dormant at this point (last commit to master in June of last year) and it seemed to only have had one major contributor -- it would seem irresponsible to adopt such a solution in light of that.

Hoping for a little advice: I'm trying to push for some development culture changes at work, one of which is doing more local, incremental refactors rather than large, all-at-once changes (i.e. the sort of thing for which one books 'architecture meetings'). Since we'll hopefully be massaging large parts of the codebase, there's an opportunity to jump into something new with both feet.

Question: what do you think of the thesis of pure4j [1] vis. frege [2]? Namely, are the advantages gained by switching to a haskell-like language far above those attained by simply forcing effects into a small part of the codebase?

[1] https://github.com/pure4j/pure4j

[2] https://github.com/Frege/frege