0

I get the general idea of encapsulation in object oriented programming and how it facilitates later code modifications. However I often get confused how far should the isolation of objects go, especially in terms of construction of related objects.

My question is how much should two classes of one package know about themselves, both having package visibility, related in a way that one class is to return the other one. For example consider class A and class B, where B is some limited view to A, however not necessarily containing the same type of Collection internally.

Consider a practical example, implementing a board game like chess or checkers.

  1. Let the board be implemented as a bulk of Paths i.e. a collections of references to Fields that can be a subject of legal movement, from one board edge to the other one.

  2. Let Vector be an object that has partial access to that Path, however only to the extent defined by the two Field indexes. Consider subList method analogy.

  3. Such Vector is given to the Figure object (e.g. Pawn) that exercises movement and uses that structure to gain information if the movement is possible and to execute movement through methods implementing Figure replacement and Figure captures.

  4. To get Vector, Board method is executed that gets appropriate Path and it in turns is to return the Vector. It is the only way to get an Vector object.

The question here is how and where should Vector be constructed? There are few scenarios here:

  1. Can Path pass whole reference to fields field to Vector constructor or would that be a breach of encapsulation?

  2. Should getVector method construct proper container first and just then should it be passed to some dead simple Vector constructor?

  3. Or maybe should I put fields to some intermediary Collection not related to any of the two classes' implementations?

Here is some code in Java for illustration:

class Path {
   private LinkedList<Field> fields;
   public Vector getVector(FieldIndex start, FieldIndex end) {
       /** ... */
   }
}

class Vector {
   /** some internal hidden representation */
   private SomeContainer<Field> container;
   /** some public methods for querying the fields contained */
}

fileds and container can be very much different depending on implementation. For example fields can hold all fields associated with a given Board path, but container could hold, say, only occupied fields. The point is to design relations between objects to rely very little on internals.

infoholic_anonymous
  • 969
  • 3
  • 12
  • 34
  • 1
    Just enough to get the job done. If you're worrying about nesting levels of encapsulation then you're overthinking it – Michael Kang Dec 22 '14 at 01:58
  • What exactly is FieldIndex here? Some int holding object that enforces bounds on it's own? – candied_orange Dec 22 '14 at 02:02
  • @CandiedOrange The assumption is that you can infer from FieldIndex the int of a list in this or other way. For example in checkers, it can be board matrix coordinate '(x,y)', and every field on a path differs by one on a 'x'. If path keeps first coordinate, you have all you need. But again, there can be many other ways of implementing it. – infoholic_anonymous Dec 22 '14 at 02:09
  • @pixelbits I'm afraid I do. I've read a lot about how important it is to keep it as elastic as possible and don't really know where exactly the sanity ends here. – infoholic_anonymous Dec 22 '14 at 02:13
  • You mean `getVector` may return a rank, file, or diagonal of the board? So two `FieldIndex`s are actually two coordinate points, say A1 to A8? – candied_orange Dec 22 '14 at 02:17
  • @CandiedOrange rank, file, diagonal are what I call a `Path`s here. I ask Board using two indexes. A board method first gets Path i.e. is given what you say. But then, still inside that Board method, I want to further limit it with Vector to have only fields between those fields. And this returned finally. In a sense Vector is a limited view within rank/file/diagonal. – infoholic_anonymous Dec 22 '14 at 02:37
  • @infoholic_anonymous I suggest driving your design from use-cases. Once you know your prioritized list of use cases, you'll know when you're over-designing when you start to build concepts that don't fit any of your primary use cases. – Michael Kang Dec 22 '14 at 03:35
  • Say, how is this thing going to construct a knights move? Will you have a `getVectorForKnight(FieldIndex pos)` method? – candied_orange Dec 22 '14 at 05:33
  • @CandiedOrange right now my solution is checkers-centric. in case of chess, the knight would require some separate handling. Why did you remove your answer? It was a bit off topic, though interesting. – infoholic_anonymous Dec 22 '14 at 18:20

0 Answers0