Whenever you design software, you always have to balance different principles, because many of them conflict. For instance, the DRY (Don't Repeat Yourself) Principle often conflicts with Single Responsibility Principle, particularly when two things do similar, but not exactly the same thing.
Often times you have to decide which principle is more important and emphasis that principle over another one (although you should try to adhere to as many as possible). Often times, principles work together, sometimes they work against each other.
In this case, Tell Don't Ask works with other principles, such as the Law of Demeter (which despite it's name is still a principle as far as software goes and is better described as the principle of least knowledge).
What the LoD tells us is that a method of an object should only call other methods
- On Itself
- On objects passed into it as a parameter
- Any objects created/instantiated with an object passed by parameter
- the objects direct component objects
- Or a global variable
It's not specifically said, but I feel that the order of preference of selection of methods to call should be in that order as well, with global variables being last resort. But, that's neither here nor there.
So, if we combine Tell, Don't Ask with LoD then it's perfectly ok to pass objects to another object for "asking". Meaning, You have an Analysis object which you "Tell" to do something, passing the DataSet object as a parmeter. That's adhering to TDA. Inside the Analysis object's method you're adhering to LoD by only accessing "close friend" data.
This also conforms to SRP, since your DataSet is still just a DataSet and your Analysis object is an Analysis object.
The key take away here is that these principles are often "relativistic". Meaning that, from the perspective of the parent object that gets the data and wants to perform the analysis, you're "telling" the analysis object to do something.
The purpose of TDA is that your parent code should not query your DataSet for its state and then make decisions based on that. It should instead pass objects to other objects and have those objects perform their responsibilities, which may including querying those objects for their state, but that's ok because it's in the context of their responsibility.
Further reference here:
http://pragprog.com/articles/tell-dont-ask
EDIT:
If you would like a more authoritative source, there's no one better than Martin Fowler himself (read towards the end, you'll find this commentary)
http://martinfowler.com/bliki/TellDontAsk.html
But personally, I don't use tell-dont-ask. I do look to co-locate data and behavior, which often leads to similar results. One thing I find troubling about tell-dont-ask is that I've seen it encourage people to become GetterEradicators, seeking to get rid of all query methods. But there are times when objects collaborate effectively by providing information. A good example are objects that take input information and transform it to simplify their clients, such as using EmbeddedDocument. I've seen code get into convolutions of only telling where suitably responsible query methods would simplify matters 1. For me, tell-don't-ask is a stepping stone towards co-locating behavior and data, but I don't find it a point worth highlighting