views:

123

answers:

6

Hi,

I have a simple question (working with Java). I have two classes, one represents a Document, a second represents a Word.

The Document class needs to know some info about the words that is kept in Word. My question is, what's the best way to decouple the two classes? I have 2 options in mind:

  1. Have no connection between the classes, and each time I call a method in Document, I pass it an object of Word (so I have a third class with a main method that initiates both Document and Word).

  2. Declare a private object of Word inside Document.

One thing to note, I only have one object for Word and one for Document. I don't create a new object for every new document or word. I store a list of the entire documents in Document, and a list pf the entire words in Word.

Thanks!

+1  A: 

From my point of view...

public class Document{

  private List<Word> words = new ArrayList<Word>();

  public void setWord(ArrayList<Word> words){this.words = words;}
  public ArrayList<Word> getWord(return this.words;)
}

It's a reasonable approach. In this example you can create a Document without any Word's, which makes for an empty Document, which is valid.

You could still create a third class as you suggest, however, I don't see the benefit with it.

StudiousJoseph
Thanks for the answer. In this implementation I would need to create a new Document object for each new document. Inside Document I have a list of documents already (so maybe I should call it Documents instead (and Words)). Word is a pretty heavy class. So the only thing I want to store in Document(s) are the words indexes. I think I need to rephrase my question... didn't do it very well.
You should reconsider your design. A document should be a document, not all documents. If you have a class Documents, it should contain several Document objects, which would then each contain Word objects
Falmarri
A: 

Your problem should be solved by composition. Thus having a List of Word seems to be a valid approach. By separating out Documents and Words, you have already achieved the required de-coupling. I do not get your exact point of de-coupling Document and Word objects.

Tushar Tarkas
A: 

Your question is

what's the best way to decouple the two classes? I have 2 options in mind:

Neither option satisfies your request. If they are going to work together, then they are going to be coupled. The only thing is how tight or loose the coupling is.

Both of your options sound like tight coupling. A form of looser coupling would be to store an interface reference and take it in on a constructor or setter method.

BioBuckyBall
A: 

If you want to decouple the classes, one standard way is to use an interface:

public interface IWord {
...
}

public class Word implements IWord {
...
}

public class Document {
    public boolean append(IWord word) { ... }

    ...
}

This way both Class and Word depend on IWord, but neither class nor Word depends on the other. This is known as Dependency Inversion.

richj
A: 

Well first of all I think you're naming your classes incorrectly.

I don't create a new object for every new document or word. I store a list of the entire documents in Document, and a list pf the entire words in Word.

Judging by what you said here you have something like this:

public class Words {
    private List<Word> = new ArrayList<Word>;
    // getters+setters
}

public class Documents {
    private List<Document> = new ArrayList<Document>;
    // getters+setters
}

And you want to use the Words class in the Documents. If you want to do that, that means you can't decouple it (as it's against the very definition of the word "decouple"). I'm guessing here again, but I think you want to code it so you can change the implementation of the Documents class so in the future it could use another class like for example BetterWords.

In order to do that I would create either an abstract class or an interface (depending on the rest of your architecture) and then make the Words class either extend it or implement. Then you can do something like this:

public class Documents {
    private List<Document> = new ArrayList<Document>;

    private IWords wordsInterface = new Words(); //in case you want to make an interface
    private AbstractWords wordsAbstract = new Words(); //in case you want to make an abstract class

    // getters+setters
}

Or you can put it in the Document class (the words), don't really know where you want them.

Zenzen
Yes, this is what I actually meant. Thanks!
+1  A: 

I don't agree with your understanding of Decoupling. Decoupling is not just about which objects create other objects, it's also about which objects know about the behaviour of other objects and (crucially) what needs to change in (your example) Document if Word changes.

However, also I really don't understand what your mean by these two phrases:

I only have one object for Word and one for Document. I don't create a new object for every new document or word. I store a list of the entire documents in Document, and a list pf the entire words in Word

Start from Document. What can objects of this class do? You seem to be saying that

class Document {

     private List<??OfWhat??> allDocuments;
}

If class Document contains a List, what's it a List of? I think you need:

class Shelf {
      private List<Document> allDocuments;
}

class Document{
      private List<Word> wordInOneDocument;
}

class Word {
      private String wordContents;
}

Now a Shelf could offer methods such as getRecentDocumets() findDocumentsContaining(String text) and Document could contain getWordCount() and insertParagraph(List, START); and so on.

To have a better discussion we need to see a bit more of what you had in mind, a bit more about behaviour.

I do agree with your general thought that there is Something other than Document and Word out there. Something that can reasonably invoke methods such as createDocument() and insertParagraph()

djna
I like this answer. Thanks!