3

This question already has an answer here:

There seems to be a trend towards immutable objects, and functional programming. I recently got aware about the benefits of immutability. However, I am not very familiar with this style of programming.

My current classes may have some private or public mutable variables (state variables). I think these variables are the source of mutable state for the objects of my class. If the number of these variables is high, then the state of objects will be more complex. (if there are other reasons for mutable state of the objects of my class, please guide me about them)

Then, my question is how to refactor this class or even redesign my project to have objects with immutable or less complex state.
For example decomposing of the class to other classes with less mutable variables or any other guideline?

Or in other words, I look for some guidelines to design and implement a project to have less mutable objects as possible?

marked as duplicate by gnat, GlenH7, user40980, Arseni Mourzenko, Dan Pichelman Feb 23 '15 at 18:23

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • What have you tried? I mean, if you know what mutable state is and you know what immutable state is, it should be straightforward to create a solution using the latter rather than the former. What problem are you actually having? – Telastyn Feb 21 '15 at 14:25
  • I guess that you don't refactor individual classes. You design and code an entire application in some more functional programming style (and possibly languages). BTW, functional languages don't use much classes: I coded several dozen of thousands of Ocaml lines and almost never used classes. – Basile Starynkevitch Feb 21 '15 at 14:45
  • @Telastyn I gave an example, I like to know what is the solution to have immutable state for the Page or Blocks...(However I am not sure that is a good example, I look for some general rules ). – Ahmad Feb 21 '15 at 14:51
  • 1
    I like to look at successful open-source projects that use the same programming language as my own project and see how they are designed. Yes, this can be time-consuming given the piss-poor code and design documentation in the open-source world, but the time spent can be worth it. – user22815 Feb 21 '15 at 15:05
4

It's not clear what you're trying to do in that example, and the implementation details of your framework will limit somewhat what you need to do.

Here are some guidelines that I use, which have been successful. There are of course other approaches that are successful. I use C# as my primary language, things similar to C# can use this approach. Other languages may not be able to use it well.

Whenever I consider making a new class, I consider what it needs to do. Some classes represent some data. Some classes represent some functionality (that may or may not require state to work). Most importantly, I consider what dependencies that class has.

Especially for beginners, these dependencies are where mutability is unnecessarily introduced. Whenever practical, dependencies should be supplied in the constructor. They are not grabbed by the class. They are not set as the class is "being initialized". You pass them into the constructor of the class so that the class may squirrel them away as private state or as public immutable state.

For classes that are just data (colors, points, text, rectangles) just set their state in the constructor and leave it be. If they need changed, make a new one.

For classes that are largely functionality, focus on the functionality. If they need private state, so be it. Functionality alone should largely not need public state. Functions are far better when they are pure, and take their dependencies as parameters (or from private class state or immutable class state).

For classes that are stuff that really does change over time (where your warlock is on the map, how much money is in your bank account) then go ahead and make those mutable classes. But try and keep them "dumb". Mutable classes are best when they are like collections. You can manipulate them, and they make it easier to do that, but logic shouldn't be there unless it's burned in logic that is guaranteed to be part of every form of that class.

The key thing to note is that classes are either immutable or they aren't. There's no "less" immutable that gets you any benefits.

  • This tells me to make the Cursor private to the Page, or even better to the TextBlocks or even better to the Write() function if possible? – Ahmad Feb 21 '15 at 16:19
  • @ahmad - Since I don't know what you're using Cursor for, what Page encompasses or why you would use TextBlocks, I can't provide you a good answer. – Telastyn Feb 21 '15 at 19:30
  • In summary, I understood 1-introduce dependencies in constructor and don't change them. 2- avoid public mutable variables, and tendency to control the function of classes by them. 3-use private state in class or in the function itself (a pure function). It all says me that my function should have less side-effects and changing the state of a class... These are all signs of new trend which may even be in contrast with OOP basics. – Ahmad Feb 22 '15 at 12:09
  • 1
    @ahmad - not only "don't change them", but where possible make them unable to be changed. And in my experience, these trends do not go against OO basics. These approaches only enforce the encapsulation, single responsibility, and modularity desires of OO. They help soften the sharp edges that cause many people to frown upon OO. – Telastyn Feb 22 '15 at 14:57
3

A good thing to do is look at most languages' String class. Strings in any language I can think of are immutable, but most of the time nobody has any problem working with them. It's good to think of the ways in which you interact with Strings and ask yourself if you can work on your class in the same way.

For example, if you want to take a String and replace all instances of upper case letters with lower case ones, there's a .toLower() method or something similar which returns a new String object that is a copy of the old string object. The original String stays the same. You can do similar things with most objects. Let's say you have a class that represents events for a venue. Currently, there's some really hip Bourbon tasting event that is set to go down on Thursday, but for whichever reason the event organizer needs to change the date of the event to Friday instead. Replace the old event with another one that has the date field changed from Thursday to Friday:

bourbonTasting = bourbonTasting.replaceDate(DAYS.Friday);

So that's all fine and dandy now! Anything that is looking at the 'bourbonTasting' variable will now read that it is on Friday rather than Thursday.

The thing that becomes hard with immutability, however, is that since you didn't mutate the original anything else that was storing a copy of the old event needs to be updated. Now imagine there's a bunch of calendars out there that have this event on them. If they all had a reference to the original object, and the original object were mutable then these calendars wouldn't need to be updated because the object they were all pointing at would just have the new value. That poses a lot of problems with concurrency though, since if something is looking at that calendar and something about the event changes mid-way though, the person consuming that calendar could be left in an inconsistent state. These are side effects of mutating that object.

Since our hypothetical calendar event IS immutable though, we don't need to worry about changing things out from under people without them noticing, but what we DO have to worry about is how to update all of these calendars. In this case, it would be good to have the person 'subscribe' their calendar to the event. When the event changes, a new event can be pushed to those calendars. If those calendars are immutable too, then they will need to be recreated with the new event replacing the old one, too. If the list of subscribers to the event is immutable, a new subscriber list needs to be created any time someone new subscribes.

As you can see, having everything be immutable can clean up concurrency problems, but it can also get expensive. You can wind up having to create a lot of new objects just because one little thing changed. The key to using immutability well is knowing when to use it, and when to not. The event object is a very public detail and having it be immutable is probably good, so that you don't change things out from under people. The list of subscribers for the event can likely be kept private to the event or the event organizer, so it might make sense to keep that be mutable so that you're not doing a crazy amount of recreation of objects if you have a hot event. The calendars of people planning on attending the event could go either way, depending on what else the calendars are being used for.

It's one of those things where you have to be sound about paying attention to both object creation and consequences of change, and make a rational decision based on the balance of those two factors. If it's going to be expensive to keep creating new objects and it wouldn't be difficult to manage who is looking at the objects, it might be better to keep it mutable. If the key is avoiding side effects, and/or object creation isn't going to be relatively expensive, it should probably be immutable.

So, if you're running into situations where you're struggling with immutability, first make sure you're thinking of immutability correctly. Think about it like String, and how you operate on that. If you're already working in that right mental model, then it's time to start asking yourself if immutability is the right thing to be doing. If creating and replacing objects is painful, maybe immutability isn't right for that particular case.

2

Making some of your objects immutable is an architectural decision that should rarely be changed later, so I would not recommend that you start refactoring all of your stuff just because. You should also think about the disadvatages of immutability when changing your project. For example, immutability can cause severe performance problems if you have to recreate thousands of objects per second because you want to change them.

Telastyn already gave a good answer how to make things immutable. Most of the time you can make a mutable class immutable if you return a new object on every method call, e.g. like the standard String class in Java does it. Just remember that you should not use it blindly.

  • 2
    The performance of both mutability and immutability depends on the language. Functional language implementations are tuned assuming that you're going to generate a huge amount of garbage and that mutable references will be rare. Imperative language implementations will assume mutation is common. And if parallelism is an option, you're going to have a hard time exploiting it with mutability. – Doval Feb 21 '15 at 20:16
  • While that is mostly true, the original question implied that a functional language is not used. Ahmad was specifically asking about refactoring of an existing project. – TheBrain Feb 22 '15 at 21:02
  • 1
    Sure, but the way your answer is phrased makes it sound like immutability is risky in general. – Doval Feb 23 '15 at 12:26
0

Obvious answer is that you use constructors.

class A {
public:
   A(int a, int b) : a(a), b(b) {}
private:
   int a, b;
 };

If you need to change a or b -variables, the correct course of action is to create new object instead of adding set_a() or set_b() functions.

  • You mean no public variables or properties? – Ahmad Mar 1 '15 at 11:24

Not the answer you're looking for? Browse other questions tagged or ask your own question.