Cesario Ramos’s Blog
Just things that keep me busy

Feb
03

Putting a few people together in a project does not make them into a team. And when people are not a team but must work together chances are they do not perform that well. It could even be the case that you could be more productive if you gave the task to a single person…

The thing is that for becoming a team certain conditions must hold. Numerous books like The Five Dysfunctions of a Team, Leading Teams and The Wisdom Of Teams just to name a few, have been written about teams and how to make them work.

Aside from the obvious things like skills for the tasks at hand and skills for cooperating with other people, the most important thing for a team, according to these books, is mutual trust and team cohesiveness. From my experiences with guiding teams I find that task and team skills can be learned most of the time, but trust and cohesiveness are harder objectives that need to be created.

A cohesive team
A cohesive team is one where the team members are all working on one common goal. There is only one goal and all team member activities are directly contributing to that goal. I always like to relate this back to a class. A cohesive class has only one responsibility and all its members and methods are used for realizing that responsibility. To create a cohesive team, goals and goal setting activities are very important. They have been recognized as a key enabler to high performing teams. (see e.g. Locke’s Goal Setting Theory) In agile processes, i.e. Scrum we can use the sprint goal for creating a cohesive team. I like to formulate one clear and challenging sprint goal in terms of user valued functionality. This helps set direction for the team. Once you have the clear sprint goal, you can use it to gain focus and thereby cohesion within the team. The sprint goal helps the team e.g. on deciding what tasks to do and what tasks not to do. Or when a task is sufficiently done or not in order to meet the sprint goal. But, for a team to be able to have productive discussions on important issues like these there needs to be trust among team members.

Trust
Trust among team members is something that comes from two things. The first is respect. People gain respect from others when they see that the person is competent in the tasks the team has to do. A skilled programmer can gain the respect of other team members by showing his skills. The second necessary ingredient for establishing trust is caring. So, if in a team setting you respect a person and that person cares about you completing your tasks then that person is gaining your trust.

Establishing team values and rules can help to establish trust within a team. When as a team you agree upon a set of values and rules you establish a reference point for the team. Team members can now reference the agreements and this makes it easier for people to discuss things. I’ve often seen that people have troubles asking for help. As a result they can keep on working a problem for far to much time. Another thing that is common is that people have troubles saying their real opinion. It could be that a team member is working on things that do not directly contribute to the spring goal but no one dares to challenge that person about it.

An example of a team rule I like to use is the following ‘We see asking for help when needed as a duty and sign of strength. We see not asking for help to be unprofessional and lack of respect for the team’. Another one is ‘We accept that we must justify our work to our team members’. With the team agreeing on these kinds of rules the road is set for team members to help each other more often. They show their care and skills to each other and are therefore creating trust within the team.

Although this is a first step and you must stimulate and facilitate this until it becomes common practice within the team. I’ve seen this as a good starting point to help a group become a team.

Jan
05

The reason for writing this little post is that I often get questions on patterns and one that stands out in particular has to do with the difference between the Strategy and the Bridge pattern. Most of the people I work(ed) with have trouble seeing the difference between these patterns and amazingly some say they never used the Bridge pattern at all. I find that very hard to believe and think that the have used it, but did not realize it was the bridge pattern.

I think that the problem has to do with the used terminology in the 1995 GoF book. The GoF describes the Bridge as “decouple an abstraction from its implementation so that the two can vary independently”…..

So I always think of the abstraction as a concept in my domain. The ‘what it IS part’. The implementation I consider the ‘what it DOES’ part.

Lets say that our abstraction is a Worker and that our implementation is a Job.

Now lets say that thanks to the economic crisis the workers must do other types of jobs. E.g. Programmers earn a few bucks on the side helping high school kids with their math and Busdrivers start selling newspapers.

Lets say you implemented this like this

class Programmer {
...
   void earnMoney() {
      if (isCrisis()) {
       teachMath();
      }
      else {
       writeCode();
      }
   }
}
class Busdriver{
...
   void earnMoney() {
      if (isCrisis()) {
       sellNewsPapers();
      }
      else {
       driveBus();
      }
   }
}

Using the Strategy you could make the Programmer and the Busdriver the ‘Context’ and encapsulate the type of Job as the Strategy. This could lead to the following code

class Programmer {
...
   void earnMoney(Job job) {
        job.doIt();
   }
}

And the same for the BusDriver.
That’s nice and all, we have higher cohesion and reduced coupling because the actual Jobis encapsulated.

Now lets say that for an additional requirement the Programmer and BusDriver have some rules for negotiating their working conditions. And that they can be offered any type of Job.
This could lead to the following code for the Programmer

class Programmer {
...
   void earnMoney(Job job) {
      if( isCrisis() ) {
         if( job.hourlyWage() > 100 ) {
            job.doIt();
         }
         else {
           ...
         }
      }
      else {
       ....
      }
   }
}

The Busdriver ofcourse has its own set of rules! For the BusDriver the daily hours of work of the job is important.

class BusDriver {
...
   void earnMoney(Job job) {
      if( isCrisis() ) {
         if( job.dailyHours() < 6 ) {
            job.doIt();
         }
         else {
           ...
         }
      }
      else {
       ....
      }
   }
}

The Job class would look something like

interface Job {
...
   int dailyHours();
   int hourlyWage();
   void doIt();
...
}

So, we now have variation in the workers because of their specific negotiation rules. And we have variation in jobs because of specific working conditions.

Could we do this with the Strategy?….
Not without duplication, because the Strategy pattern does not have variation on its context. You have one type of context which can use varying strategies. But you have to explicitly handle the different types of Workers!

So in order to clean this up, you also introduce variation in the context. You need to encapsulate the types of Workers. You introduce a Worker abstraction, make Programmer and Busdriver inherit from the Worker abstraction and move up an abstract earnMoney method to the Worker.

And there you have your Bridge pattern. The context is now called abstraction and the strategy is now called implementation. You can now cleanly combine Workers and Jobs!

So, there must be many times you used the Bridge pattern!!

Nov
17

One of my favourite BDD frameworks is easyb. I really like the dsl for user stories. In a previous post called Easy Requirements by Example I discussed how easy and clear this dsl can be.

For Scala I would also like to have a dsl just like the one of easyb. Writing a dsl in Scala is real easy, not as easy as in Groovy, but easy enough. So I decided to see how fast I could write a story dsl in Scala.

So, I need to be able to write things like the following

   given ("a blogger with a blog") {
    	val blogger = new Blogger("Mr Blog", "mrblog@blogger.com", "passwd")
    	val blog = new Blog("blogTitle", blogger)

		when("mr blog writes a new post") {
			blog addPost ("post Title", "post Text");
		}
		and
		when("mr blog publishes its post") {
		    blog publishPost
		}
		then("the post should be publised for reading") {
			blog.published shouldHave "post Title"
		}
	  }

The words given, when, then, and, shouldHave are part of the dsl.
The story dsl words are defined by a curried function. They have a explaining piece of text as the first argument and a code block as the second argument.

See below the definition of given

  def given(text: String)( codeBlock: => Unit ) = {
	  codeBlock;
  }

Because given is a curried function you can pass in the arguments one at a time. And when you pass in one argument you can choose to use curly braces instead of parentheses. As you can see in the above example, the given function has the rest of the story as the second argument within curly braces. So, the when, then, and form the codeBlock argument.

Here is the definition of the other methods

  def then(text: String)( codeBlock: => Unit ) = {
    codeBlock;
  }

  def when(text: String)( codeBlock: => Unit ) = {
    codeBlock;
  }

  def and(text: String)() = {
  }

… Yep this is really simple!

Because the codeBlock parameters are so-called “By-name-parameters” the codeBlocks of the functions are only evaluated when the given method evaluates it’s codeBlock! Also because closures in Scala see changes made to the free variables outside of the closure itself, you get the sequential execution ordering of the story.

The only thing that is left is the shouldHave word. As you might have guessed this is just a simple implicit conversion. To have free integration with IDE’s and other tools I choose to use JUnit as the underlying framework. So all the dsl vertification words are mapped to JUnit asserts as you can see below.


  implicit def shouldHave(l: List[Any]) = {
	  ShouldHave(l)
  }

case class ShouldHave(i: List[Any]) {
    def shouldHave(j: Any) = {
    	assertEquals(j, i.find( _ == j))
    }
}

You can use the dsl in your JUnit test like this

[/sourcecode]
  @Test
  def bloggerSpecification() = {

    given ("a blogger with a blog") {
      .....
    }
   }
[sourcecode]

You can imagine that you would like to execute a story multiple times with different argument values. Lets say that you would like to execute the story with multiple post titles. A little extension of the dsl made that possible. I introduced the words testcases, addCase and execute_testcases_with_specification.
See below an example

    testcases {
    	var postTitle: String = null;

    	addCase { postTitle = "title 1"	}
    	addCase { postTitle = "title 2"	}

    	execute_testcases_with_specification {
    		given ("a blogger with a blog") {
    			val blogger = new Blogger("Mr Blog", "mrblog@blogger.com", "passwd")
    			val blog = new Blog("blogTitle", blogger)		   

    			when ("mr blog writes a new post") {
    				blog addPost (postTitle, "post Text");
    			}
    			and
    			when ("mr blog publishes its post") {
    				blog publishPost
    			}
    			then ("the post should be publised fo reading") {
    				blog.published exists(_.title == postTitle) shouldBe true
    			}
    		}
    	}
 

What you see is that there are two test cases, each specifying a different value for the postTitle. The story is executed for each test case where the free variables are changed according to the test case at hand.

In order to make this work I stored all the test cases in a list. Then for each test case I first evaluate the test case. This sets the free variables of the story closure. Next I evaluate the story itself.

Again the code is really simple as you can see below.

object TestCase {

  var codeBlocks = List[() => Unit]()
  var scenario: Any = 0;

  def addCase( codeBlock: => Unit) = {
	  codeBlocks = codeBlock _ :: codeBlocks
  }

  def execute_testcases_with_specification( scenario: => Unit) = {
    codeBlocks.foreach( codeBlock => {
      codeBlock();
      scenario;
    })
  }

  def testcases( codeBlock: => Unit) = {
	  codeBlock
  }
}

If you made it this far in the post… what do you think of this approach?

Oct
30

More then a year ago myself and Eelco Gravendeel wrote the top 9 challenges of adopting Scrum . But those where just the top 9. Some did not make it to the top 9. This post publishes one that did not make it but I think is quite good. here it goes….

 

 

 

“If everything seems under control,
you’re just not going fast enough.”
Mario Andretti

The situation
You’ve got it all setup: a multidisciplinary team, a Product Owner and a dedicated Scrum Master. Deadlines are tight but seem to be do-able, scope appears to be negotiable, and the rest of the organization is well informed and prepared about what is happening. We’re good to go!
However; during the project deadlines are not met, quality doesn’t appear to be as good as expected and overall commitment of team members is not what you would like to see. And although the Scrum Master is pitching in and doing valuable project tasks to help out, things just don’t seem to improve very much per sprint passed.

The problem
The catch here is that the Scrum master is doing “valuable” project tasks. He or she is trying to do work which other team members might depend on to do their tasks. It can even go so far that the Scrum Master gets the feeling that they can’t get the Sprint done without him/her pitching in and picking up those all important / difficult tasks.
What happens next can be a combination of problems, some of these mentioned below:

 Team will not self-organize to meet deadlines
 Team does not feel committed to quality
 Scrum Master does not have (take) enough time to resolve impediments
 Scrum Master does not have (take) enough time to coach Team Members
 Scrum Master does not have (take) enough time to coach Product Owner
 Scrum Master pulls all responsibility towards him-/herself

As a result of such problems the Scrum Master then often feels the Team is letting him/her down and falls into a command & control style of managing (not leading!) the team. That way you miss out on much of the benefits self-organizing teams in general and Scrum specifically can provide.

How to fix this
It is a bit too simplistic to say the Scrum Master can never pick up any development or testing tasks. As always it depends. Here’s what worked for us:

When the project consists of one Team, one Product Owner and One Scrum Master you are best of if the Scrum Master doesn’t do any development, testing or analysis at all. Almost all time will have to be spent facilitating the team by removing impediments, coaching, etc. Some time will have to be spent on reporting about the project to management or other stakeholders. The rest of the time will go into helping out the Product Owner in managing the Product Backlog, managing Stakeholders, etc. Any time spent on doing “in Sprint” work such as development will not be spent on tasks such as mentioned above.

When the project consists of multiple teams or just has a Project Manager assigned to it, all becomes a bit different. The Scrum Master is of course still very much responsible for facilitating the team and removing impediments, but can leave the more “team outward facing” things to the Project Manager. Tasks such as Stakeholder Management, Risk Management, Product Owner coaching or removing impediments on an organizational level can be left to the Project Manager. So, if the Scrum Master has any time left he might be able to help out the team with some development tasks, or testing or whatever. But: The Scrum Master tasks always come first! The team should prevent the Scrum Master from picking up any tasks which might be in the critical path of the sprint, you never know whether some pressing impediment comes along and will require the Scrum Masters full attention!

Oct
25

Ever been in a project with this special guy that ‘helps’ the project succeed? This guy, ‘the Good’, that has the guts to stand up to management and tell them how things really are, bring discussions to a good end or has this unique technical skill?
On the other hand, have you ever worked with this ‘problem guy’, someone who acted negative, had little trust in others, was passive in his actions, did not take responsibility or any real interest in what was going on besides his own specific little piece of work or even was very cautious to show to others what he was really doing?… Let’s call this guy ‘the Bad’.

Imagine yourself being in a team with ‘the Good’ and ‘the Bad’ and frictions arise between the team members because things are not going as expected.
All to often what happens is that Mr Manager, lets call him ‘the Ugly’, who manages from behind his desk, starts talking to ‘the Good’ and encourages him to keep up the good work. “You are doing great, you are really helping the project move in the right direction”. The Good guy explains what he thinks is going on and complains a bit about the way the Bad guy behaves when it comes down to team work. “It’s very hard working with this guy, it is really hurting the team, he only sees problems and does not help at all when it comes down to team work”. The Bad and the Ugly quickly sit down together and come up with the solution to the problem.
The Bad and the Ugly decide that someone should speak to the Bad and tell him to change his behavior.

So, the Ugly goes talk to the Bad. “So, what is going on here…? why are you acting in this non constructive way?… It’s time for you to change, your lack of team spirit is causing problems in the project… I want you to change your behavior!, I want you to listen to the Good and work with him”.

This kind of Management behavior is often not the best approach from a long term perspective.
First of all the Bad is by-passed by talking only to the Good. This actually enforces the behavior of the Bad because he feels not involved and feels that anything he has to say does not matter anyways. Secondly the Ugly and the Good are jumping to conclusions and coming up with a counter measure without really grasping the situation and looking for root causes. It can be an solution but probably not the solution for the root cause of the problem. Next to that, he will not really support the countermeasure and everything is setup to stay the same again.
The third and biggest issue in this approach is that there is minimal learning involved and no real progress as the root cause is probably not tackled. The Good and the Bad do not learn much from this, so that in the future they could handle these situation better or prevent them from happening in the first place.

A different type of Manager realizes that real progress is to be found in coaching the team to learn how to deal with these kind of challenges. He realizes that most often it’s not the people who are causing the problems, but the systems in which they must work.
This Lean manager would talk to the team as a whole and make the team the owner of the issue in the long run. He would dig into the situation and see first hand what is going on at the Gemba to really understand the background and the problems. He would discuss with the team what would be appropriate goals to achieve so they could identify the gap between the current state and desired future state. Do the necessary analysis to find the root cause(s) of the issues. Guide the team to explore opportunities and propose a number of countermeasures to get team alignment and support.
He would stimulate team members to stand up and become the owner of improvement actions and ‘pull authority’ to take the team forward in becoming a constantly improving team that works thoroughly using the PDCA cycle.

Oct
13

Over the last few years I’ve had lots of discussions with teams on how to cope with this thing we call Agile Testing. The same topics arise over and over again, with the same kind of discussions. The main question is ‘How do we handle all these Use Cases, User Stories, Test Cases and Requirement Documents in this Agile Journey’
‘First we had software requirement specification documents, from these documents we derived our test cases…..’. We worked with the RUP, used CMMI or even worse the freighting DOD or MIL standards! Now you try to ‘help’ us in using user stories, but what about the use cases and the test cases? how do they relate? what about my Master Test Plan, Feature List, Test Specification and the like? Are they not needed anymore?

First of all, an approach that worked for me several times is to start with what is already used and only propose to remove or change things when it becomes clear that things are not needed anymore. So if e.g. people are using an Master Test Plan, let them use it until it becomes clear that the way they’ve been using it does not add the value it should add because of the iterative way of working. The same holds for using user stories. If they are used to using use cases let them use it next to the user stories. If you can help the team make a successful transition they will figure out how to cope with the use cases.

User Stories work perfectly for Agile planning and estimating. Next to that, an very important aspect is that user stories force the teams to communicate with the requirements people, be it the product owner, customer or domain specialist. In the case of use cases, what you see is that people incorrectly assume that they can write everything in the use case and that face-to-face communication is not that important because the requirements are written down so ‘carefully’ and ‘precise’…..
So, if you have a mixed team with testers, requirements people and developers, why do you still need to write this pile of documentation? Why not…… just talk more to each other?
It could be that the organization needs formal requirements documents to please some institution or manager, or even better a very ‘good’ reason I heard today, ‘I want to give the test document to someone else to do the testing for me’ or ‘when we fix a bug, we need to use the test case to verify everything else still works’.

Well there is good news, with the user stories there comes acceptance criteria and from these acceptance criteria you should derive test cases to further detail the user stories. So user stories get detailed with test cases, preferably automated ones, and these can be documented in any form you want. You can even group a set of related user stories into an use case if you wish and use an use case as a container for user stories. The test cases fill up the test documents as the sprints progress and at the end of a release there you have your required test documentation….. ….. or is it not required anymore?

Jul
24

There are numerous things you can measure when it comes down to software projects. I usually see that, if things are measured, the things that are measured do not result in the expected behavior. I’ve seen KPI’s on number of bugs fixed, features solved within given estimation, documents delivered and even hours worked. Eliyahu M. Goldratt wrote in his book The Goal “Tell me how [and when] you’ll measure me, and I’ll tell you how I’ll behave”. People normally try score as high as possible on the specific metric that is used to measure them. So if you are not measuring the real problem, you’ll probably just end up with high scores on your metric but without any improvement of your real problem.

In case you are trying to improve some aspect of your software development process you need to define a KPI. The KPI should express a measurement on the root cause of the problem. Lets say e.g. that you want to improve your estimations for delivering features so that the SW department gets better info for making planning decisions. You decide to measure how many features are realized within the estimated time. Lets say that as a result of this KPI you’ll see an increase in issues that are solved within the given estimation!! Good……., problems being solved right?

but….. did the estimations really improve? or did the estimators just added more padding to be sure their estimations were ‘correct’? Taking a step back… were you unhappy with the estimations or with the time it takes to deliver features? Why why why does it take so much time to deliver a feature? What is the root cause?

If you are not that happy with the time it takes to realize a feature than you could measure just that! From Lean we know that the time it takes from the moment a feature is known until it is actually finished is called Lead Time. It is the average time it takes for one unit of work to go from start to finish through the process, including delays between sub-processes. We also know that in a stable system we have that Lead Time = CycleTime * Work In Progress + Delay Between Sub-Processes, where Work In Progress is the number of features currently in the system and Cycle Time is the average time it takes for a feature to be realized. Notice that the Work In Process strongly increases lead time. Also note that Delays Between Processes directly contributes to Lead Time.

By measuring the Lead Time, Cycle Time, Work In Progress and Delays Between Sub-Processes we are measuring the things that really matter. Next to that they give us a clear indication for potential wastes in the process so you can get to the root cause of why it takes so long to realize a feature! So once you have these metrics setup for your department you can start identifying the wastes and eliminating them by defining KPI’s on them. But remember the one metric that rules them all is the Lead Time!

the average time it takes for one unit to go through the entire process – from start to finish – including time waiting between sub-processes.

Apr
27

Recently people have been asking me how to deal with so-called ‘expert estimations’ in Agile development. In most organisations where IT is seen as a supplier or cost centre, the business wants to know the costs and the duration of a project before it decides to fund it. This is of course perfectly normal!

The poor IT department is asked to do an ‘expert estimation’ based on the available vision, requirements and any other available information. The estimation is expected to be quite accurate with e.g. a max -10% to +10% deviation. So the IT department adds the necessary buffers and slack to the estimation. As a result the project plan is probably longer then necessary which results in longer projects and less productivity thanks to Parkinson’s Law. The project will also unnecessary claim personnel and other scarce resources for longer periods complicating their use by other projects. Task switching and hand-offs now become a necessity as people must work on multiple projects. It often also results in a project to not start at all thanks to the overestimation!

 So, how could we do this in Agile?

 Well…, what some people do not seem to realize is that in Agile we also provide estimates upfront. In Scrum e.g. we have the estimation meetings where the product backlog is estimated. We estimate just enough to be able to make the ‘right’ decision. We acknowledge that in the beginning of a project, when we know least about it, the estimates could be very inaccurate. We keep on estimating throughout the project increasing the accuracy of our estimations as we learn more about the project. We measure our progress based on actual working features and value added. This enables the business to get valuable estimation and planning info as early as possible to make the ‘right’ decision, which could be to stop the project! We use a project baseline that is based on actual data and progress. If we have 1000 points of estimated work, we work with 2 week iterations and we must be complete in 20 weeks then we must burn 100 points every iteration. This becomes our baseline and is used to measure our schedule and budget variance. We track features completed vs. features remaining, work in progress, feature cycle time and client value added. In Agile we do a lot more planning and we do it throughout the project.

We use the initial estimation to make the funding decision! We then have our estimated schedule, budget and functionality. After the decision to fund the project is made, we use the mentioned metrics and techniques to steer the project and track against the initial schedule and cost estimation. We re-estimate and re-plan based on real progress and provide the business with the most accurate information as quickly as possible.

Mar
25

In the days of waterfall project the testers did not have anything to do during the first half of a project. During this period they would spent most of their time surfing the net and rewriting their test plans. Nowadays with cross functional teams the testers play a significant role right from the beginning of the project. 

The role of a tester is not just testing anymore. An agile tester helps the team figure out what needs to be delivered at the end of a sprint. He plays an important role in clarifying the user stories and establishing a common understanding on the requirements within the team. During sprint planning the tester helps to clarify the user stories by also paying attention to things that could go wrong (Developers often have the tendency to see only the happy flow). Next to that testers work on requirement examples prior to sprint planning together with the requirements people to start the feedback early on. During the sprint the testers continuously provide feedback to the rest of the team to ensure the right thing is build correctly the first time.

When the team finishes a story during the sprint, a tester can have a feedback session with the product owner by demonstrating the user story and showing that the acceptance criteria are met. This is specially valuable in case the product owner is discovering what it really needs! In that case the acceptance criteria or the accompanying specifications are vague and the team helps the product owner figure out what he wants. Based on what he sees he gets a better understanding on what he really needs. It’s like when you want to buy a table. You know what a table looks like, but you can’t exactly specify the table you want. That’s why you go visit stores to see various tables. One table you see helps you to decide on the table size, while another helps you decide on the color and yet another helps you see the style and material you like. By having seen these examples you steadily get a clearer and more accurate picture of what it is you really want.

So for the testers there is no more laying back during the early stages of the project, but instead being part of the team right away and working hard to help the team achieve its sprint goal.

Feb
12

I’ve been testing ObjectTeams for a while now and think its a really cool way for using roles in the Java language. A role is a set of attributes and behavior a object can assume temporarily in a certain context. It’s like an actor behaving according to the film script. The actor plays the role as described in the script as long as he is shooting the film. After that he returns to be himself again.

Roles can help you in achieving a strict separation of concerns. This is because roles let you encapsulate context specific behavior in a role removing it from the class itself. In a collaboration you can have multiple roles working together to achieve some functionality. An example of a collaboration could be a car race. The Race collaboration exposes the role of a RaceCar for cars that want to participate in the race. A car object that assumes the RaceCar role will get additional state and behavior defined in the role RaceCar. These could be things like laps to go and car number. The Race collaboration itself can also have state like e.g. the participating race cars and the laps to go untill the race ends.

ObjectTeams is an extension to the Java language. It introduces some new language constructs that make it possible to program using roles. A collaboration is represented by a team and declared using the team keyword. Within the team you can define roles and their interaction. You can express that objects of a certain class will play a certain role using the playedBy keyword. As a result objects can be extend at run-tme with role specific behavior and state.

See below an implemtation of the SubjectObserver pattern in ObjectTeams.


public abstract team class SubjectObserver {
    …
    protected abstract class Subject {
        private LinkedList<Observer> observers = …
        public void attachObserver (Observer o) {…}
        ...
        public void notify() {
            for (Observer observer : observers)
                observer.update(this);
        }
}

    protected abstract class Observer {
        abstract void update(Subject s);
}
}

You see that we have a abstract team SubjectObserver that defines the roles of Subject and Observer. Lets assume that we have a TV and a Screen that needs to be updated when the TV changes state. We have to let TV play the role of Subject and Screen play the role of Observer.

public team class ObservingGraphical extends SubjectObserver {
    protected class Subject playedBy TV {
           notify <- after setPrice;
      }

    protected class ScreenObserver extends Observer playedBy Screen {
        update -> redraw;
}
…
}

We see that team ObservingGraphical extends SubjectObserver. Because it uses the same role name for Subject as its base, this role is implicitly extended using the same name. You can also see the use of playedBy keyword.

To couple the objects and roles the so called callin and callout statements are used. Using callin statement ‘notify <- after setPrice; ‘ you state that after method ’setPrice’ is called on TV, method ‘notify’ of Subject should be called. Using callout statement ‘update -> redraw;’ a call of the ‘update’ method on Observer is mapped to method ‘redraw’ on Screen.

How to use the collaboration and its roles is shown below

final ObservingGraphical observingGrph = new ObservingGraphical();
TV tv = new TV();
Screen screen = new Screen();
within(observingGrph) {
observingGrph.attachSubjectObserver(tv, screen);
tv.setPrice(1000);
}

The interesting part is the within statement. It defines that the role specific behavior is active. During the statement the objects TV and Screen are extended with role specific behavior. After the within statement they are back to normal again.

References

[1] E. Gamma et al (1994). Design Patterns: Elements of Reusable Object-Oriented Software.
[2] Edsger W.Dijkstra (1974).  HYPERLINK “http://www.cs.utexas.edu/users/EWD/transcriptions/EWD04xx/EWD447.html” http://www.cs.utexas.edu/users/EWD/transcriptions/EWD04xx/EWD447.html.
[3] Robert C. Martin (2002). Agile Software Development: Principles, Patterns, and Practices.
[4] ObjectTeams.  HYPERLINK “http://www.objectteams.org” http://www.objectteams.org/
[5] ObjectTeams language definition.  HYPERLINK “http://www.objectteams.org/def/1.2/index.html” http://www.objectteams.org/def/1.2/index.html.
[6] Bertrand Meyer (1997). Object-Oriented Software Construction, Second Edition.
[7] Matteo Baldoni et el. The Interplay between Relationships, Roles and Objects.
[8] Trygve Reenskaug, Role Modeling.  HYPERLINK “http://folk.uio.no/trygver/themes/roles/roles-index.html” http://folk.uio.no/trygver/themes/roles/roles-index.html.