in reply to Re^11: Assignable Subroutines
in thread Assignable Subroutines

While I'm at it, a couple of questions. Where is this "no mutators" idea coming from? What exactly is the damage that results from having mutators?

I've read the Java world article and all it's saying is don't create public mutuators for fields that are for internal use only. Blindingly obvious advice but I can understand why it may have been needed. I imagine the sequence of events in Javaland to be

That last step would probably be performed by newer programmers, copying without understanding, seeing that public fields are not being used at all and that private + accessor seems to be "correct".

Replies are listed 'Best First'.
Re^13: Assignable Subroutines
by dragonchild (Archbishop) on Jan 27, 2005 at 18:20 UTC
    Why do you think you need to poke a value into a memory location like you're an ASM Programmer? Because, with a mutator, that's really what you're doing. You're not telling the object to do something and trusting it to accomplish the task you've set for it. You're pushing values into its head, then executing a series of statements that run based on the values you've shoved into its head. Which means you've broken encapsulation.

    No, not because you shoved values into the object's head. Because you had to know what values to shove into its head into order to make sure the series of statements you ran did what you wanted it to do.

    There is always a better way to write an object than to use mutators. Except, it takes more time in the design phase and Lord&Lady know that no-one ever has time to design.

    Being right, does not endow the right to be rude; politeness costs nothing.
    Being unknowing, is not the same as being stupid.
    Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence.
    Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.

      What do mean "like an ASM programmer". I'm talking about a fuly overridable way of setting things. I am trusting the object to do it. I know you're get at ask don't tell but what better way is there to ask the object "please update your salary field to $50000" than by saying
      $employee->setSalary(50000);
      or
      $employee->Salary = 50000;

      The whole problem here comes originally from people exposing highly interrelated fields as independently manipulable things when they shouldn't and in that case mutators are wrong. The whole idea is to be able to have invariants that are always true about an object and giving access to individual fields can sometimes allow things outside the object to leave the object in a state where the invariant is no longer true. I totally appreciate that. But sometimes objects have fields that are independent of all other fields and can be twiddled by anyone without breaking an invariant. There are only 2 choices for implementing these - direct field access or mutator and in most languages direct access is bad because it cannot be overridden in the future so you use a mutator.

        ... what better way is there to ask the object "please update your salary field to $50000" ...

        That statement is sidestepping the debate. Why are you setting the salary field to "$50000"? What is the thought process behind it? Why aren't you letting the object do more of the thinking?

        Let's explore this situation a little more. I can see three reasons why you would want to set the salary.

        1. You just hired someone and are setting their salary.

          This should be done as part of the initial creation of the Employee object. There should be a method that accepts a large number of parameters, presumably named and not positional, and will validate those parameters before accepting them.

        2. You just gave someone a raise.

          The object should be handling all the math, not you. You should be calling the giveRaise() method. That method should be able to accept a number or a percentage. That method will do all the bit-fiddling.

        3. You just promoted someone.

          The object should be handling this. There should be a givePromotion() method that, as one of its optional parameters, accepts a new salary value. That method will do all the bit-fiddling.

        Now, the object enforces the business rules of the HR department. You can't just walk into someone's cube and say "Hey, I decided to set your salary to $50000. Have a nice day!" and expect the HR department to be ok with it. (Depending on the prior salary, the employee might not be ok with it, either!)

        I am starting to become convinced that everytime someone says "I need a mutator here!", they're really saying "I haven't fully thought out my problem, but I know I can bruteforce it with a mutator!" I'm not saying that brute force is necessarily a "Bad Plan"™. I am saying that it's not good theoretical practice.

        Being right, does not endow the right to be rude; politeness costs nothing.
        Being unknowing, is not the same as being stupid.
        Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence.
        Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.

Re^13: Assignable Subroutines
by hardburn (Abbot) on Jan 27, 2005 at 18:22 UTC

    The "no trivial mutators" idea comes from the fact that if you wanted a struct, then you should have used a struct and left the OO baggage behind.

    Java gets stuck on the fact that everything has to be an object, which means that when a struct really is the best way to do something (as it is in many simple programs), you still have to define it in terms of an object. That's an inheirent difficulty in single-paradigm languages.

    We don't have that problem in Perl, but it's still good advice that if you're going to trouble yourself with OO, then you should really do OO. I'm not going to demand that you apply OO everywhere, only that if you use it, you use it correctly. Bad OO is often worse than not using it in the first place.

    "There is no shame in being self-taught, only in not trying to learn in the first place." -- Atrus, Myst: The Book of D'ni.

      Why should I have to choose between struct and object? It's incredibly useful to have both and I still haven't seen an example of anything bad happening when that is done. Look, for example, at Haskell, which uses multiple dispatch, where not only structs have object behaviours but even scalars (which are equivalent to structs with a single field) have too.

        You end up having insufficient checks in the object. Actually, I think dragonchild's giveRaise() and givePromotion() methods are better than my solution (these two methods could potentially be implemented with Effects, though I'm not sure why you would want to). In both cases, it's clear from the method name alone what is going to be done.

        Further, there are two different reasons given here for changing the salary of an existing employee, and they both likely have completely different buisness rules behind them. With dragonchild's method, those buisness rules will be completely seperated by two different methods.

        The Effect^H^H^H Visitor Pattern is still applicable in some applications, such as implementing the massive flexibility required by my game framework.

        "There is no shame in being self-taught, only in not trying to learn in the first place." -- Atrus, Myst: The Book of D'ni.