3 ms·
I used "opinionated" instead "wrong" intentionally. There's nothing wrong with being opinionated (I'm opinionated, too!), and it's pretty much unavoidable when
by rbehrends 12y ago
I used "opinionated" instead "wrong" intentionally. There's nothing wrong with being opinionated (I'm opinionated, too!), and it's pretty much unavoidable when it comes to coding style; I'd only quibble with calling the document "Best Practices", which seems to indicate an absolute rule. And yes, I also mean that I'm ignoring some of the "MUST" and "MUST NOT" rules (for a very simple example, using "return" at the end of a function in spite of 2.1 as a visual indicator; similarly, 2.9 or 2.14 are sometimes not an option – pun intended – because Scala's abstractions often come with a measurable performance hit; note the inherent conflict between 2.9/2.14 and 3.4 in particular, where often you have to break one or the other rule).
With respect to your points:
> I'm not against destructive updates, but I'm against doing destructive updates without knowing what you're doing.
With all due respect, the document doesn't make this clear. See, e.g.: "a public API exposing a mutable data-structure is an abomination of nature". That's a pretty absolute statement.
> I'm also against usage of shared state without proper encapsulation and synchronization.
There are really two parts to this. First of all, in principle I agree with the above, but that's not what your document says. For example, section 4.1 goes much farther than that; it may be exaggerated overstatement for effect, but it's really not backed up by anything.
Admittedly, part of the problem is that Scala has never fixed Java's broken [1] concurrency model (and may not be able to do so due to interoperability issues), but even so, this is a statement that's difficult to support in the general case.
There are also sections that don't really make sense, to be honest. For example, 4.7: Not only isn't there really a formal definition of "thread-safe", any attempt to define it (such as using non-interference per Owicki/Gries) makes it essentially a global property of the program, not the local property of a module (let alone its API). There are software design and implementation techniques that allow you to have composable module specifications in the face of concurrency, but that's something different.
In a way, yes, avoiding concurrency is not unreasonable advice in the face of the limited tools you have available and you can say that I'm lamenting more the (lack of) actual support for concurrency in modern programming languages rather than criticizing your statement; at the same time, even given the circumstances, section 4 strikes me as overall too limiting. There ARE other techniques to handle concurrency cleanly, after all.
[1] I use the word "broken" advisedly. See http://brinch-hansen.net/papers/1999b.pdf http://brinch-hansen.net/papers/1999b.pdf
- bad_user 12y agoOn 2.1 I cannot agree with you, because if you're using return for clarity, you're circumventing the compiler, which is then unable to do proper inference, not to mention it has gotchas, because as I was saying, most people do not know how return works, and besides, if you need return for clarity, you're doing it wrong and I challenge you to show me a piece of code that is clearer with it. On 2.9/2.14, as somebody that suffered from servers crashing due to enormous load and that had to profile the shit out of everything, I usually find such arguments against persistent data structures to be bullshit, and if you think it matters that much for your problems, you probably picked the wrong language and possibly the wrong platform. And NO, there is no conflict with 3.4. On destructive updates again, there is a fine line between interesting and boring, plus I don't really have time to write a book. But thanks for the feedback, I'll add more details. On 4.1, I really hope you're making a difference between concurrency and parallelism, right? I don't need to back that claim up, just as I don't need to prove that the sky is blue. And as I was telling somebody else, concurrency is not something to take advantage of, but rather something one has to suffer from. On Java's "broken concurrency model", actually I find Java to be quite sane, because at least it has a memory model that works well cross platform and that is generic enough to support all kinds of abstractions built on top, like a sane Future with C#-like async, or light weight threads (Quasar), or extremely efficient queues (LMAX Disruptor), or Erlang-style Actors (Akka), or reactive streams (Rx), or parallel collections (Scala), or STM that works (Scala-STM) or CSP or Agents or what have you. And because there is no silver bullet, all of these abstractions are useful to have in your toolbox. And surely a platform built for a certain abstraction (eg Erlang) will be better than a library, but also find that to be very limiting. Again I challenge you to give me an example of a platform that handles concurrency better than Java. Related to my list, I wasn't the one that posted it BTW, not trying to impose my will on anybody, take from it what you will.