Question about the idea of ​​"Say not ask"

There is this famous quote that says

The procedural code receives information, then makes decisions. Object oriented code tells objects to do something. - Alec Sharp

The subject of the message is about this.

Suppose we are developing a game in which we have a Game where there is a Board . When you encounter the problem of deciding which methods we will implement in the Board class, I always think of two different ways:

The first approach is

fill in the Board class getSize() , getPieceAt(x, y) , setPieceAt(x, y, piece) . This will seem reasonable and is what is commonly found in libraries / frameworks. The Board class has a set of internal functions that they want to share and has a set of methods that allow the class client to control the class as they wish. The client must request what he needs and decide what to do. If he wants to install all the boards on black, he will "manually" sort them out to achieve this goal.

The second approach relates to

looking for Board dependent classes and see what they "tell" him. ClassA wants to count how many pieces are red, so I would do calculateNumberOfRedPieces() . ClassB intends to clear all fragments on the Board (for example, set all of them to NullPiece ), so I will add the clearBoard() method to the Board class. This approach is less general, but provides much greater flexibility in relation to other aspects. If I β€œhide” the Board behind the IBoard interface and decide that I want to have a board with an infinite size, doing in the first case, I would be stuck, because I would have to sort through an infinite number of objects! On the other hand, in this way, I could do my best (I could, for example, assume that all parts are zero, except for those contained in the hash table!).

So...

I know that if I intend to create a library, I probably stick with the first approach, as this is a more general approach. On the other hand, I would like to know what approach should be followed when I have full control over the system that will use the Board class, when I am the one who is also going to develop all the classes that Board will use. At present and in the future (will the second approach not raise problems if later I decide to add new classes depending on Board with different "desires"?).

+6
java c # oop
source share
3 answers

The quote really warns you of data structures that do nothing with the data they store. Thus, your Board class in the first approach can be eliminated and replaced by a common collection.

Despite this, the Single Responsibility Principle is still applied, so you should be careful with the second approach.

What I would do is call YAGNI (you won’t need it) and try to figure out how far I can use the general collection, not the Board class. If you find that you will need the Council class later, its responsibility is likely to be much more obvious by then.

+4
source share

Let me suggest the opposite point of view. I think the second approach has legs. I agree with the principle of a single responsibility, but it seems to me that there is one protected one mission / concern for the Board class: Maintaining the playing field.

I can imagine a very reasonable set of methods such as getSize() , getPiece(x,y) , setPiece(x, y, color) , removePiece(x, y) , movePiece(x1,y1,x2,y2) , clear() , countPieces(color) , listPiecePositions(color) , read(filename) , write(filename) , etc., which have a consistent and clear joint mission. Consideration of the problems associated with managing these tips would allow other classes to implement the logic of the game more cleanly, and for Board or Game will be more easily expanded in the future.

YAGNI is doing well and well, but I understand that he encourages you not to start building beautiful buildings with the hope that one day they will be useful. For example, I will not spend time on the future possibility of an endless game surface, a three-dimensional game surface, or a game surface that can be embedded in a sphere. If I wanted to take YAGNI seriously, I would not write simple Board methods until they were needed.

But this does not mean that I will drop the Council as a conceptual organization or a possible class. And this, of course, does not mean that I would not even think about how to share the problems in my program. At least YAGNI in my world does not require you to start with low-level data structures, little or nothing through encapsulation, and a fully procedural approach.

I do not agree that the first approach is more general (in any way), or that it seems to the consensus that you need to "just see how far you can go without abstracting something." Honestly, this sounds like we decided eight queens . In the year 1983. In Pascal.

YAGNI is an excellent guiding principle that helps to avoid many second system effects and similar solutions, we-can-do-it We must be wrong too. But YAGNI, which crossed the Agile Practice Thupidity Threshold , is not a virtue.

+1
source share

CurtainDog is right, call Yagni and find out what you really need right now, implement this, and then make sure that it will not interfere with any features that may be desired in the future.

The second approach violates the principle that superclasses should not know about each of their subclasses. I think the element that you are missing is that the base class can define template methods like getBoardSize, countRedPieces, countBlackPieces that can be overridden by subclasses, and your superclass has code that uses these template methods, so telling your subclasses what to do, but not how to do it.

0
source share

All Articles