5

I need to model a very simple mobile object (Robot) on a rectangular grid. Its state is described by position (basically a pair of integers) and direction (e.g., N, E, S, W). It only has two methods (apart from constructor): it can move one step in its direction, or rotate by 90, 180 or 270 degrees.

Apart from the obvious performance issues and any language-specific considerations, what factors should I consider when deciding whether to make Robot instances mutable (methods modify state) or immutable (methods return a newly created robot with the new state)? Instances of this class will be used in various simulations (I intentionally omit the details to get a clearer understanding of overall principles).

(Edited to clarify) When I think of a robot, the natural picture in my mind is a movable thing, which would correspond to a mutable object. That said, it's not hard for me to overcome this mental association and think of robots as little marks on the grid that are created (and destroyed if no other reference points to them) every time they move. So I would not worry about what feels natural, and would just choose what works better code-wise.

I was planning to model position and direction as attributes of robot. Regardless of whether robot itself is immutable, I was planning to make the types of position and direction objects immutable just because it's more natural for me to think of them as such (e.g., when I talk about a "point on a grid", I imagine it remains in the same place forever; same for a "direction").

  • 1
    Think of it from a code perspective, not a real life perspective. Although OOP is great for replicating real world systems, attempting to replicate every concept usually isn't the most efficient. Do you want other types to mutate Robot objects? If they mutate the object, should other objects referencing that object notice the changed state? Maybe you should have both a mutable and immutable version (mutable could derive from immutable, same behaviors just without mutable ones), exposing the mutable type only where the object should be mutated. – Vince Emigh Nov 13 '16 at 17:57
  • 1
    Will these robot objects be accessed from several threads? – Gernot Nov 13 '16 at 18:07
  • @VinceEmigh This makes sense. That's exactly the type of considerations I'm looking for. – max Nov 13 '16 at 18:23
  • @Gernot A good point! I didn't think about it, but I assume immutable objects would be automatically thread-safe, while mutable objects would require highly complicated synchronization mechanism? – max Nov 13 '16 at 18:25
  • @max Yes, this was the intention of my question. Have a look at Bogdan's answer, it also covers this topic – Gernot Nov 13 '16 at 18:42
4

It only has two methods (apart from constructor): it can move one step in its direction, or rotate by 90, 180 or 270 degrees.

This is turn taking. It screams immutable. Why? Because time can be removed.

On the other hand, when I think of a robot, the natural picture in my mind is a movable thing, which would correspond to a mutable object.

When we watch movies we see movable things throughout. Yet each image is a static immovable thing. What it looks like and how it works don't have to be the same thing.

Being immutable has benefits beyond concurrency. It also comes at a cost. This choice has implications for time space trade offs, caching, and state validation.

Without knowing the details of your simulation I know enough about the benefits of immutable objects to encourage you to use as much of it as you can. When you've gone to far you'll know. It's when you haven't gone far enough that you get treated to nasty surprises.

4

These types of questions are hard to answer without knowing the whole context, but from your description I see the Robot as being a mutable object. You have one robot that moves across the grid, you don't have one robot that appears at a certain location and is destroyed on its old one.

The Robot has a position. This can be a tuple (immutable) or just two number properties on the robot. The position can be changed by a moveTo method on the robot. The robot has a direction. So these are states of the robot.

Apart from the obvious performance issues and any language-specific considerations, what factors should I consider when deciding whether to make Robot instances mutable (methods modify state) or immutable.

The only thing to consider is if in the simulations you run, the robot is used by multiple threads. If it is you need to synchronize access to its state or think about making it immutable.

  • Apart from multi threading context, what else would make you change your recommendation to an immutable object? – max Nov 13 '16 at 18:44
  • @max: Immutability and mutability have their pros and cons. They both behave well in some contexts and poorly in others. Like I said at the beginning of my answer, this is hard to answer without knowing the full context. You should analyze your problem, read on the pros and cons of immutability and mutability, then decide for yourself which solution works better in your case. If both solve the problem but you can't decide, then just go for the one that seems the simplest. – Bogdan Nov 13 '16 at 20:47
1

when I think of a robot, the natural picture in my mind is a movable thing, which would correspond to a mutable object ... it's not hard for me to overcome this mental association

It seems like you're trying to force immutability, rather than use it for a tool to solve a problem.

Immutable types with "mutable" methods

An immutable type with "mutable" methods raises a flag, and there's very few situations where it actually serves beneficial purpose. Other than those few situations, it usually causes problems/confusions (String being a good example, with beginners not understanding that toLowercase() actually creates a new object).

Your idea of Position being immutable due to it's static nature is a good idea, but that doesn't mean it should have methods that return new instances of Position.

Logical breakdown of your situation

Position objects should exist composed by some kind of Grid. When a Robot moves to a new position on the grid, the robot should be given a reference to that position.

If for some reason you want Robot to have it's own independent position which is subject to change, you should not consider it immutable, as the robot is not creating positions, it's simply adjusting it's position to match the target position.

Always think in "pros" and "cons"

Apart from the obvious performance issues

If you are aware there will be performance issues, you should definitely understand and weight the benefits gained from your decision. It sounds like you can't really find any, the only reasoning being "It's not hard to picture this scenario in my head". It's probably best to focus on the pros and cons of a certain design, rather than what best replicates the real world.

"Don't think of it from a real world perspective" was a bad choice of words. What I meant was "Don't let attempts at replicating the real world affect the manageability and performance of your software". Just because you can imagine it doesn't mean it's best for a software enviornment.

  • I edited my question to clarify the position / direction part; basically, I'm just confirming I agreed with you. – max Nov 13 '16 at 21:10
  • Can you copy to your answer your comment: Do you want other types to mutate Robot objects? If they mutate the object, should other objects referencing that object notice the changed state? Maybe you should have both a mutable and immutable version (mutable could derive from immutable, same behaviors just without mutable ones), exposing the mutable type only where the object should be mutated? Even if you don't elaborate any more, that comment is useful as is. – max Nov 17 '16 at 8:18
1

(This is originally intended for introducing immutability to science fiction readers, so it is written in a non-rigorous way.)

You can use immutable object if you need search-based motion planning.

In this design, the following is an immutable:

  • At time T,
  • The robot is at position X, Y,
  • Facing direction D.

There will be many instances of immutable objects in your search tree. But for each time T up to the present (i.e. past or present), there will be exactly one such instance that reflects the path of the robot's motion history. All other instances will be contemplation of what would happen if the robot had chosen to move in different ways at different time points.

The present time is T, therefore every instance having time greater than T is a contemplation, since that future time hasn't happened yet.

This gives you a parallel universe, speaking in a science-fiction sense.

An instance at time T+1 will need a parent link referring to a pre-existing instance at time T. This link explains how the robot could get to its state at T+1 by making a move from a previous position at T.

You can use this as a graph search, or for path-finding purpose.

1

In my humble opinion, in most cases we are not modeling real world, but dealing with real life problems. In this case, such "Robot" can be either an app to control a real robot, or an app to control a virtual robot character, but it can't be a real robot itself. That's why the question actually doesn't have an answer because it's missing context.

Based on different context, there can be different explanations. For example, if we are talking about a robot that can move or rotate inside a mobile app, we definitely would have different ways to implement it.

If we use MVVM pattern, Robot is mutable but passive:

  • Robot is a passive model, which has position and direction properties and no methods.
  • ViewModel owns one or more instances of Robots, and can move(robot) and/or rotate(robot, direction).
    • If operating robots are not the only work ViewModel does, a RobotOperator helper can handle tasks like move(robot) and/or rotate(robot, direction).
  • ViewModel.robots are rendered on View.

I'll ignore the details, but in MVC, Robot will be able to move and/or rotate on its own, and in functional programming each move/rotate is going to return a new instance with updated states.

I would say all of them makes sense, they are all valid design patterns and have pros and cons. Based on the scaling of your app, concurrency requirement, development budget and so on, the preferred choice would differ.

As a conclusion, I don't believe there's right or wrong for this question, just think it through and as long as your approach suits your business requirement it would be good.

  • I agree with your general idea of ignoring the real world, and focusing instead on what the software needs to do (requirements, performance, etc.). The 3 approaches you briefly outline also make sense. But could you add a little more about what the pros/cons are of these 3 approaches? – max Mar 5 at 7:51
  • That would be platform and implementation depend, for example iOS developers are moving away from MVC for years but it's not really MVCs fault, Apple just gave their UIViewControllers too many responsibilities. In general, it would be a bigger topic than mutability, so I'd prefer keep it short and sort of on topic (it's already a bit off). – superarts.org Mar 5 at 12:10
  • Platform and implementation dependent* – superarts.org Mar 6 at 5:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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