and don't forget... if you've ever worked with strings in java then you are ALREADY dealing quite happily with immutable objects.
"Hello " + "World!" will yield a new immutable String "Hello World!" Or try this: val x = "Hello " val y = x + "World!" It would be incredibly surprising and error-prone if sequences like that caused x to change. But if you're working with mutable object then that's exactly what would happen... Also, ANYTHING that might possibly be used as a key in a hashed container must be immutable (at least, the fields that contribute to the hash key must be mutable), or you're going to run into problems with the collection appearing not to contain the object after mutation (even though it does). On 29 April 2010 17:11, Reinier Zwitserloot <[email protected]> wrote: > egervari, if EVERYTHING is immutable, changing the name of an object > that contains a complex set of data is still simple; just clone it > (shallow - if immutability is everywhere copying is trivial and cheap) > with a different name. > > Nevertheless, trying to make everything immutable is failing the first > Rule of Programming Rules: They never apply in every single last > situation. If in doubt, go for immutability, but if its clear the > design would suck gigantic balls if you do that, then don't. For > example, in a game, making a character's Hitpoints, for example, > immutable, hence creating a copy every time these get affected, that > really isn't useful. Also, the state you are leaving behind (the > character with more hitpoints) really isn't useful by itself. > > To illustrate, here's an example: > > Let's say I have a City object which represents a city. This is its > complete definition: > > public class City { > private String name; > private Location centralStation; > } > > If that's all there is, it's obvious that centralStation should NOT be > immutable, and hence city won't be immutable. Every decade or so its > possible for a city's central station to undergo major renovations and > move a bit. > > However, all the same, a location *SHOULD* be immutable. A certain > latitude/longitude cannot change, and it would be completely > ridiculous if code that's working with the current location of the > station all of a sudden sees its location move around. In practice, if > Location were mutable, the getCentralStationLocation() method would > have had to give a defensive copy anyway, so even the theoretic idea > that one gets a magically transforming Location object that 'tracks' > where-ever the central station is at this point in time isn't really > feasible without a lot more effort. > > Sometimes these things become complicated though. Should 'name' be > immutable? Names tend to be used as keys and in display lists, so name > changing at a whim is somewhat disconcerting (that is: Code using the > "City" library needs to put in extra effort to work around the notion > that name can change over time), and cities don't usually change > names. Nevertheless, when Leningrad renamed itself back to St. > Petersburg, was it a different city? The answer "No, it's the same > city" seems more logical than "it's a new city", so I'd err on the > side of making name mutable here. > > However, with a slight tweak to the City model it would make more > sense for City objects to be immutable: > > public class City { > private final String name; > private final Location centralStation; > private final Timestamp when; > } > > we included a timestamp. It doesn't matter that St. Petersburg is > called St. Petersburg today, a city object with a timestamp of 0 (Jan > 1st 1970) can only have one name: Leningrad. And this name can't ever > change, except in the face of wrong data. > > > This is in fact a common thread when trying to represent a state- > changes-over-time system with immutables, such as a game. You include > a timestamp. This can work (and if you program in Haskell you're > pretty much forced into it), but it's easy to see that this is > probably not the best use case for immutables: You'd have to write > code to integrate two diverging time-lines. If you don't, there's > absolutely no point in tracking any of it. However, with both > timestamp tracking and a merge algorithm you can massively scale your > game, by letting each thread do its own thing, merging only on an as > needed basis. > > > There are also questions about equality in either system: With > timestamped final cities, obviously the 1980 state of a city isn't > equal to the 1970 state of a city, but an .isSameCity() method would > be prudent. I don't see a way to write it without including an ID of > some sort. Same goes for when you're working with a mutable city. With > an ID you can even use the city as a key in a map, as the equality/ > hashCode of it won't change even if you fiddle with it. > > > However, if a field can NOT reasonably change intrinsic meaning over > time it shouldn't be mutable just because the underlying system may > have a need for changing it. For example, java.awt.Point is mutable, > and that was a mistake. A mutable Location object would be a mistake. > Mutable strings would be bad. Mutable numbers are no good. Sometimes > you need a mutable *container*, and that's fine, but that should be > explicit (fortunately java has them; java.util.concurrent.Atomic*). > > On Apr 29, 2:41 pm, egervari <[email protected]> wrote: > > How many of you are currently programming in a hybrid language such as > > Scala? > > > > I'm finding it difficult to make things immutable. While I am > > definitely using more immutability than I ever have in the past, I > > don't think it's practical for some applications. > > > > For example, I am making a game right now. While I can kind of see how > > to make it immutable... I'm not sure it's entirely desirable. There is > > a lot of state in a game, especially a complex one. > > > > Right now, classes that are immutable are things that don't have a lot > > of nested structures, or things that have case class semantics. For > > example, a Potion of healing that heals for 200 health is a good > > example of an immutable object. Once it's consumed, you can just throw > > it away. > > > > Also, various parts of the game will have use actors, so I make sure > > any of the objects that need to be passed from actor to actor in the > > messages are immutable. If they aren't going to be used as messages, I > > prefer mutability instead. This is backwards of what people have been > > saying to do... but I find it makes things much simpler. > > > > The hardest part of keeping everything immutable is large classes with > > collections. To make them fully immutable, you have to clone > > everything on every operation. > > > > Let's say you a character in an rpg game and you change their name. > > Bam, you gotta clone all fields and return a new character. This is a > > gigantic pain in the ass. It feels bloated to do it over and over, and > > it is a maintenance havoc. > > > > I'm thinking back to some systems I have done in the past, where I > > have 130-150 domain objects. How do we make those immutable? If you > > have a customer... and you change a line item on an invoice... you'd > > have to re-create the entire object graph if you were working with the > > root customer object. > > > > How have you been wrestling with immutability/mutability in your > > programs? What patterns/principles have you been using to decide? How > > far have you gone to the immutability end? > > > > -- > > You received this message because you are subscribed to the Google Groups > "The Java Posse" group. > > To post to this group, send email to [email protected]. > > To unsubscribe from this group, send email to > [email protected]<javaposse%[email protected]> > . > > For more options, visit this group athttp:// > groups.google.com/group/javaposse?hl=en. > > -- > You received this message because you are subscribed to the Google Groups > "The Java Posse" group. > To post to this group, send email to [email protected]. > To unsubscribe from this group, send email to > [email protected]<javaposse%[email protected]> > . > For more options, visit this group at > http://groups.google.com/group/javaposse?hl=en. > > -- Kevin Wright mail/google talk: [email protected] wave: [email protected] skype: kev.lee.wright twitter: @thecoda -- You received this message because you are subscribed to the Google Groups "The Java Posse" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/javaposse?hl=en.
