Announcement Announcement Module
Collapse
No announcement yet.
Rich Domain Model Q Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Rich Domain Model Q

    I went to a talk by Steven Devijver at the Spring One on Practical Rich Domain Models, and there he said automatically generating getters and setters wasn't a good idea.

    Seems like good advice to me, so I removed all my setters to see what code broke, and the biggest catastrophy was in my unit tests.

    So here comes my question: does anyone have any ideas how to write unit tests when you don't have setters? I.e. I am constructing my test object and I need to initialise it somehow. In the real world it would be done from the database, but I don't want to write integration tests.

    Ideas/comments?

    The best idea I came up with was making my setters protected and then writing test builder objects.

  • #2
    Originally posted by raining
    I went to a talk by Steven Devijver at the Spring One on Practical Rich Domain Models, and there he said automatically generating getters and setters wasn't a good idea.
    I agree with Steven. I'm currently working on a blog about this and I hope to finish it this weekend.

    So here comes my question: does anyone have any ideas how to write unit tests when you don't have setters? I.e. I am constructing my test object and I need to initialise it somehow. In the real world it would be done from the database, but I don't want to write integration tests.
    It isn't just done by the database, but also by 'state changing methods' like 'employee.fire'.

    The fire methods sets the fired date and also the salary (for example).

    If I want to test if an exception is thrown when a employee is fired for the second time (this isn't possible) I could do the following.

    Code:
    Employee employee = createEmployedEmployee();
    employee.fire(); //the employee doesn't work anymore for the company
    
    try{
        employee.fire();
        fail("IllegalStateException expected");
    }catch(IllegalStateException e){
        assertTrue(true);
    }
    If I want to check if the fired date is set, and the salary also, I could do the following:
    Code:
    Employee employee = createEmployedEmployee();
    employee.fire(); //the employee doesn't work anymore for the company
    assertEquals(new Date(),employee.getFiredDate());//this is just an example :)
    assertEquals(0,employee.getSalary());

    Comment


    • #3
      Thanks ... I'd really like to read your blog once it's done.
      My question is with the method createEmployedEmployee... how exactly do you create the Employee if you don't have any setters?

      Comment


      • #4
        Originally posted by raining
        Thanks ... I'd really like to read your blog once it's done.
        My question is with the method createEmployedEmployee... how exactly do you create the Employee if you don't have any setters?
        It depends.

        example:

        Employee employee = createNewEmployee("peter","veentjer");
        employee.startToWorkForCompany(someCompany);

        Comment


        • #5
          But what does the method createNewEmployee(String name, String surname) do?

          Code:
          Employee employee = new Employee();
          employee.setName(name);
          employee.setSurname(surname);
          or because setters aren't available ....

          Code:
          return new Employee(name, surname);
          I.e. construct a new domain object with the attributes needed to initialise it.

          Comment


          • #6
            Originally posted by raining
            But what does the method createNewEmployee(String name, String surname) do?

            Code:
            Employee employee = new Employee();
            employee.setName(name);
            employee.setSurname(surname);
            or because setters aren't available ....

            Code:
            return = new Employee(name, surname);
            I.e. construct a new domain object with the attributes needed to initialise it.
            Personally I like constructors (although they can be a pain in the ass if they are long).

            The definition of the Employee(name,surname) could be:
            creates a new unemployed Employee with the given name and surname.

            Now you know the exact state the object is in.

            Comment


            • #7
              What are the other options besides passing the parameters in the constructor ... remember that you don't have any setters, and I'm sure the Employee attributes are anything but private.

              Comment


              • #8
                Originally posted by raining
                What are the other options besides passing the parameters in the constructor
                I don't know. Exposing (all) properties is bad imho. And I also don't like non private access modifiers for my fields: you don't want a subclass screwing around with your fields. But I'm a very defensive programmer, other developers are less defensive.

                In some cases you can expose fields by setters, for example: name and surname, so:
                Code:
                Employee employee = new Employee();//an unemployed Employee
                employee.setName(...);
                employee.startToWorkForCompany(someCompany);

                Comment


                • #9
                  Cool thanks.... so the conclusion is that some initialising fields might have setters or might also be set in the constructor.

                  Sorry, just read my previous post and I meant to say that the Employee attributes are private, not anything but

                  Comment


                  • #10
                    Originally posted by raining
                    Cool thanks.... so the conclusion is that some initialising fields might have setters or might also be set in the constructor.
                    I would create setters for properties that are not related to any state in the object. Properties like address, emailaddress, name etc.

                    For properties like salary and fireDate I would only use 'state changing methods' like fire.

                    In some cases you need to expose internal state by setters. If the fire logic is very complex, or can't be logically modelled as part of employee (an Employee isn't going to fire himself, it is the task of the human resource manager) you could create a domain service (FireService/HumanResourceManager) where all logic is placed. This domain service needs access to the internals of your object and this makes your object vulnerable to violations in your class invariants (a fired employee with a salary != 0). So in some cases you need to.
                    Last edited by Alarmnummer; Jun 29th, 2006, 07:54 AM.

                    Comment


                    • #11
                      I absolutely agree that automatically adding getters/setters for all fields is just a bad thing. That being said, it seems to me that it'd be going too far toward the other extreme by automatically forbidding all the setters. If we all agree that some, if not most, objects in any domain model by their nature can never be immutable, why do we insist on making them so?

                      Comment


                      • #12
                        Originally posted by manifoldronin
                        I absolutely agree that automatically adding getters/setters for all fields is just a bad thing. That being said, it seems to me that it'd be going too far toward the other extreme by automatically forbidding all the setters. If we all agree that some, if not most, objects in any domain model by their nature can never be immutable, why do we insist on making them so?
                        Replacing setters (like setSalary and setFireDate) by business methods (like fire or hire) doesn't lead to immutable objects.

                        Comment


                        • #13
                          Originally posted by Alarmnummer
                          Replacing setters (like setSalary and setFireDate) by business methods (like fire or hire) doesn't lead to immutable objects.
                          Absolutely. My comment was directed to the OP's "I removed all the setters" part.

                          Comment


                          • #14
                            Originally posted by manifoldronin
                            Absolutely. My comment was directed to the OP's "I removed all the setters" part.
                            Do you have idead about packaging? Personally I prefer to package by functionality and not by position in one of the layers.

                            Comment


                            • #15
                              Originally posted by Alarmnummer
                              Do you have idead about packaging? Personally I prefer to package by functionality and not by position in one of the layers.
                              Me, too. Projects with packages like "controllers", "daos", "ejbs" are just depressing.

                              Comment

                              Working...
                              X