1

I am designing a treeNode class. While implementing the getPathToParentNode() and getPathFromParentNode() methods, I noticed that their functionality is essentially the same - they just operate on different data structures.

getPathToParentNode() recursively adds all parent nodes into a queue, and then creates the path using the queue iterator.

getPathFromParentNode() recursively adds all parent nodes into a stack, and then creates the path using the stack iterator.

To adhere to the DRY principle, I was thinking of extracting the duplicate code (recursively adding parents to a collection, and using the collection iterator to generate the path) into a separate function, and just passing it a queue from the first function and a stack from the second function.

// takes in a queue or a stack
// returns path to root node or path from root node respectively
List<ITreeNode<T>> getPath(Collection<ITreeNode<T>> pathCollection) {

    pathCollection.add(this);

    ITreeNode<T> parent = this.getParent();
    pathCollection.add(parent);

    while (parent.getParent() != null) {
        pathCollection.add(parent.getParent());
    }

    return new ArrayList<ITreeNode<T>>(pathCollection);
}

However, the resulting helper function doesn't feel right. I don't think it performs something independent/worthwhile enough to justify its existence. Furthermore, its objective changes based on the type of collection passed into it, and perhaps as a consequence of that, it is difficult to name.

Is such a method considered "good" in light of the principles of object-orientated design? What would be a better approach?

Edit:

Similar question regarding method extraction in general (but the answers do not address my specific case): Should I extract specific functionality into a function and why?

  • I think this one might come down to too much of an opinion based discussion. Personally I would probably have two separate functions and skip over DRY in this context in favour of clarity, but I wouldn't be at all put out if someone presented me with your code to work with either. – Jack Parkinson Jul 13 '17 at 7:49
  • 1
    Possible duplicate of Should I extract specific functionality into a function and why? – gnat Jul 13 '17 at 8:29
  • That is about method extraction in general - I was asking about my specific case. – Hassaan Jul 13 '17 at 9:50
2

You could have both implemented with a DQueue and just use an end selector to determine whether it is used FIFO or FILO, (First In First Out = Queue, First In Last Out = Stack). Then the two functions would become a single one with a direction specifier. Much simpler and no need for template specifiers.

  • What would be a good format for the direction specifier? Is an enum appropriate here? – Hassaan Jul 13 '17 at 8:12
  • You could just use a bool called something like upwards or a enum of upwards, downwards would be clearer. – Steve Barnes Jul 13 '17 at 9:38
  • If you go with the enum, make the name like queue/stack or fifo/filo. – Robert Baron Jul 13 '17 at 10:36
  • 2
    @RobertBaron Or "Direction.FromParent"/"Direction.ToParent" – T. Sar Jul 13 '17 at 13:49
  • 1
    Decedents/Ancestors there are lots of possibilities. TopDown/BottomUp will probably raise a smile from future maintainers. – Steve Barnes Jul 14 '17 at 4:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.