Agile Zone is brought to you in partnership with:

I am a programmer and architect (the kind that writes code) with a focus on testing and open source; I maintain the PHPUnit_Selenium project. I believe programming is one of the hardest and most beautiful jobs in the world. Giorgio is a DZone MVB and is not an employee of DZone and has posted 637 posts at DZone. You can read more from them at their website. View Full User Profile

Tell, Don't Ask in the case of a web service

10.20.2011
| 8478 views |
  • submit to reddit

This is a language agnostic post: it is valid for each object-oriented imperative language like Java, C#, PHP.

Let's start from the beginning: a web service adapter

I had a requirement: downloading posts from a particular group on LinkedIn for analysis of their content. So far so good: for any integration with my applications I follow the Hexagonal Architecture.

According to Cockburn, the Hexagonal Architecture features a series of ports (usually interfaces defined in the language), where you can plug in adapters to make the application actually work. Persistence is dealt with Repository interfaces; web service integration with a WebServiceName interface. In my case, the implementation is an object that asks the LinkedIn Api via HTTP.

The rest of the application just depends on the interfaces of the ports: testing becomes easier as for new test cases you can plugin a Test Double for the web service, which is able to return all the fake XML (or JSON) responses you need.

With this habit in mind, I started test-driving this design:



Scribe is the name of the OAuth library used for making the requests in the implementation of the service. PostsParser composes the service, and is the first object in the domain of my application. The code is a bit simplified omitting the need for timing limits and various options in the request.

Recapping: now my code depends on an interface and I can test most of it with a stub returning fake XML responses. I actually just put one object in front of it to analyze the XML, so from then on the rest of the system will work with Plain Old YourLanguage Objects. Right? Right.

Can you see the problem yet?

Weren't getters evil? Am I mocking or stubbing?

Yes, getters on objects containing logic are not my definition of clean code. However, when I write adapters I fill the classes with them: getPosts(), getUsers(), getComments()...

I can segregate the methods in various interfaces, and have just one implementation. This time let's try something different and get some inspiration from what is called (wrongfully) the London school.

I watched a Ruby presentation (to write with a Java application, as a PHP programmer... I told you this post was language agnostic), titled Why you don't get mock objects.

An outlined problem was that often we are writing mocks which become stubs, and we both verify the arguments passed to them and the result of the computation:

$mock = $this->getMock();
$mock->expects($this->once)
     ->method('whatIsThis')
     ->with(42)
     ->will($this->returnValue("The answer"));
...bit of work to obtain $response from a real object composing the mock...
$this->assertEquals("According to Deep Thought, 42 is The answer", $response);

State-based (the assertion), and behavior-based verification (with(42)) at the same time are becoming a smell to me. This kind of tests also lead to test and production code which are mirror each other.

In our LinkedIn example, I have to verify the parameters (groupId == 23 and postsToFetch == 10, or whatever), and that the class composing the service does its job (returning Post domain objects containing the right values parsed from XML).

Hollywood objects

There was also an interesting discussion on Hollywood objects in the GOOS mailing list a while ago. Hollywood objects were defined as hypothetical objects that do not have getters, but just methods with callbacks:

mainObject.getField();
//becomes:
mainObject.tellField(objectWhoNeedsIt);

The missing piece in that discussion (I may have missed even if someone wrote it) was that objectWhoNeedsIt was passed on the stack, and tellField() is a level of indirection which I find useless in most cases.

But if objectWhoNeedsIt is passed in the constructor of mainObject it becomes a collaborator. The method call becomes just mainObject.tellField().

My new solution

Now that I have refreshing my ideas on object composition, let's try to eliminate the getter on LinkedInService:

Inverted Dependency Inversion... nice name. PostsParser will in turn pass his newly created Post objects to someone else, and so on and so on. No need for getters on ScribeLinkedInService, and I don't even need a stub for the service now; the Test Doubles I use are still all mock of my own types, but excluding the service.

Repeat with me:

Object-oriented programming is based on objects passing messages to each other, not on method calls.

Why is that so? Each object does it work and a part of the system can change without affecting the rest of the application (the messages does not change). Method calls which asks for state expose very much of the two objects that interact, since data flows into two directions as parameters and return values.

We cannot always use so-called Hollywood objects, but when appropriate, method calls which just tell only go in one direction and simplify the protocol. When the protocol is simpler, you reap the benefits while substituting objects for testing or for adding new behavior to the system.

Hey, the whole aynchronous paradigm in SOA, or of events between DD Aggregates is also based on this advantage of one-way communication.

Why I mock less often than I can?

The tools we use have a profound (and devious!) influence on our thinking habits, and, therefore, on our thinking abilities. -- Dijkstra

I originally used only JUnit and PHPUnit for TDD: the absence of a mocking framework in the first and of decent matchers in the second has lead me to favor state-based verification with lot of assert*() even when mocks proved equally capable. As a consequence, I wrote a lot of getters instead of following the Tell, Don't Ask principle. State-based verification is also how I learned (and taught) TDD, since it is the most immediate method.

But now I have transformed my LinkedIn code: it's easier to test with mocks, and it's easier for me to substitute objects.

Published at DZone with permission of Giorgio Sironi, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Alexandru Repede replied on Thu, 2011/10/20 - 9:11am

Tst tst tst... 'Repeat after me'. Nice one. Also, nice theme. You're wondering off the topic a bit, around here and there, but +1 for the real example on a programming principle :D

Giorgio Sironi replied on Thu, 2011/10/20 - 11:28am in response to: Alexandru Repede

Every now and then I take an holistic view :)

Erwin Mueller replied on Thu, 2011/10/20 - 6:32pm

If I could only read the hand writing (or whatever) in the diagrams without get a magnifying glass. Does it look "cool" if you scan your scribes and post them?

 I just don't understand why you talk about  Hollywood Objects, mocks, stubs, getters and DI. You just got the responsibilities of your objects wrong.

Witold Szczerba replied on Fri, 2011/10/21 - 3:08am

Hi, after reading the article I think I get your point, but the thing I am missing here is how are the test actually/exactly chenge? I think the article would be so much complete with a sample of tests before and after, at the end - this is what matters, isn't it?

Giorgio Sironi replied on Fri, 2011/10/21 - 8:06am in response to: Witold Szczerba

I understand your need for code as the source of truth, but I tried to keep the post language-agnostic. Here is a diff that tells all about the test and shows how the Test Double of the Adapter vanished: https://gist.github.com/1303801

Giorgio Sironi replied on Fri, 2011/10/21 - 8:13am in response to: Erwin Mueller

I believe in testing as a metric to discover when a design works and when it needs to be rethought; Eclipse and JUnit was programmed by very smart people, but keep pointing in the direction of getters and setters (autogenerated) and state-based verification (no native support for mocking).

Witold Szczerba replied on Sat, 2011/10/22 - 6:45am

The Hollywood objects example, instead of:

mainObject.getField();
//becomes:
mainObject.tellField(objectWhoNeedsIt);
 
Shouldn't actually look like this?
 
mainObject.getField();
//becomes:
objectWhoNeedsIt.tellField(value);
 
So now the value does not need to be exposed to the outside world, 'mainObject' can keep it private.

Giorgio Sironi replied on Sun, 2011/10/23 - 11:23am in response to: Witold Szczerba

This is exactly the code inside mainObject; the call from the outside it becomes: mainObject.tellField();

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.