Is “avoid yoyo problem” a reason to allow “primitive obsession”?












4















According to When is Primitive Obsession not a code smell?, I should create a ZipCode object to represent zip code instead of a String object.



However, in my experience, I prefer to see



public class Address{
public String zipCode;
}


instead of



public class Address{
public ZipCode zipCode;
}


because I think the latter one requires me to move to the ZipCode class to understand the program.



And I believe I need to move between many class to see the definition if every primitive data fields were replaced by a class, which feels as if suffering from yo-yo problem.



So I would like to move the ZipCode methods into a new class, eg:



old:



public class ZipCode{
public boolean validate(String zipCode){
}
}


new:



public class ZipCodeHelper{
public static boolean validate(String zipCode){
}
}


so that only the one who needs to validate the zip code would depend on the ZipCodeHelper class .And I found another "benefit" of keep primitive obsession: it keeps the class looks like its serialized form, if any, for example : an address table with string column zipCode.



My question is, is "avoid yoyo problem" (move between class definitions) a reason to allow "primitive obsession"?










share|improve this question



























    4















    According to When is Primitive Obsession not a code smell?, I should create a ZipCode object to represent zip code instead of a String object.



    However, in my experience, I prefer to see



    public class Address{
    public String zipCode;
    }


    instead of



    public class Address{
    public ZipCode zipCode;
    }


    because I think the latter one requires me to move to the ZipCode class to understand the program.



    And I believe I need to move between many class to see the definition if every primitive data fields were replaced by a class, which feels as if suffering from yo-yo problem.



    So I would like to move the ZipCode methods into a new class, eg:



    old:



    public class ZipCode{
    public boolean validate(String zipCode){
    }
    }


    new:



    public class ZipCodeHelper{
    public static boolean validate(String zipCode){
    }
    }


    so that only the one who needs to validate the zip code would depend on the ZipCodeHelper class .And I found another "benefit" of keep primitive obsession: it keeps the class looks like its serialized form, if any, for example : an address table with string column zipCode.



    My question is, is "avoid yoyo problem" (move between class definitions) a reason to allow "primitive obsession"?










    share|improve this question

























      4












      4








      4








      According to When is Primitive Obsession not a code smell?, I should create a ZipCode object to represent zip code instead of a String object.



      However, in my experience, I prefer to see



      public class Address{
      public String zipCode;
      }


      instead of



      public class Address{
      public ZipCode zipCode;
      }


      because I think the latter one requires me to move to the ZipCode class to understand the program.



      And I believe I need to move between many class to see the definition if every primitive data fields were replaced by a class, which feels as if suffering from yo-yo problem.



      So I would like to move the ZipCode methods into a new class, eg:



      old:



      public class ZipCode{
      public boolean validate(String zipCode){
      }
      }


      new:



      public class ZipCodeHelper{
      public static boolean validate(String zipCode){
      }
      }


      so that only the one who needs to validate the zip code would depend on the ZipCodeHelper class .And I found another "benefit" of keep primitive obsession: it keeps the class looks like its serialized form, if any, for example : an address table with string column zipCode.



      My question is, is "avoid yoyo problem" (move between class definitions) a reason to allow "primitive obsession"?










      share|improve this question














      According to When is Primitive Obsession not a code smell?, I should create a ZipCode object to represent zip code instead of a String object.



      However, in my experience, I prefer to see



      public class Address{
      public String zipCode;
      }


      instead of



      public class Address{
      public ZipCode zipCode;
      }


      because I think the latter one requires me to move to the ZipCode class to understand the program.



      And I believe I need to move between many class to see the definition if every primitive data fields were replaced by a class, which feels as if suffering from yo-yo problem.



      So I would like to move the ZipCode methods into a new class, eg:



      old:



      public class ZipCode{
      public boolean validate(String zipCode){
      }
      }


      new:



      public class ZipCodeHelper{
      public static boolean validate(String zipCode){
      }
      }


      so that only the one who needs to validate the zip code would depend on the ZipCodeHelper class .And I found another "benefit" of keep primitive obsession: it keeps the class looks like its serialized form, if any, for example : an address table with string column zipCode.



      My question is, is "avoid yoyo problem" (move between class definitions) a reason to allow "primitive obsession"?







      object-oriented coding-style






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked 6 hours ago









      mmmaaammmaaa

      2,21231319




      2,21231319






















          3 Answers
          3






          active

          oldest

          votes


















          16














          The assumption is that you don't need to yo-yo to the ZipCode class to understand the Address class. If ZipCode is well-designed it should be obvious what it does just by reading the Address class.



          Programs are not read end-to-end - typically programs are far too complex to make this possible. You cannot keep all the code in a program in your mind at the same time. So we use abstractions and encapsulations to "chunk" the program into meaningful units, so you can look at one part of the program (say the Address class) without having to read all code it depends on.



          For example I'm sure you don't yo-yo into reading the source code for String every time you encounter String in code.



          Renaming the class from ZipCode to ZipCodeHelper suggest there now is two separate concepts: a zip code and a zip code helper. So twice as complex. And now the type system cannot help you distinguish between an arbitrary string and a valid zip code since they have the same type. This is where "obsession" is appropriate: You are suggesting a more complex and less safe alternative just because you want to avoid a simple wrapper type around a primitive.



          Using a primitive is IMHO justified in the cases where there is no validation or other logic depending on this particular type. But as soon as you add any logic, it is much simpler if this logic is encapsulated with the type.



          As for serialization I think it sounds like a limitation in the framework you are using. Surely you should be able to serialize a ZipCode to a string or map it to a column in a database.






          share|improve this answer

































            4














            If can do:



            new ZipCode("totally invalid zip code");


            And the constructor for ZipCode does:



            ZipCodeHelper.validate("totally invalid zip code");


            Then you've broken encapsulation, and added a pretty silly dependency to the ZipCode class. If the constructor doesn't call ZipCodeHelper.validate(...) then you have isolated logic in its own island without actually enforcing it. You can create invalid zip codes.



            The validate method should be a static method on the ZipCode class. Now the knowledge of a "valid" zip code is bundled together with the ZipCode class. Given that your code examples look like Java, the constructor of ZipCode should throw an exception if an incorrect format is given:



            public class ZipCode {
            private String zipCode;

            public ZipCode(string zipCode) {
            if (!validate(zipCode))
            throw new IllegalFormatException("Invalid zip code");

            this.zipCode = zipCode;
            }

            public static bool validate(String zipCode) {
            // logic to check format
            }

            @Override
            public String toString() {
            return zipCode;
            }
            }


            The constructor checks the format and throws an exception, thereby preventing invalid zip codes from being created, and the static validate method is available to other code so the logic of checking the format is encapsulated in the ZipCode class.



            There is no "yo-yo" in this variant of the ZipCode class. It's just called proper Object Oriented Programming.





            We are also going to ignore internationalization here, which may necessitate another class called ZipCodeFormat or PostalService (e.g. PostalService.isValidPostalCode(...), PostalService.parsePostalCode(...), etc.).






            share|improve this answer































              0














              The ZipCode abstraction could only make sense if your Address class did not also have a TownName property. Otherwise, you have half an abstraction: the zip code designates the town, but these two related bits of information are found in different classes. It doesn't quite make sense.



              However, even then, it's still not a correct application (or rather solution to) primitive obsession; which, as I understand it, mainly focuses on two things:




              1. Using primitives as the input (or even output) values of a method, especially when a collection of primitives is needed.

              2. Classes that grow extra properties over time without ever reconsidering whether some of these should be grouped into a subclass of their own.


              Your case is neither. An address is a well-defined concept with clearly necessary properties (street, number, zip, town, state, country). There is little to no reason to break up this data as it has a single responsibility: designate a location on Earth. An address requires all of these fields in order to be meaningful. Half an address is pointless.



              This is how you know that you don't need to subdivide any further: breaking it down any further would detract from the functional intention of the Address class. Similarly, you don't need a Name subclass to be used in the Personclass, unless Name (without a person attached) is a meaningful concept in your domain. Which it (usually) isn't. Names are used for identifying people, they usually have no value on their own.






              share|improve this answer
























              • I disagree. In some cases it makes perfect sense to add a Name type to a Person class, if there are additional business rules attached to a Name. You wouldn't want to handle the rules for names in the Person class. Same for validating ZipCodes, it makes perfect sense to make a ZipCode type inside an Address class.

                – Rik D
                3 hours ago











              • @RikD: From the answer: "you don't need a Name subclass to be used in the Person class, unless Name (without a person attached) is a meaningful concept in your domain." When you have custom validation for the names, the name has then become a meaningful concept in your domain; which I explicitly mentioned as a valid use case for using a subtype. Secondly, for the zipcode validation, you're introducing additional assumptions, such as zip codes needing to follow a given country's format. You're broaching a topic that's much broader than the intent of OP's question.

                – Flater
                2 hours ago













              • I disagreed with part of your post, not everything. We're on the same page when it comes to the Person class. You seem to argue that ZipCode is not a good abstraction in an Address class; I disagree with that. I'm not making assumptions; OP clearly states he wants to validate a ZipCode, noone (but you) is talking about other countries. In my opinion, the validation of that ZipCode belongs in the ZipCode class; if you want to validate it against a Town, the validate method in de ZipCode class should have an argument for TownName (OP didn't mention this either).

                – Rik D
                2 hours ago











              • @RikD: Zip code assumes United States Postal Service, and you can derive the name of the town from the zip code. Cities can have multiple zip codes, but each zip code is only tied to 1 city. It actually makes sense to get the city and state from the zip code (in the USA at least).

                – Greg Burghardt
                16 mins ago











              Your Answer








              StackExchange.ready(function() {
              var channelOptions = {
              tags: "".split(" "),
              id: "131"
              };
              initTagRenderer("".split(" "), "".split(" "), channelOptions);

              StackExchange.using("externalEditor", function() {
              // Have to fire editor after snippets, if snippets enabled
              if (StackExchange.settings.snippets.snippetsEnabled) {
              StackExchange.using("snippets", function() {
              createEditor();
              });
              }
              else {
              createEditor();
              }
              });

              function createEditor() {
              StackExchange.prepareEditor({
              heartbeatType: 'answer',
              autoActivateHeartbeat: false,
              convertImagesToLinks: false,
              noModals: true,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: null,
              bindNavPrevention: true,
              postfix: "",
              imageUploader: {
              brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
              contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
              allowUrls: true
              },
              onDemand: true,
              discardSelector: ".discard-answer"
              ,immediatelyShowMarkdownHelp:true
              });


              }
              });














              draft saved

              draft discarded


















              StackExchange.ready(
              function () {
              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsoftwareengineering.stackexchange.com%2fquestions%2f386042%2fis-avoid-yoyo-problem-a-reason-to-allow-primitive-obsession%23new-answer', 'question_page');
              }
              );

              Post as a guest















              Required, but never shown

























              3 Answers
              3






              active

              oldest

              votes








              3 Answers
              3






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes









              16














              The assumption is that you don't need to yo-yo to the ZipCode class to understand the Address class. If ZipCode is well-designed it should be obvious what it does just by reading the Address class.



              Programs are not read end-to-end - typically programs are far too complex to make this possible. You cannot keep all the code in a program in your mind at the same time. So we use abstractions and encapsulations to "chunk" the program into meaningful units, so you can look at one part of the program (say the Address class) without having to read all code it depends on.



              For example I'm sure you don't yo-yo into reading the source code for String every time you encounter String in code.



              Renaming the class from ZipCode to ZipCodeHelper suggest there now is two separate concepts: a zip code and a zip code helper. So twice as complex. And now the type system cannot help you distinguish between an arbitrary string and a valid zip code since they have the same type. This is where "obsession" is appropriate: You are suggesting a more complex and less safe alternative just because you want to avoid a simple wrapper type around a primitive.



              Using a primitive is IMHO justified in the cases where there is no validation or other logic depending on this particular type. But as soon as you add any logic, it is much simpler if this logic is encapsulated with the type.



              As for serialization I think it sounds like a limitation in the framework you are using. Surely you should be able to serialize a ZipCode to a string or map it to a column in a database.






              share|improve this answer






























                16














                The assumption is that you don't need to yo-yo to the ZipCode class to understand the Address class. If ZipCode is well-designed it should be obvious what it does just by reading the Address class.



                Programs are not read end-to-end - typically programs are far too complex to make this possible. You cannot keep all the code in a program in your mind at the same time. So we use abstractions and encapsulations to "chunk" the program into meaningful units, so you can look at one part of the program (say the Address class) without having to read all code it depends on.



                For example I'm sure you don't yo-yo into reading the source code for String every time you encounter String in code.



                Renaming the class from ZipCode to ZipCodeHelper suggest there now is two separate concepts: a zip code and a zip code helper. So twice as complex. And now the type system cannot help you distinguish between an arbitrary string and a valid zip code since they have the same type. This is where "obsession" is appropriate: You are suggesting a more complex and less safe alternative just because you want to avoid a simple wrapper type around a primitive.



                Using a primitive is IMHO justified in the cases where there is no validation or other logic depending on this particular type. But as soon as you add any logic, it is much simpler if this logic is encapsulated with the type.



                As for serialization I think it sounds like a limitation in the framework you are using. Surely you should be able to serialize a ZipCode to a string or map it to a column in a database.






                share|improve this answer




























                  16












                  16








                  16







                  The assumption is that you don't need to yo-yo to the ZipCode class to understand the Address class. If ZipCode is well-designed it should be obvious what it does just by reading the Address class.



                  Programs are not read end-to-end - typically programs are far too complex to make this possible. You cannot keep all the code in a program in your mind at the same time. So we use abstractions and encapsulations to "chunk" the program into meaningful units, so you can look at one part of the program (say the Address class) without having to read all code it depends on.



                  For example I'm sure you don't yo-yo into reading the source code for String every time you encounter String in code.



                  Renaming the class from ZipCode to ZipCodeHelper suggest there now is two separate concepts: a zip code and a zip code helper. So twice as complex. And now the type system cannot help you distinguish between an arbitrary string and a valid zip code since they have the same type. This is where "obsession" is appropriate: You are suggesting a more complex and less safe alternative just because you want to avoid a simple wrapper type around a primitive.



                  Using a primitive is IMHO justified in the cases where there is no validation or other logic depending on this particular type. But as soon as you add any logic, it is much simpler if this logic is encapsulated with the type.



                  As for serialization I think it sounds like a limitation in the framework you are using. Surely you should be able to serialize a ZipCode to a string or map it to a column in a database.






                  share|improve this answer















                  The assumption is that you don't need to yo-yo to the ZipCode class to understand the Address class. If ZipCode is well-designed it should be obvious what it does just by reading the Address class.



                  Programs are not read end-to-end - typically programs are far too complex to make this possible. You cannot keep all the code in a program in your mind at the same time. So we use abstractions and encapsulations to "chunk" the program into meaningful units, so you can look at one part of the program (say the Address class) without having to read all code it depends on.



                  For example I'm sure you don't yo-yo into reading the source code for String every time you encounter String in code.



                  Renaming the class from ZipCode to ZipCodeHelper suggest there now is two separate concepts: a zip code and a zip code helper. So twice as complex. And now the type system cannot help you distinguish between an arbitrary string and a valid zip code since they have the same type. This is where "obsession" is appropriate: You are suggesting a more complex and less safe alternative just because you want to avoid a simple wrapper type around a primitive.



                  Using a primitive is IMHO justified in the cases where there is no validation or other logic depending on this particular type. But as soon as you add any logic, it is much simpler if this logic is encapsulated with the type.



                  As for serialization I think it sounds like a limitation in the framework you are using. Surely you should be able to serialize a ZipCode to a string or map it to a column in a database.







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited 3 hours ago









                  Rik D

                  16115




                  16115










                  answered 5 hours ago









                  JacquesBJacquesB

                  42k1687124




                  42k1687124

























                      4














                      If can do:



                      new ZipCode("totally invalid zip code");


                      And the constructor for ZipCode does:



                      ZipCodeHelper.validate("totally invalid zip code");


                      Then you've broken encapsulation, and added a pretty silly dependency to the ZipCode class. If the constructor doesn't call ZipCodeHelper.validate(...) then you have isolated logic in its own island without actually enforcing it. You can create invalid zip codes.



                      The validate method should be a static method on the ZipCode class. Now the knowledge of a "valid" zip code is bundled together with the ZipCode class. Given that your code examples look like Java, the constructor of ZipCode should throw an exception if an incorrect format is given:



                      public class ZipCode {
                      private String zipCode;

                      public ZipCode(string zipCode) {
                      if (!validate(zipCode))
                      throw new IllegalFormatException("Invalid zip code");

                      this.zipCode = zipCode;
                      }

                      public static bool validate(String zipCode) {
                      // logic to check format
                      }

                      @Override
                      public String toString() {
                      return zipCode;
                      }
                      }


                      The constructor checks the format and throws an exception, thereby preventing invalid zip codes from being created, and the static validate method is available to other code so the logic of checking the format is encapsulated in the ZipCode class.



                      There is no "yo-yo" in this variant of the ZipCode class. It's just called proper Object Oriented Programming.





                      We are also going to ignore internationalization here, which may necessitate another class called ZipCodeFormat or PostalService (e.g. PostalService.isValidPostalCode(...), PostalService.parsePostalCode(...), etc.).






                      share|improve this answer




























                        4














                        If can do:



                        new ZipCode("totally invalid zip code");


                        And the constructor for ZipCode does:



                        ZipCodeHelper.validate("totally invalid zip code");


                        Then you've broken encapsulation, and added a pretty silly dependency to the ZipCode class. If the constructor doesn't call ZipCodeHelper.validate(...) then you have isolated logic in its own island without actually enforcing it. You can create invalid zip codes.



                        The validate method should be a static method on the ZipCode class. Now the knowledge of a "valid" zip code is bundled together with the ZipCode class. Given that your code examples look like Java, the constructor of ZipCode should throw an exception if an incorrect format is given:



                        public class ZipCode {
                        private String zipCode;

                        public ZipCode(string zipCode) {
                        if (!validate(zipCode))
                        throw new IllegalFormatException("Invalid zip code");

                        this.zipCode = zipCode;
                        }

                        public static bool validate(String zipCode) {
                        // logic to check format
                        }

                        @Override
                        public String toString() {
                        return zipCode;
                        }
                        }


                        The constructor checks the format and throws an exception, thereby preventing invalid zip codes from being created, and the static validate method is available to other code so the logic of checking the format is encapsulated in the ZipCode class.



                        There is no "yo-yo" in this variant of the ZipCode class. It's just called proper Object Oriented Programming.





                        We are also going to ignore internationalization here, which may necessitate another class called ZipCodeFormat or PostalService (e.g. PostalService.isValidPostalCode(...), PostalService.parsePostalCode(...), etc.).






                        share|improve this answer


























                          4












                          4








                          4







                          If can do:



                          new ZipCode("totally invalid zip code");


                          And the constructor for ZipCode does:



                          ZipCodeHelper.validate("totally invalid zip code");


                          Then you've broken encapsulation, and added a pretty silly dependency to the ZipCode class. If the constructor doesn't call ZipCodeHelper.validate(...) then you have isolated logic in its own island without actually enforcing it. You can create invalid zip codes.



                          The validate method should be a static method on the ZipCode class. Now the knowledge of a "valid" zip code is bundled together with the ZipCode class. Given that your code examples look like Java, the constructor of ZipCode should throw an exception if an incorrect format is given:



                          public class ZipCode {
                          private String zipCode;

                          public ZipCode(string zipCode) {
                          if (!validate(zipCode))
                          throw new IllegalFormatException("Invalid zip code");

                          this.zipCode = zipCode;
                          }

                          public static bool validate(String zipCode) {
                          // logic to check format
                          }

                          @Override
                          public String toString() {
                          return zipCode;
                          }
                          }


                          The constructor checks the format and throws an exception, thereby preventing invalid zip codes from being created, and the static validate method is available to other code so the logic of checking the format is encapsulated in the ZipCode class.



                          There is no "yo-yo" in this variant of the ZipCode class. It's just called proper Object Oriented Programming.





                          We are also going to ignore internationalization here, which may necessitate another class called ZipCodeFormat or PostalService (e.g. PostalService.isValidPostalCode(...), PostalService.parsePostalCode(...), etc.).






                          share|improve this answer













                          If can do:



                          new ZipCode("totally invalid zip code");


                          And the constructor for ZipCode does:



                          ZipCodeHelper.validate("totally invalid zip code");


                          Then you've broken encapsulation, and added a pretty silly dependency to the ZipCode class. If the constructor doesn't call ZipCodeHelper.validate(...) then you have isolated logic in its own island without actually enforcing it. You can create invalid zip codes.



                          The validate method should be a static method on the ZipCode class. Now the knowledge of a "valid" zip code is bundled together with the ZipCode class. Given that your code examples look like Java, the constructor of ZipCode should throw an exception if an incorrect format is given:



                          public class ZipCode {
                          private String zipCode;

                          public ZipCode(string zipCode) {
                          if (!validate(zipCode))
                          throw new IllegalFormatException("Invalid zip code");

                          this.zipCode = zipCode;
                          }

                          public static bool validate(String zipCode) {
                          // logic to check format
                          }

                          @Override
                          public String toString() {
                          return zipCode;
                          }
                          }


                          The constructor checks the format and throws an exception, thereby preventing invalid zip codes from being created, and the static validate method is available to other code so the logic of checking the format is encapsulated in the ZipCode class.



                          There is no "yo-yo" in this variant of the ZipCode class. It's just called proper Object Oriented Programming.





                          We are also going to ignore internationalization here, which may necessitate another class called ZipCodeFormat or PostalService (e.g. PostalService.isValidPostalCode(...), PostalService.parsePostalCode(...), etc.).







                          share|improve this answer












                          share|improve this answer



                          share|improve this answer










                          answered 35 mins ago









                          Greg BurghardtGreg Burghardt

                          12.4k42856




                          12.4k42856























                              0














                              The ZipCode abstraction could only make sense if your Address class did not also have a TownName property. Otherwise, you have half an abstraction: the zip code designates the town, but these two related bits of information are found in different classes. It doesn't quite make sense.



                              However, even then, it's still not a correct application (or rather solution to) primitive obsession; which, as I understand it, mainly focuses on two things:




                              1. Using primitives as the input (or even output) values of a method, especially when a collection of primitives is needed.

                              2. Classes that grow extra properties over time without ever reconsidering whether some of these should be grouped into a subclass of their own.


                              Your case is neither. An address is a well-defined concept with clearly necessary properties (street, number, zip, town, state, country). There is little to no reason to break up this data as it has a single responsibility: designate a location on Earth. An address requires all of these fields in order to be meaningful. Half an address is pointless.



                              This is how you know that you don't need to subdivide any further: breaking it down any further would detract from the functional intention of the Address class. Similarly, you don't need a Name subclass to be used in the Personclass, unless Name (without a person attached) is a meaningful concept in your domain. Which it (usually) isn't. Names are used for identifying people, they usually have no value on their own.






                              share|improve this answer
























                              • I disagree. In some cases it makes perfect sense to add a Name type to a Person class, if there are additional business rules attached to a Name. You wouldn't want to handle the rules for names in the Person class. Same for validating ZipCodes, it makes perfect sense to make a ZipCode type inside an Address class.

                                – Rik D
                                3 hours ago











                              • @RikD: From the answer: "you don't need a Name subclass to be used in the Person class, unless Name (without a person attached) is a meaningful concept in your domain." When you have custom validation for the names, the name has then become a meaningful concept in your domain; which I explicitly mentioned as a valid use case for using a subtype. Secondly, for the zipcode validation, you're introducing additional assumptions, such as zip codes needing to follow a given country's format. You're broaching a topic that's much broader than the intent of OP's question.

                                – Flater
                                2 hours ago













                              • I disagreed with part of your post, not everything. We're on the same page when it comes to the Person class. You seem to argue that ZipCode is not a good abstraction in an Address class; I disagree with that. I'm not making assumptions; OP clearly states he wants to validate a ZipCode, noone (but you) is talking about other countries. In my opinion, the validation of that ZipCode belongs in the ZipCode class; if you want to validate it against a Town, the validate method in de ZipCode class should have an argument for TownName (OP didn't mention this either).

                                – Rik D
                                2 hours ago











                              • @RikD: Zip code assumes United States Postal Service, and you can derive the name of the town from the zip code. Cities can have multiple zip codes, but each zip code is only tied to 1 city. It actually makes sense to get the city and state from the zip code (in the USA at least).

                                – Greg Burghardt
                                16 mins ago
















                              0














                              The ZipCode abstraction could only make sense if your Address class did not also have a TownName property. Otherwise, you have half an abstraction: the zip code designates the town, but these two related bits of information are found in different classes. It doesn't quite make sense.



                              However, even then, it's still not a correct application (or rather solution to) primitive obsession; which, as I understand it, mainly focuses on two things:




                              1. Using primitives as the input (or even output) values of a method, especially when a collection of primitives is needed.

                              2. Classes that grow extra properties over time without ever reconsidering whether some of these should be grouped into a subclass of their own.


                              Your case is neither. An address is a well-defined concept with clearly necessary properties (street, number, zip, town, state, country). There is little to no reason to break up this data as it has a single responsibility: designate a location on Earth. An address requires all of these fields in order to be meaningful. Half an address is pointless.



                              This is how you know that you don't need to subdivide any further: breaking it down any further would detract from the functional intention of the Address class. Similarly, you don't need a Name subclass to be used in the Personclass, unless Name (without a person attached) is a meaningful concept in your domain. Which it (usually) isn't. Names are used for identifying people, they usually have no value on their own.






                              share|improve this answer
























                              • I disagree. In some cases it makes perfect sense to add a Name type to a Person class, if there are additional business rules attached to a Name. You wouldn't want to handle the rules for names in the Person class. Same for validating ZipCodes, it makes perfect sense to make a ZipCode type inside an Address class.

                                – Rik D
                                3 hours ago











                              • @RikD: From the answer: "you don't need a Name subclass to be used in the Person class, unless Name (without a person attached) is a meaningful concept in your domain." When you have custom validation for the names, the name has then become a meaningful concept in your domain; which I explicitly mentioned as a valid use case for using a subtype. Secondly, for the zipcode validation, you're introducing additional assumptions, such as zip codes needing to follow a given country's format. You're broaching a topic that's much broader than the intent of OP's question.

                                – Flater
                                2 hours ago













                              • I disagreed with part of your post, not everything. We're on the same page when it comes to the Person class. You seem to argue that ZipCode is not a good abstraction in an Address class; I disagree with that. I'm not making assumptions; OP clearly states he wants to validate a ZipCode, noone (but you) is talking about other countries. In my opinion, the validation of that ZipCode belongs in the ZipCode class; if you want to validate it against a Town, the validate method in de ZipCode class should have an argument for TownName (OP didn't mention this either).

                                – Rik D
                                2 hours ago











                              • @RikD: Zip code assumes United States Postal Service, and you can derive the name of the town from the zip code. Cities can have multiple zip codes, but each zip code is only tied to 1 city. It actually makes sense to get the city and state from the zip code (in the USA at least).

                                – Greg Burghardt
                                16 mins ago














                              0












                              0








                              0







                              The ZipCode abstraction could only make sense if your Address class did not also have a TownName property. Otherwise, you have half an abstraction: the zip code designates the town, but these two related bits of information are found in different classes. It doesn't quite make sense.



                              However, even then, it's still not a correct application (or rather solution to) primitive obsession; which, as I understand it, mainly focuses on two things:




                              1. Using primitives as the input (or even output) values of a method, especially when a collection of primitives is needed.

                              2. Classes that grow extra properties over time without ever reconsidering whether some of these should be grouped into a subclass of their own.


                              Your case is neither. An address is a well-defined concept with clearly necessary properties (street, number, zip, town, state, country). There is little to no reason to break up this data as it has a single responsibility: designate a location on Earth. An address requires all of these fields in order to be meaningful. Half an address is pointless.



                              This is how you know that you don't need to subdivide any further: breaking it down any further would detract from the functional intention of the Address class. Similarly, you don't need a Name subclass to be used in the Personclass, unless Name (without a person attached) is a meaningful concept in your domain. Which it (usually) isn't. Names are used for identifying people, they usually have no value on their own.






                              share|improve this answer













                              The ZipCode abstraction could only make sense if your Address class did not also have a TownName property. Otherwise, you have half an abstraction: the zip code designates the town, but these two related bits of information are found in different classes. It doesn't quite make sense.



                              However, even then, it's still not a correct application (or rather solution to) primitive obsession; which, as I understand it, mainly focuses on two things:




                              1. Using primitives as the input (or even output) values of a method, especially when a collection of primitives is needed.

                              2. Classes that grow extra properties over time without ever reconsidering whether some of these should be grouped into a subclass of their own.


                              Your case is neither. An address is a well-defined concept with clearly necessary properties (street, number, zip, town, state, country). There is little to no reason to break up this data as it has a single responsibility: designate a location on Earth. An address requires all of these fields in order to be meaningful. Half an address is pointless.



                              This is how you know that you don't need to subdivide any further: breaking it down any further would detract from the functional intention of the Address class. Similarly, you don't need a Name subclass to be used in the Personclass, unless Name (without a person attached) is a meaningful concept in your domain. Which it (usually) isn't. Names are used for identifying people, they usually have no value on their own.







                              share|improve this answer












                              share|improve this answer



                              share|improve this answer










                              answered 5 hours ago









                              FlaterFlater

                              6,94821323




                              6,94821323













                              • I disagree. In some cases it makes perfect sense to add a Name type to a Person class, if there are additional business rules attached to a Name. You wouldn't want to handle the rules for names in the Person class. Same for validating ZipCodes, it makes perfect sense to make a ZipCode type inside an Address class.

                                – Rik D
                                3 hours ago











                              • @RikD: From the answer: "you don't need a Name subclass to be used in the Person class, unless Name (without a person attached) is a meaningful concept in your domain." When you have custom validation for the names, the name has then become a meaningful concept in your domain; which I explicitly mentioned as a valid use case for using a subtype. Secondly, for the zipcode validation, you're introducing additional assumptions, such as zip codes needing to follow a given country's format. You're broaching a topic that's much broader than the intent of OP's question.

                                – Flater
                                2 hours ago













                              • I disagreed with part of your post, not everything. We're on the same page when it comes to the Person class. You seem to argue that ZipCode is not a good abstraction in an Address class; I disagree with that. I'm not making assumptions; OP clearly states he wants to validate a ZipCode, noone (but you) is talking about other countries. In my opinion, the validation of that ZipCode belongs in the ZipCode class; if you want to validate it against a Town, the validate method in de ZipCode class should have an argument for TownName (OP didn't mention this either).

                                – Rik D
                                2 hours ago











                              • @RikD: Zip code assumes United States Postal Service, and you can derive the name of the town from the zip code. Cities can have multiple zip codes, but each zip code is only tied to 1 city. It actually makes sense to get the city and state from the zip code (in the USA at least).

                                – Greg Burghardt
                                16 mins ago



















                              • I disagree. In some cases it makes perfect sense to add a Name type to a Person class, if there are additional business rules attached to a Name. You wouldn't want to handle the rules for names in the Person class. Same for validating ZipCodes, it makes perfect sense to make a ZipCode type inside an Address class.

                                – Rik D
                                3 hours ago











                              • @RikD: From the answer: "you don't need a Name subclass to be used in the Person class, unless Name (without a person attached) is a meaningful concept in your domain." When you have custom validation for the names, the name has then become a meaningful concept in your domain; which I explicitly mentioned as a valid use case for using a subtype. Secondly, for the zipcode validation, you're introducing additional assumptions, such as zip codes needing to follow a given country's format. You're broaching a topic that's much broader than the intent of OP's question.

                                – Flater
                                2 hours ago













                              • I disagreed with part of your post, not everything. We're on the same page when it comes to the Person class. You seem to argue that ZipCode is not a good abstraction in an Address class; I disagree with that. I'm not making assumptions; OP clearly states he wants to validate a ZipCode, noone (but you) is talking about other countries. In my opinion, the validation of that ZipCode belongs in the ZipCode class; if you want to validate it against a Town, the validate method in de ZipCode class should have an argument for TownName (OP didn't mention this either).

                                – Rik D
                                2 hours ago











                              • @RikD: Zip code assumes United States Postal Service, and you can derive the name of the town from the zip code. Cities can have multiple zip codes, but each zip code is only tied to 1 city. It actually makes sense to get the city and state from the zip code (in the USA at least).

                                – Greg Burghardt
                                16 mins ago

















                              I disagree. In some cases it makes perfect sense to add a Name type to a Person class, if there are additional business rules attached to a Name. You wouldn't want to handle the rules for names in the Person class. Same for validating ZipCodes, it makes perfect sense to make a ZipCode type inside an Address class.

                              – Rik D
                              3 hours ago





                              I disagree. In some cases it makes perfect sense to add a Name type to a Person class, if there are additional business rules attached to a Name. You wouldn't want to handle the rules for names in the Person class. Same for validating ZipCodes, it makes perfect sense to make a ZipCode type inside an Address class.

                              – Rik D
                              3 hours ago













                              @RikD: From the answer: "you don't need a Name subclass to be used in the Person class, unless Name (without a person attached) is a meaningful concept in your domain." When you have custom validation for the names, the name has then become a meaningful concept in your domain; which I explicitly mentioned as a valid use case for using a subtype. Secondly, for the zipcode validation, you're introducing additional assumptions, such as zip codes needing to follow a given country's format. You're broaching a topic that's much broader than the intent of OP's question.

                              – Flater
                              2 hours ago







                              @RikD: From the answer: "you don't need a Name subclass to be used in the Person class, unless Name (without a person attached) is a meaningful concept in your domain." When you have custom validation for the names, the name has then become a meaningful concept in your domain; which I explicitly mentioned as a valid use case for using a subtype. Secondly, for the zipcode validation, you're introducing additional assumptions, such as zip codes needing to follow a given country's format. You're broaching a topic that's much broader than the intent of OP's question.

                              – Flater
                              2 hours ago















                              I disagreed with part of your post, not everything. We're on the same page when it comes to the Person class. You seem to argue that ZipCode is not a good abstraction in an Address class; I disagree with that. I'm not making assumptions; OP clearly states he wants to validate a ZipCode, noone (but you) is talking about other countries. In my opinion, the validation of that ZipCode belongs in the ZipCode class; if you want to validate it against a Town, the validate method in de ZipCode class should have an argument for TownName (OP didn't mention this either).

                              – Rik D
                              2 hours ago





                              I disagreed with part of your post, not everything. We're on the same page when it comes to the Person class. You seem to argue that ZipCode is not a good abstraction in an Address class; I disagree with that. I'm not making assumptions; OP clearly states he wants to validate a ZipCode, noone (but you) is talking about other countries. In my opinion, the validation of that ZipCode belongs in the ZipCode class; if you want to validate it against a Town, the validate method in de ZipCode class should have an argument for TownName (OP didn't mention this either).

                              – Rik D
                              2 hours ago













                              @RikD: Zip code assumes United States Postal Service, and you can derive the name of the town from the zip code. Cities can have multiple zip codes, but each zip code is only tied to 1 city. It actually makes sense to get the city and state from the zip code (in the USA at least).

                              – Greg Burghardt
                              16 mins ago





                              @RikD: Zip code assumes United States Postal Service, and you can derive the name of the town from the zip code. Cities can have multiple zip codes, but each zip code is only tied to 1 city. It actually makes sense to get the city and state from the zip code (in the USA at least).

                              – Greg Burghardt
                              16 mins ago


















                              draft saved

                              draft discarded




















































                              Thanks for contributing an answer to Software Engineering Stack Exchange!


                              • Please be sure to answer the question. Provide details and share your research!

                              But avoid



                              • Asking for help, clarification, or responding to other answers.

                              • Making statements based on opinion; back them up with references or personal experience.


                              To learn more, see our tips on writing great answers.




                              draft saved


                              draft discarded














                              StackExchange.ready(
                              function () {
                              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsoftwareengineering.stackexchange.com%2fquestions%2f386042%2fis-avoid-yoyo-problem-a-reason-to-allow-primitive-obsession%23new-answer', 'question_page');
                              }
                              );

                              Post as a guest















                              Required, but never shown





















































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown

































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown







                              Popular posts from this blog

                              How to label and detect the document text images

                              Vallis Paradisi

                              Tabula Rosettana