<!DOCTYPE html><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<font size="4" face="monospace">So, you provide several good
arguments here for "Java picked a bad default with respect to
mutability." (It is in good company; Java picked many bad
defaults, such as package visibility rather than private, classes
being extensible rather than closed, etc.) Let's just take it as
given that non-final is an imperfect default for fields. <br>
<br>
Which brings us to the next question: "now that we realize the
default is bad, should we change it?" This is a much harder
question, because it involves the reality of 10M developers and
billions of lines of code. <br>
<br>
One bit of prior art here that might be relevant (and the
experiment is still playing out) is C#'s flipping of the
nullability default on a per-module basis (with injecting checking
at the boundaries.) This was a bold experiment and we are
interested in seeing the results.<br>
<br>
The problem with trying to fix the mistakes of the past is that in
most cases, you are just creating a fork and forcing users to deal
with both branches. If we had a directive:<br>
<br>
class X { <br>
#pragma default-final<br>
<br>
...<br>
}<br>
<br>
then now users have to keep track (possibly on a per-file basis)
of where "int x" means final or mutable. This is adding cognitive
load to all users, since almost no Java developer has the luxury
of controlling 100% of the code they deal with. <br>
<br>
<blockquote type="cite">
<div>A one line distillation of the above is perhaps:
"Immutability is common enough to consider a fast path at
source level; the current slow path has negative consequences
for cognition and devx."</div>
</blockquote>
<br>
Valid, but what this misses is: "having to constantly reason about
whether line #656 of Moo.java is on the fast path or the slow path
has even higher cognitive load." <br>
<br>
</font><br>
<div class="moz-cite-prefix">On 1/17/2024 10:20 PM, Subra V wrote:<br>
</div>
<blockquote type="cite" cite="mid:CAFUsZQGoJic90k1sidiDaerd69z4yEdWMjib3kgzmW1qxUhznQ@mail.gmail.com">
<div dir="ltr">Hello Project Amber team,
<div><br>
</div>
<div>What are the current thoughts on providing source level
mechanisms for opting-in to mutability rather than the current
opt-out? For example, a notion of immutable class (not a
record) can obviate specifying "private final" for fields.
Opt-in mutability would perhaps also jive with two recent
themes in language evolution: 1. Functional style 2. More
cognition, less ceremony (switch statement, pattern matching
to name a few). </div>
<div><br>
</div>
<div>If there's prior relevant material, I'd appreciate a
pointer; Dr. Google hasn't uncovered anything of note.
<div><br>
</div>
<div>I realize that this question has red flags of "proposing
a solution" to "my specific problem". So, let me clarify
that (1) I only write because I believe there's a reasonable
chance that opt-in mutability is of fairly broad interest.
(2) I am not proposing obviating the need for 'private
final' as a solution; instead, it is meant to be analogous
to saying 'I want String interpolation', a 'solution' from
which language designers carefully teased apart a
general problem and solved it in the form of String
Templates.
<div>---</div>
<div><br>
</div>
<div>I am certain language designers are aware of this (and
plenty more), but in the interest of intellectual honesty,
let me attempt to articulate problems with
default-mutability from my default-immutable practice.</div>
<div><br>
</div>
<div>1. [Immutable style feels second class] Java has moved
in a functional direction much to my (and most
practitioner's?) pleasure. For the subset of folks who buy
into this direction, Immutable classes are natural. Yet,
they feel second class in that (1) notions of "private
final" aren't relevant yet pollute (2) It requires extra
work [making all fields final, binding them in
constructor] compared to the default case of mutability</div>
<div><br>
</div>
<div>2. [Cognitive Cost of Ceremony] For non-record
Immutable classes, I have to (1) Write 'private final X'
and then add a constructor param and set `this.X = X` in
the constructor. (2) Read and verify `private final` on
every field to know that the class is immutable. Even
though IDEs help, it breaks the flow of thought both when
reading and writing</div>
<div><br>
</div>
<div>3. [Poor Prototyping Velocity] I often find the
ceremony especially frustrating in early phases of design,
especially when using immutable classes. Imagine I have 20
concepts/fields and I am attempting to organize them. A
common occurrence is to realize 'ohh this field/method
logically belongs to that other class; let me move it
there' but it is a pretty big chore to do so (even with
Intellij) given that immutability takes extra work to
achieve. Such moves also come with further transitive
ripple effects. All the busy work perhaps accounts for
upwards of 30% of the initial few hours/days of design and
more importantly, constantly interrupts thoughts. For
contrast, if I just make every field public during the
initial period, it'd probably be a better experience, but
then I need a magic wand to make them all immutable after
the design settles down.</div>
<div><br>
</div>
<div>A one line distillation of the above is perhaps:
"Immutability is common enough to consider a fast path at
source level; the current slow path has negative
consequences for cognition and devx."</div>
<div><br>
</div>
<div>Appreciate thoughts.</div>
<div><br>
</div>
<div>Thank you,</div>
<div>Subrahmanyam</div>
<div><br>
</div>
</div>
</div>
</div>
</blockquote>
<br>
</body>
</html>