Upload
johannes-brodwall
View
751
Download
0
Tags:
Embed Size (px)
DESCRIPTION
My talk on Superfying your team with (remote) pair programming at #AgileIndia2014 with Niruka Ruhunage
Citation preview
Remote Pair Programming
Agile India 2014Johannes Brodwall
Exilesoft Chief scientist
@jhannes
Guest starring: Niruka Ruhunage
How can a distributed team
still collaborateclosely?
How can a team collaborate well?
But first
But first – a competition:
Competition:Find the blue sentence
This talk is a talkfor you if you…
You work in a team, but...
Your team doesn’t feel like a team
Your distributed team doesn’t feel like a team
After this talk you will…
Be motivated to start using pair programming, possibly remotely
Have seen remote pair programming
Know how to get started
Who is using pair programming as their preferred approach?
1. What is a super team2. Building a super team
with pairing3. Getting the benefits4. Summary
Part I
What is a super team?
Sharing the burden
The fun remote team
Rabbit hole!
Shared context
Sharing experience
Whops! No!
Working baseline
“That’s strange…”
“Eureka!”
20 minutes fix (where 10 was
waiting)
Problem solved
The sad team
Planning
The sad team
JohannesJohannes
Backend dev
“Scrum” “Master”
Johannes: You’ll create CRUD SOAP service for projects
with applications
Okay
Planning
The sad team
JohannesJohannes
Backend dev
“Scrum” “Master”
How long will it take?
Um…
Planning
Backend dev 2
The sad team
JohannesJohannes
Backend dev
“Scrum” “Master”
It’s pretty easy with Hibernate
Okay, 8 hours for each of Create…
then
!
Stand-up
The sad team
Designer
Frontend devDatabase dev
Today, I will work on Create Project
JohannesJohannes
Backend dev
Scrum master
Stand-up
The sad team
Designer
Frontend devDatabase dev
No impediments
JohannesJohannes
Backend dev
Scrum master
Behold – the uber coder
The sad team
Exception!
The sad team
org.hibernate.PropertyValueException: not-null property references a null or transient value: ....common.entities.Application._applicationsBackref org.hibernate.engine.Nullability.checkNullability(Nullability.java:95) org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:313) org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:204) org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:130)org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:210) org.hibernate.event.def.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:56) org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:195) org.hibernate.event.def.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:50) org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
The sad team
Exception
Stack overflow
Tweak
Deploy
Poke
The sad team
Exception
Stack overflow
Tweak
Deploy
Poke
The sad team
Exception
Stack overflow
Tweak
Deploy
Poke
The sad team
Exception
Stack overflow
Tweak
Deploy
Poke
Stand-up
The sad team
Designer
Frontend devDatabase dev
Yesterday, I worked on Create Project
JohannesJohannes
Backend dev
Scrum master
Stand-up
The sad team
Today, I will hopefully fix the
exception and also do Delete Project
JohannesJohannesScrum master
Designer
Frontend devDatabase dev
Backend dev
Stand-up
The sad team
No impediments
JohannesJohannesScrum master
Designer
Frontend devDatabase dev
Backend dev
Stand-up
The sad teamJohannesJohannesScrum master
Designer
Frontend devDatabase dev
Backend dev
How could they help anyway
The sad team
Behold – the uber coder
The sad team
Exception!
The sad team
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.hibernate.ObjectDeletedException: deleted object would be re-saved by cascade (remove deleted object from associations): [Person[id=22]] at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:927) at org.springframework.web.servlet.FrameworkServlet.doDelete(FrameworkServlet.java:844) at javax.servlet.http.HttpServlet.service(HttpServlet.java:653) at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:796) at javax.servlet.http.HttpServlet.service(HttpServlet.java:728) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at org.springframework.orm.hibernate4.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:152) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at org.springframework.web.multipart.support.MultipartFilter.doFilterInternal(MultipartFilter.java:119) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at filter.NoCacheFilter.doFilter(NoCacheFilter.java:102) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
The sad team
Stand-up
The sad teamJohannesJohannesScrum master
Yesterday, I finally finished Delete after 3 days of «coding»
Designer
Frontend devDatabase dev
Backend dev
I didn’t need the Delete service
Stand-up
The sad teamJohannesJohannesScrum master
Designer
Frontend devDatabase dev
Backend dev
I didn’t need the Delete service
Yesterday, I finally finished Delete after 3 days of «coding»
The sad team
STOP
Imagine you should carry 10 pieces of timber
Each is 3 meters and 30 kg
The fun team
Stand-up
The sad team
I’m ready for a new task.What’s on the board..
JohannesJohannes
Johannes
Scrum master
Stand-up
The sad team
«Let’s users administrate their projects»
JohannesJohannes
Johannes
Scrum master
Stand-up
The sad team
I haven’t done any Hibernate tasks before.
Who can I pair with?
JohannesJohannes
Johannes
Scrum master
I can work together with you
Exception!
The sad team
org.hibernate.PropertyValueException: not-null property references a null or transient value: ....common.entities.Application._applicationsBackref org.hibernate.engine.Nullability.checkNullability(Nullability.java:95) org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:313) org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:204) org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:130)org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:210) org.hibernate.event.def.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:56) org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:195) org.hibernate.event.def.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:50) org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
That link doesn’t really seem relevant.
Are we getting anywhere? Time to ask for help?
I think Niluka has worked on this sort of thing before
Niluka
Yeah, just look at the Person HasMany Roles
mapping
That’s it!High five!
The difference
Everyone works everywhere
Knowledge is disseminated
You’re never alone
Part II
Superfyingwith
Pair programming
Pair programming styles
Debate club
“No, this variable should be called fooNumber, not fooNum”,
“But it’s a common abbreviation”
Dedicated driver
“I’ll write the parser”
“I’ll design the algorithm”
Driver-navigator
“I don’t know how to solve this, so I’ll sit at the keyboard”
Ping-pong
Ingredient #1:
Pair programming
Ingredient #2:
Test driven development
Failing test
Write code
Failing test
Write code
Failing test
Ingredient #3:
Refactoring
Failing test
Write code
Failing test
Write code
Failing test
Refactor code and tests
Refactor code and tests
Put together
Failing test
Write code
Failing test
Write code
Failing test
Failing test
Write code
Failing test
Write code
Failing test
Refactor code and tests
Refactor code and tests
Failing test
Write code
Failing test
Write code
Failing test
Refactor code and tests
Refactor code and tests
Demonstration(Guest starring
Niruka Ruhunage)
Kata: Number to text
Kata: Number to text8192 => eight thousand one hundred and ninety two
125,017 =>
one hundred and twenty five thousand and seventeen
What does it feel like?
Part III
From here to there
Make sharing into a goal
Dileepa
Johannes
Chintaka
Thomas
Sergey
Arunas
Dileepa
Johannes
Chintaka
Thomas
Sergey
Arunas
Arunas Johannes Dileepa Chinthaka Sergey Thomas
Add new company✓ ✓ ✓ ✓ ✓
Display contacts on map ✓ ✓ ✓
Filter contacts in list✓ ✓
Authenticate user by company ✓ ✓ ✓ ✓
Store password securely ✓ ✓
Usernames with Norwegian letters are rejected
✓
Arunas Johannes Dileepa Chinthaka Sergey Thomas
Add new company✓ ✓ ✓ ✓ ✓
Display contacts on map ✓ ✓ ✓
Filter contacts in list✓ ✓
Authenticate user by company ✓ ✓ ✓ ✓
Store password securely ✓ ✓
Usernames with Norwegian letters are rejected
✓
Arunas Johannes Dileepa Chinthaka Sergey Thomas
Add new company✓ ✓ ✓ ✓ ✓
Display contacts on map ✓ ✓ ✓
Filter contacts in list✓ ✓
Authenticate user by company ✓ ✓ ✓ ✓
Store password securely ✓ ✓
Usernames with Norwegian letters are rejected
✓
Overcoming obstacles
JIRA
With a true team, no member owns more
than their current task
TODO DOING DONE
WAITING
AWAY
You will get more done
(But not in the first or second sprint)
Distance
• See each other• Share what we see• Share our work
• Skype (or any voice sharing)• GoToMeeting (or flexible screen
sharing)• Dropbox (or any file sharing)
Skill and tact
• Experiment with switching patterns
• Try out ping-pong• “Could we try it this way
first?”
Expect exhaustion
When
Bug fix
Training event
Practice with kata
1. Create a dropbox account
2. Share a folder with a friend
3. Put a coding project there
4. Create a screen share session
5. Call up your friend
Failing test
Write code
Failing test
Write code
Failing test
Refactor code and tests
Refactor code and tests
Set a time per week
Don’t wait to find the perfect tool
Just do it
Conclusion
What
• Two people at one codebase• No member owns a task
beyond the day• Team rotates pairing
Why
• Less Overproduction (unused functions in API)• Less Waiting (for the only person who knows X)• Less Motion (as everyone gets more skilled)• Fewer Defects (as two pair of eyes see better)• Less Over-processing (from double responsibility)• Less Inventory (as team works more focused)• Less Transportation (handoffs inside a story)
How
• Ask for help – don’t work alone
• Play with ping pong programming for two hours
• Be open, share and listen
Competition:What was the blue sentence?
A team creates together what no member could do
alone
Next week: Commit to two hours of
working together
http://JohannesBrodwall.comhttp://exilesoft.com
http://twitter.com/jhannes
Thank you