14

According to Jeff Bay's Essay on Object Callisthenics,

One of the practices is set to be "Wrap all primitives and Strings"

Can anyone elaborate on this ?

In languages where we already have wrappers for primitives like C# and Java. and In languages where Collections can have generics where you are sure of what type goes into the collection, do we need to wrap string's inside their own classes ?

Does it have any other advantage ?

Tulains Córdova
  • 39,201
  • 12
  • 97
  • 154
Amogh Talpallikar
  • 1,997
  • 2
  • 26
  • 39
  • 20
    Does the essay not explain *why* that's supposed to be a good practice? If not, I would stop paying attention to that essay. "good practices" that don't come with explanations *why* they are good are just another form of cargo cult. – Michael Borgwardt Jun 25 '13 at 09:28
  • 3
    @MichaelBorgwardt: The essay does explain the reasoning. In fact, the explanation is more or less identical to the accepted answer below. – Jörg W Mittag Jun 25 '13 at 09:35
  • Hi, I haven't read the actual essay, I know that its the source, I found an article referring to it in an msdn blog. I actually didn't clearly understand the need.Now I got it. – Amogh Talpallikar Jun 25 '13 at 09:45
  • 2
    For reference: http://www.bennadel.com/resources/uploads/2012/ObjectCalisthenics.pdf – Scroog1 Jun 25 '13 at 11:43
  • Take note that the practice is intended as an exercise. The essay explicitly states: "Once you’ve written 1000 lines of code, the exercise is done, and you can relax and go back to using these 9 rules as guidelines." – Brian Jun 25 '13 at 17:13
  • Similar to [this question](http://programmers.stackexchange.com/questions/131852/never-use-strings-in-java). Not an exact duplicate: you have linked to a less dogmatic article than the one linked in the other question. – MarkJ Jun 25 '13 at 17:16
  • @MainMa I asked this question in 2013 and the link you posted has been asked this year. – Amogh Talpallikar Jun 02 '15 at 04:23
  • @AmoghTalpallikar: see http://meta.programmers.stackexchange.com/a/6161/6605 – Arseni Mourzenko Jun 02 '15 at 07:28

4 Answers4

19

Imagine a situation where you have a primative type:

int distanceInKm;

This is in many, many places throughout your code.

One day Mr Client comes to you and says, "We'd like everything displayed in miles now, please."

You now have to change everywhere where distanceInKm is used.

Now imagine an alternative situation where you have you own type:

class Distance
{
    private int _distanceInKm;

    public string DescriptionOfDistance()
    {
        return ...;
    }
}

Now you only need to change one place to make everything display in miles.

As @DanielFisherlennybacon has mentioned in the comments, you need to be pragmatic about when to apply any 'rules' of programming. In this specific case, it is worth noting that Object Calisthenics is an exercise to stretch your programming muscles. Marathon runners do sprints in training to improve their basic speed; it doesn't mean they have to sprint for the entire race.

Scroog1
  • 1,115
  • 8
  • 9
  • So basically if there are chances of that type being more than just one type of value and expectations can change, its better to make it into a separate class of its own ? – Amogh Talpallikar Jun 25 '13 at 09:33
  • Oh I remember, once we had a project where we were displaying distance and time graph for a moving object. we were using enums for each type in distance e.g km,cm,mm based on which we were displaying the string for distance and similarly for time: hour,min,sec. Then what happened was, client said, now we need velocity-time graph as well! now I had to write a function which would return a velocity enum type km/hour,m/sec etc based on enums values for distance and time being used. If I had classes for distance,time I could have just made a class velocity composed of all this. – Amogh Talpallikar Jun 25 '13 at 09:39
  • Also, I could have actually put description methods in the classes which could print string representation of these types. all of which implementing some Unit interface. Thanks! all of a sudden , past problems are flashing in front of me. – Amogh Talpallikar Jun 25 '13 at 09:41
  • 7
    I think it's NOT best practice to wrap ALL. If you e.g have an property/field "Amount" (something not bound to something else e.g. a unit) why would you want to wrap it. Right tool for the right job, please. – Daniel Fisher lennybacon Jun 25 '13 at 11:00
  • 1
    -1; Mr. Client now needs the software to work for his associates in China/Brazil/India/etc. who don't all speak English. Mr. Client, who is a bit of a software engineer himself, is dismayed to find that display logic is embedded within domain objects, making it extremely difficult to add support for other languages. –  Jun 25 '13 at 11:20
  • 2
    @MattFenwick _touché_. Obviously, you wouldn't mix such things in practice; I was just condensing it down for example purposes. – Scroog1 Jun 25 '13 at 11:34
16

In fact, the article repeatedly states that it is not best practice to blindly wrap all primitives:

The Challenge Do a simple project using far stricter coding standards than you’ve ever used in your life. Below, you’ll find 12 “rules of thumb” that will help push your code into good object-oriented shape.

By suspending disbelief, and rigidly applying these rules on a small, 1000 line project, you’ll start to see a significantly different approach to designing software. Once you’ve written 1000 lines of code, the exercise is done, and you can relax and go back to using these 12 rules as guidelines.

This is a hard exercise, especially because many of these rules are not universally applicable. The fact is, sometimes classes are a little more than 50 lines. But there’s great value in thinking about what would have to happen to move those responsibilities into real, first-class-objects of their own. It’s developing this type of thinking that’s the real value of the exercise. So stretch the limits of what you imagine is possible, and see whether you start thinking about your code in a new way.

Why would you post a question asking to explain an article you haven't read?

Here is what it says:

Rule 3: Wrap all primitives and Strings In the Java language, int is a primitive, not a real object, so it obeys different rules than objects. It is used with a syntax that isn’t object-oriented. More importantly, an int on its own is just a scalar, so it has no meaning. When a method takes an int as a parameter, the method name needs to do all of the work of expressing the intent. If the same method takes an Hour as a parameter, it’s much easier to see what’s going on. Small objects like this can make programs more maintainable, since it isn’t possible to pass a Year to a method that takes an Hour parameter. With a primitive variable the compiler can’t help you write semantically correct programs. With an object, even a small one, you are giving both the compiler and the programmer additional info about what the value is and why it is being used.

Small objects like Hour or Money also give us an obvious place to put behavior that would otherwise have been littered around other classes. This becomes especially true when you apply the Rule X, and only the small object can access the value.

  • My concern was this line "int is a primitive, not a real object, so it obeys different rules than objects." So, What I thought was, if we are just wrapping primitives so that we can use them as objects then why won't we use wrappers, Java anyways has auto-boxing and unboxing for them. Also that second para only says it is just good to understand that money is an object Money not long for readability etc. This was before I read the answer above. – Amogh Talpallikar Jun 25 '13 at 11:57
  • @maple_shaft the OP explicitly said in a comment that he hadn't read the paper. This was before I posted my answer. See http://programmers.stackexchange.com/questions/202663/why-is-it-a-good-practice-to-wrap-all-primitives-and-strings/202669#comment395407_202663 –  Jun 25 '13 at 16:17
  • the supposed linked article references an advertising site – Raul May 13 '20 at 10:32
9

Scroog1's answer covers adding context to a value. Another example: say you have

public void SubmitOrder(int productId, int customerId) { ... }

then there is always the possibility that you call it as so:

processor.SubmitOrder(customerId, productId);

Ouch. Let's hope you wrote a unit test that checked which value was passed in which place. But if you define:

public void SubmitOrder(ProductID pid, CustomerID cid) { ... }

then the compiler will stop you getting it wrong. For a small project this may well be overkill; for a large one where bugs have life-or-death consequences it may well stop you having sleepless nights.

Julia Hayward
  • 2,872
  • 2
  • 15
  • 12
-1

Trivially no. Absolutely not. It's a bad idea for the same reason that if(boolValue==true) is a bad idea. If it was a good idea, doing it twice would be even better: if((boolValue==true)==true) or WrappedWrappedString. But a boolean is already a boolean, and a string is already an abstraction that wraps a container of characters.

A successful design pattern modifies a primitive component to perform a related but different task. A design pattern which modifies a primitive component to perform the same task adds no value and causes entirely avoidable confusion.

MSalters
  • 8,692
  • 1
  • 20
  • 32
  • 1
    ... Ideally, the wrapping isn't to give the same functionality, it's to avoid certain types of mis-communication; there's a fairly famous [real world example](http://en.wikipedia.org/wiki/Mars_Climate_Orbiter#Cause_of_failure) where something like what @scroog1 suggests would have solved the problem. F# has [unit-of-measure](http://msdn.microsoft.com/en-us/library/dd233243.aspx) functionality; in some instances, an even more agressive form may be called for (say, limiting absolute rotations to the range -180 to 180?). – Clockwork-Muse Jun 25 '13 at 20:34