Links for 2012-02-03 [del.icio.us]

Sahana Chattopadhyay

48 min 43 sec ago

Back to the basics: What made this Agile Inception especial?

Paulo Caroli

Fri, 02/03/2012 - 12:14
The following two pictures depict the latest Inception I participated at.








A little bit of history: For the past two years I have participated directly in 3 Inceptions, and indirectly in 5 inceptions. By directly, I mean, I was sitting in the war room for most of the Inception sessions. And by indirectly, I mean, I was participating on the Inception sessions over video from a Nearshore location (onshore is San Francisoc, USA, nearshore is Porto Alegre, Brazil).

I attribute the success of the last Agile Inception to 3 things: collocation, war room, and colorful post-it.

Collocation

Don’t under estimate the value of a face to face interaction. I am currently in Brazil and I am used to having effective meetings over video and phone with USA. I know that technology can bring people closer together, and, perhaps, we can work together without sitting next to each other. However, the face to face during Inception will bring the team together in a way that it will be worth each penny spend for making the collocated Inception a reality.

I compare it to dating and internet dating. Relationship development goes to another level when the whole team is at the same room. Think creatively on how to save on costs. In our case we were able to reduce the collocated period by having a pre-Inception period before the collocate Inception. Spikes, research, data gathering, codebase analysis were the sort of activities we did in the pre-Inception week.

War room

Keep a single room for the team during the intense Inception period: the war room! The room should fit all team comfortably. It must have a clean table and wall space. The room should also have a cabinet or a box with index cards, colorful post-its and pen.

The war room makes the environment for collaborative sessions. It also avoids the waste of time of people moving from one room to another. Another important point is about carrying the information between rooms. You can either carry all hand-written notes (index cards, post-its, flip-charts, etc) and put them back in the wall and tables, or upload them on a digital format and carry it on your laptop. The former option is a waste of time. The later lessens people interaction. There is no replacement for writing on and tearing apart colorful post-it or index cards. Once the information goes to the computer, it will not get back to paper. People interaction reduces as there is nothing on the table to gather around.

colorful post-its

Do not bring a list of existing user stories to the Inception. I am sure there is a list somewhere (excel, Jira, or alike). Use it for reference, but don’t use it for driving the Inception sessions. Print a few copies and bring them to the war room. Let people consume it if required. Try not to read items from a list during a collaborative session. In fact, do not build a list while in a collaborative session.

Group people around colorful post-its. Write and place post-its either on the table or at the wall.. Talk about them. Write a few more. Tear them apart. Make use of colors. Reorganize it. The collaboration from using such basic, low-fi technology— colorful post-its and pen—cannot be matched by any digital alternative (file sharing, projector, spreadsheets, etc).

The picture below depicts a great example from my last Inception. Without a previous encoding, the team decided to use the colored small post-its for personas. User Stories (in green post-its) were placed on white index cards containing numbers and estimated (with notes on the back).


On future posts: user story mapping for driving Inception, and a few notes on Inception facilitation

Scopes in Rails

Jaco Pretorius

Fri, 02/03/2012 - 09:00

Scopes is one of the features in Rails that I only learned about through reading The Rails 3 Way. It doesn’t seem to be a feature that’s used very often, but I think it can make your code a lot neater if it’s used correctly.

I’m going to illustrate how scopes can be used with a simple example.

A Product Application

I’ve created a very simple application to manage products. All the basic functionality is there – view/create/edit/delete.

List of Products

The controller code for viewing the list of products is very simple.

def index
  @products = Product.all
end

You’ll notice (in the screenshot) that each product has a status – ‘Available’ or ‘Coming Soon’. Let’s imagine that the user wants to be able to view all Available products. How might we accomplish that?

The easiest way to do this would be to add a separate route and action which simply filters the products to only those with the correct status. First, let’s add the route.

get 'products/available' => 'products#available', :as => 'available_products'

Now we only need to add the controller action.

def available
  @products = Product.where(:status => 'Available')
  render 'index'
end

This certainly works, but there’s a cleaner way of doing this.

Using a named scope

Instead of using the where method in the controller, we can move the behavior to the controller. We could create a class method to expose this filter, but Rails has a much nicer way – named scopes. Let’s see what that looks like.

class Product < ActiveRecord::Base
  scope :available, where(:status => 'Available')
end

Now our controller code is much cleaner and easier to read.

def available
  @products = Product.available
  render 'index'
end

And everything still works exactly as before. Hurrah!

Using default scope

As I mentioned, we also have the functionality to delete a product. However, we might not want to delete the record out of the database – we simply want to mark it as deleted. (There are a number of reasons why we might choose to do this – for example, we might have transactions linked to a product)

Here’s the code for deleting a product.

def destroy
  @product = Product.find(params[:id])
  @product.update_attribute(:deleted, true)
  redirect_to products_path
end

Let’s take another look at our list of products.

List containing Deleted Products

The deleted products are showing up in our regular list! While this makes sense (since we’re simply flagging them as deleted – not actually deleting them), this is definitely not what we want. So how do we fix that? One way would be to update all our queries to include :deleted => false. As you probably guessed, Rails has a neater way of doing this – using default scope.

class Product < ActiveRecord::Base
  default_scope where(:deleted => false)
  scope :available, where(:status => 'Available')
end

As the name implies, default_scope changes the default list of products being returned. Our list of products no longer shows deleted products. For example, Product.all will exclude deleted products. Pretty neat.

What if we want to bypass the default scope and actually get all products? For example, I might want to have an admin function that lists all unavailable products – meaning products which have their status set to something other than Available. We can do that by using the unscoped method.

def unavailable
  @products = Product.unscoped.where('status <> ?', 'Available')
  render 'index'
end

Pretty cool.

Conclusion

This is one of those pieces of functionality that you probably won’t miss until you know it’s around. It can definitely clean up your code and make it a bit more readable. I would probably be wary of using default_scope, but in certain scenarios it probably makes sense.

If you would like to play around with this code you can find it on Github. Happy coding.

Surviving change

Maria Ocampo

Fri, 02/03/2012 - 02:14

My life is changing so fast at this point that I can barely cope. As exciting as it is to the outside, it is uncomfortable, it makes me feel insecure and I start feeling the need  of proofing myself once again, even if I thought I was completely exhausted of this process. What is the world demanding of me? Of everyone? Can we even say “enough is enough”?

As the saying goes, the only people who like change are busy cashiers and wet babies. We find change disorienting, creating within us an anxiety similar to culture shock, the unease visitors to an alien land feel because of the absence of the familiar cues they took for granted back home.

Unfortunately as much as I (and you would too, I bet)  would like to think that your life will become stable at some point, the matter of fact is that in this century, as an active member of the global economy…

Change is a business fact of life

Is your company is currently undergoing major changes that will affect the lives of all of its employees? These changes are probably in response to the evolving needs of your customers. They are made possible because of improvements in telecommunications and digital technology. They are likely guided by accepted principles and practices of total quality management. And you can expect that they will result in significant improvements profitability–a success that all employees will or will not share. Because our customers’ needs are NOW, we must make changes swiftly, which means that all of us must cooperate with the changes, rather than resist them.

But people do not like change all that much. It doesn’t matter how good you are at adapting, there will always be those fluctuating moments when change gives you the feeling of an “empty stomach”. We tend to respond to change the same way we respond to anything we perceive as a threat: by flight or fight. Our first reaction is flight–we try to avoid change if we can,  we seal ourselves off from those around us and try to ignore what is happening. This can happen in the workplace just by being passive. We don’t volunteer for teams or committees; we don’t make suggestions, ask questions, or offer constructive criticism. But the changes ahead are inescapable. Those who “cocoon” themselves will be left behind.

Even worse is to fight, to actively resist change. Resistance tactics might include negativity, destructive criticism, and even sabotage. If this seldom happens at your company, you are fortunate.

But you have to realize… we are not bunnies… Rejecting both alternatives of flight or flight, we seek a better option–one that neither avoids change nor resists it, but harnesses and guides it.

In the life I chose, I have looked for individual practices to enable change to become the means to my goals, not a barrier to them. Still with all the different practices and approaches I have taken here, things are easier said than done.

Both fight and flight are reactions to perceiving change as a threat. But if we can change our perceptions, we can avoid those reactions. An old proverb goes, “Every change brings an opportunity.” In other words, we must learn to see change as a means of achieving our goals, not a barrier preventing us from reaching them.

Another way of expressing the same thought is: A change in my external circumstances provides me with an opportunity to grow as a human being. The greater the change is, the greater and faster I can grow. If we can perceive change along these lines, we will find it exciting and energizing, rather than depressing and debilitating.

Yet this restructuring of our perspective on change can take some time. In fact, coping with change follows the same steps as the grieving process.1 The steps are shock and denial that the old routine must be left behind, then anger that change is inevitable, then despair and a longing for the old ways, eventually replaced by acceptance of the new and a brighter view of the future. Everyone works through this process; for some, the transition is lightning fast, for others painfully slow.

I have tried different practices of meditation and collective intelligence to adapt better to this, and if it is truth that this is a great help, for a human being with a standard level of consciousness (me), there is still a long way to go.

Different individual approaches to change in organizations

As one writer put it recently:

Our foreparents lived through sea changes, upheavals so cataclysmic, so devastating we may never appreciate the fortitude and resilience required to survive them. The next time you feel resistant, think about them and about what they faced–and about what they fashioned from a fraction of the options we have. They blended old and new worlds, creating family, language, cuisine and new life-affirming rhythms, and they encouraged their children to keep on stepping toward an unknown but malleable future.

Human beings are created remarkably flexible, capable of adapting to a wide variety of environments and situations. Realizing this can help you to embrace and guide change rather than resisting or avoiding it.

Corporate employees typically follow one of four decision-making styles: analytical, directive, conceptual, and behavioral. These four styles, described in a book by Alan J. Rowe and Richard O. Mason,3 have the following characteristics:

Analytical Style  - technical, logical, careful, methodical, needs much data, likes order, enjoys problem-solving, enjoys structure, enjoys scientific study, and enjoys working alone.

Analytical coping strategy - You see change as a challenging puzzle to be solved. You need plenty of time to gather information, analyze data, and draw conclusions. You will resist change if you are not given enough time to think it through.

Conceptual Style - creative and artistic, future oriented, likes to brainstorm, wants independence, uses judgement, optimistic, uses ideas vs. data, looks at the big picture, rebellious and opinionated, and committed to principles or a vision.

Conceptual coping strategy  - You are interested in how change fits into the big picture. You want to be involved in defining what needs to change and why. You will resist change if you feel excluded from participating in the change process.

Behavioral Style - supportive of others, empathetic, wants affiliation, nurtures others, communicates easily, uses instinct, avoids stress, avoids conflict, relies on feelings instead of data, and enjoys team/group efforts.

Behavioral coping strategy - You want to know how everyone feels about the changes ahead. You work best when you know that the whole group is supportive of each other and that everyone champions the change process. If the change adversely affects someone in the group, you will perceive change as a crisis.

Directive Style - aggressive, acts rapidly, takes charge, persuasive and/or is manipulative, uses rules, needs power/status, impatient, productive, single-minded, and enjoys individual achievement.

Directive coping strategy  - You want specifics on how the change will affect you and what your own role will be during the change process. If you know the rules of the change process and the desired outcome, you will act rapidly and aggressively to achieve change goals.

You resist change if the rules or anticipated results are not clearly defined or when you are not involved in the process.

But what to do when change is imminent and you have not been even asked?

1. Get the big picture. - Sometimes, not only do we miss the forest because of the trees, but we don’t even see the tree because we’re focused on the wood. Attaining a larger perspective can help all of us to cope with change, not just the conceptualists. The changes under way in global organizations today follow at least four important trends, which I believe are probably reflective of businesses in general.

2. Do some anchoring. - When everything around you is in a state of flux, it sure helps to find something stable that isn’t going to change, no matter what. Your company’s values (whether articulated or not) can provide that kind of stability for you around decision making. Concentrate in the identity of your organization and make decisions based on your own good and that of the organization as a whole.

3. Keep your expectations realistic. - A big part of taking control of the change you experience is to set your expectations. You can still maintain an optimistic outlook, but aim for what is realistically attainable. That way, the negatives that come along won’t be so overwhelming, and the positives will be an adrenaline rush. Here are some examples:

    • There will be some bumps along the road. We shouldn’t expect all of the changes ahead to be painless, demanding only minimal sacrifice, cost, or effort. In fact, we should expect some dead ends, some breakdowns in communications, and some misunderstandings, despite our best efforts to avoid them. We may not be able to anticipate all of the problems ahead, but we can map out in general terms how we will deal with them.
    • Not everyone will change at the same rate. The learning rates of any employees will distribute themselves along a bell curve. A few will adapt rapidly, most will take more time, and a few will adjust gradually. Also, many younger employees may find change, especially technological innovations, easier than those older. The reason may be, as one observer explains, “Older people’s hard disks are fuller.”4 On the other hand, you may find some younger ones surprisingly reluctant to take on a new challenge.
    • The results of change may come more slowly than we would want. As participants in an “instant society,” conditioned by the media to expect complex problems to reach resolution in a 60-minute time frame, we may find the positive results of change slow to arrive from the distant horizon. If we are aware of this, we won’t be so disappointed if tomorrow’s results seem so similar to today’s.

4. Develop your own, personal change tactics. Get plenty of exercise, plenty of rest, and watch your diet. Even if you take all the right steps and follow the best advice, undergoing change creates stress in your life, and stress takes energy. Aware of this, you can compensate by taking special care of your body.

Invest time and energy in training. Sharpen your skills so that you can meet the challenges ahead with confidence. If the training you need is not available in your organization, get it somewhere else, such as the community college or adult education program in your area.

Get help when you need it. If you are confused or overwhelmed with the changes swirling around you, ask for help. Your manager, or co-workers may be able to assist you in adjusting to the changes taking place.

Make sure the change does not compromise either your company values or your personal ones. If you are not careful, the technological advances jostling each other for your attention and adoption will tend to isolate you from personal contact with your co-workers and customers. E-mail, teleconference, voice-mail, and Intranet can make us more in touch with each other, or they can keep us antiseptically detached, removed from an awareness that the digital signals we are sending reach and influence another flesh-and-blood human being.

Aware of this tendency, we must actively counteract the drift in this direction by taking an interest in people and opening up ourselves to them in return. We have to remember to invest in people–all of those around us–not just in technology.

The “new normalcy”

Ultimately, we may discover that the current state of flux is permanent. After the events of September 11, Vice President Richard Cheney said we should accept the many resultant changes in daily life as permanent rather than temporary. “Think of them,” he recommended, “as the ‘new normalcy.’”

You should take the same approach to the changes happening at your workplace. These are not temporary adjustments until things get “back to normal.” They are probably the “new normalcy” of your life as a company. The sooner you can accept that these changes are permanent, the better you can cope with them all–and enjoy their positive results.

And if change, constant change is the rule of your life and your industry… if you can never expect for “things to settle down”… then, please be welcome to my club. For those who like it, it  is exciting, enticing, fabulous and never stopping… yet, remember to sit down from time to time to catch your breath and to realize the beauty of it all.


Links for 2012-02-02 [del.icio.us]

Sahana Chattopadhyay

Fri, 02/03/2012 - 02:00
  • 7 Ways to Bring Your Community into the Content Creation Process | Business 2 Community
    The value of real-time content can be short-term, but high-yield. When a window of opportunity presents itself — say, due to a breaking news item or a special event —relevant content has tremendous potential to be viewed (and appreciated) by a large audience. Once that window closes, however, the content’s value and potential drops sharply. It’s a tricky proposition that requires being in the right place at the right time, ready to turn around and execute on short notice.

邮件:新的堆积成山的纸

Chen Jinzhou

Fri, 02/03/2012 - 02:00

2009年在新加坡工作的时候,我的单月电子邮件数量达到了最大:2000多封。以22个工作日大致算了一下,每天约100封,以8小时工作时间计算,每隔不到5分钟就有一封新的邮件收到。我知道这不算太坏。不是所有的邮件需要你处理,大多数情况下你只需要看一眼标题就够了。

那么,这些种类繁多的邮件中包含什么呢?无所不含。新发起的对话,需要审批通过的议题,同意,顶,周末去哪里玩,新员工加入了大家欢迎等等。如果我们将这些电子邮件纸质化,每封邮件打印在一张A4纸上,那么每个月每个人都将得到一本2000页的当月邮件记录。2000页是个什么概念呢,红楼梦120回加起来也不过4公分厚,2000页加起来就是8公分,大概就是大多数人拳头的高度。

这并非是想象。若干年前许多企业嚷嚷着要无纸化办公。于是这些信息开始转移到电子媒体上。堆积成山的纸片并没有神奇般的消失,经过人们几年的学习和适应,这东西有了新的名字,叫电子邮件。

我一定不是最繁忙的人。作为稍具自动化观念的人,我还知道将邮件进行分类、过滤、归档。然而,既然某些邮件注定不会被读过,他们的存在又意义何在呢?

Cool hunting and Augmented Reality

Lindsay Ratcliffe

Fri, 02/03/2012 - 00:44

Cate Trotter from Insider Trends was also presenting at theThoughtWorks Retail Agility conference the other day. Being a big fan ofWilliam Gibson’s ‘Pattern Recognition’ series I was very excited to meet areal-life ‘cool-hunter’.
Cate’s day job is looking for trends, looking for patternsthat exist in subcultures that will come to influence main stream culture. Shetakes businesses on ‘trend tours’, to show them where the hip and happeningstarts.  She had a dizzying amountof great examples of cutting edge inovation in the retail sector that drivesnot just compelling customer experiences but also disruptive experiences. Realcreative ways of engaging customers and creating buzz. 
One of the underlyingthemes that seemed to emerge for me was the subtle shift away from ‘hard sell’and the focus on the immediate returns, to building brand and relationships ina more meaningful and engaging way. Which in the current economic climate isnot only refreshing but a very insightful strategy for long term survival.While most retailers are scrabbling to claim their share of shoppers’ limitedwallet with sales, discounts and ‘special-purchase’ cheap and nasty give-aways,to secure short-term income, some creating brand experiences that willencourage loyalty long after the event is over. 
Take Airwalk as a greatexample: They created and ‘Invisible Pop‐Up Store’ enhanced with augmentedreality to create buzz around the very limited edition Goldrun sneaker. So cool! Or Wetseal, who have taken theconcept of user-generated content and have created the capability to ‘crowdsource’outfits.
Big thanks to Cate.

Cross-Functionality in Scrum

Paulo Caroli

Fri, 02/03/2012 - 00:18

Scrum recommends that a team should feature all the skills required in order to deliver the releasable product increment by the end of the Sprint. 
Why is it a good thing to have all the skills needed? It is all about dependencies. We try to design our software systems to be loosely coupled and highly cohesive. The same principles apply to team composition. We want our team to be like a special unit, self sufficient and able to deliver on the chosen assignment.So, what would happen if one significant skill is missing from the team? The team will have a strong external dependency and will need to ask for support from external sources. This is a huge risk. Will the team get access to the person at the right time for the right duration? This creates an additional drag factor and affects the delivery date or reduces the scope of the product to be delivered.
Scrum does not require cross-functional teams, it only recommends them. In practice they have shown to be a significant boost for productivity. Especially in combination with self-organization.
Often it is misunderstood that cross-functional means that any person in the team needs to be able to do all the upcoming work. This is wrong. The unit that needs to be cross-functional is the development team. The dev team has the responsibility to self-organize in order to maximize the usage of its skills.  Hence, the team might be composed of specialists only, however the sum of the individuals needs to possess all required skills.
Nevertheless, as described above, if you only have specialists then you will have rather large teams, as for every skill you will need at least one developer. This will cause larger than needed teams and probably all other kinds of problems: part time team members based on FTE mathematics, work organized by activity not by feature, bad ‘unskilled' estimates, ...
Therefore agile teams favor generalists, developers with a rounded and versatile skill set. I like to use the term specialized generalists, strong all-rounders with one top notch special area.

MongoDB: rename a field in all collections

Franklin Dattein

Thu, 02/02/2012 - 23:54

I would like to share a script to rename all fields in a collection. It can be used to update field values, as well.

var collections = db.getCollectionNames()

collections.forEach(function(collectionName) {
	var collection = db.getCollection(collectionName)
	collection.update ( {}, { $rename : { "oldFieldName" : "newFieldName" }} );
});

Design vs User Experience

Jaco Pretorius

Thu, 02/02/2012 - 09:00

One of the topics that keeps popping up around the office is that of design vs user experience. At first glance you might consider them to be the same issue – both involve presenting data and actions to the user in a way that they find appealing and easy to use. While they address the same issue, I think that these practices do so with a similar, yet different, goal in mind. The best differentiation might be to say that design is focusing on making the application visually appealing while user experience focuses on making the application easy to use.

There is a massive amount of overlap between these two approaches – they’re implicitly linked. A large part of making something easy to use is to make it visually appealing, and a large part of making something visually appealing is to make it easy to use! I try to think of it as two different targets within user interface design. Design tends to focus on the visual appeal as the end goal, while user experience tends to focus on ease-of-use as the end goal. The key word here is focus – I’m not saying that design doesn’t consider ease-of-use and vice versa.

Why is this distinction important? While these two approaches have a very similar goal in mind, they follow very different development cycles. Most design firms will happily create the entire design up front, before the application is anywhere near completion. User experience – on the other hand – can’t guarantee the design up front and will evolve the design over time. The design will evolve as the user experience is refined and improved.

Case in Point

The Flight Card iPhone app is a good example of this distinction. It’s one of the best-looking apps out there. Just look at it – absolutely stunning. The fonts, colors, layout – everything is just perfect. You would think this would be one of the top-selling apps out there.

Not quite. A mere three stars out of 20 reviews? What went wrong? Let’s take a look at some of the reviews.

This app is quite visually appealing, but it has some issues that make it harder to use. You cannot add trips more than 3 days in the future (hard when you want to put an literary in). You can’t swipe between flights.

First, the app is stunningly beautiful. It’s simply a joy to look at. But it’s missing some basic functionality. First, there is no way to swipe between cards. You need to menu back to list view and choose the next card. Not so big a deal except for the page dots at the top. You can tap the dots and they will change as if you’re changing cards, but you don’t change cards. And the dots are maddeningly hard to hit.

It seems that while the visual design is off the charts, the user experience is terrible. (I haven’t used the app, I’m only going on what the reviews say) This is perhaps an extreme example, but I’m trying to point out that a bad user experience means a bad app.

Guarantees

At the moment the popular approach is the design approach. No doubt about it. I think from a client’s point of view this is regarded as the ‘safe’ approach. Because we start out with the design and do pretty much the entire design up front it’s guaranteed – we have a good idea of what the final application will look like, even though we don’t know exactly how it will work.

The user experience approach is perhaps considered to be the ‘risky’ approach. We don’t have a good idea of what the application will look like – we only know that we will get much more input into the design and the user experience as the application is built. We’re almost guaranteed to end up with a better user experience, but because we don’t have a good idea of what the final application will look like, it feels like we’re taking a risk.

History repeating itself?

I think we’re facing a similar challenge to the one we faced 10 to 15 years ago – when agile started being introduced. Clients felt safe with the waterfall approach – all the planning being done up front meant that we had a very good idea of what the software would look like in the end. Then agile came along and suggested that the initial idea is less important, and we should rather focus on refining this idea as we go along.

Selling agile 10 years ago was probably similar to selling the user experience today. I do think that approaching the user interface from a user experience point of view is inevitable – it simply makes the most sense from both the user’s and the client’s perspective.

Super Movie! Literally!

Rajiv Mathew

Thu, 02/02/2012 - 07:25

Recently I watched Upendra's "Super". It really is a soopar movie. The storyline is innovative and ideas are fantastic. Hats off to Upendra for always thinking different. Hope this movie gets remade in Hindi or English sometime, with some polishing of some scenes.

Surprised I’m still surprised

Lindsay Ratcliffe

Thu, 02/02/2012 - 03:07

I presented at the ThoughtWorks Retail Agility Conference onAgile Experience Design. Specifically I was looking at how retailers can takeadvantage of AXD to design, develop and deliver compelling, shopper-centric,omni-channel experiences that delight customers and drive business success.I’ve been doing experience design for a long time. I’ve beendoing agile experience design for a sizeable proportion of that time. When Iwas preparing the presentation I got that pre-presentation feeling, similar tothe pre-publication feeling I got when reading the draft manuscript of ourAgile Experience Design book. I was worried that I had nothing to say. I’vebeen doing this stuff for so long that it has just become second nature to me andfeels like common sense.
But no fear! A number of people approached me immediatelyafter the presentation and thanked me for talking about the approach, about howinspirational it was and how it’s really got them thinking about how they cando things differently and most important, make a difference. Perhaps to otherexperienced practitioners in the same field, what I’m talking about isn’tnecessarily all that different but it certainly seems to make a difference tomany of the business and IT people that I meet along the way.
I guess that is similar to what James Box and Cennydd Bowles said in their book ‘Undercover User Experience Design’, “The fundamentals of UX design…are easy to learn but difficult to put intopractice.” So I guess what I bring to the table is the benefit of my experienceand the context of all of my learnings in different situations.

向前的张力

Chen Jinzhou

Thu, 02/02/2012 - 02:00

高中的时候,每个月都要从遥远的县城往返乡下的老家,都要经过一段常常的蜿蜒的小路。夏天的早晨走过这段路,来不及蒸发的露水总是把鞋子弄湿,于是踩着潮潮的鞋子去赶一天一班的班车。傍晚的时候,晚霞总是很漂亮,夕阳在露出半个脸的时候将云彩烤得灿红。走着走着,天经常就黑了,不远处的坟地偶尔冒出的鬼火已经不再像儿时那般吓到我,但仍然心里发毛着加快脚步往家跑。

那时候想的东西如同每个步入高中的少年一般。望着天边还未散去或者刚刚出来的星星,吹着若有若无的晨风或者晚风,我在想着一个极其庸俗的目标:要考上大学。

有时候也会怀疑。秋天的时候田地里一捆捆稻草就那样摆在哪里,连飘落的叶子、逐渐凋零的秋树也开始影响着自己的判断。仍然会偶尔开小差,课堂上看漫画。但似乎有一种纠正的力量不断的提醒,在偏离方向一点之后更加用功的学习。这时候那些课外读物(比如尼采的书,各种武侠小说,鲁迅)、胡思乱想的想法居然形成了某种神奇的力量,在不比最好的学生更用功的情况下,考试成绩居然还不错。

最后果然上了大学,没考。

后来见得多了,越发觉得这段经历的珍贵。在做Buffalo Ajax的那段时间里,每天晚上写到很晚,但精力充沛。那种做有意义事情的感觉充盈全身,吃得少,睡得也不多,产量却颇丰。这种感觉能分析吗?虽然读理科,虽然逻辑是吃饭的根本,但不得不说这种感觉很难分析。那种纯粹的、毫无任何功利目的的神秘力量,指引产生出的令人不可思议的结果,完全是任何过程所分析不出的。

唯一具备共性的东西是,那种宁静状态下的反省。曾子说要日省吾身,乔布斯说每天要对着镜子问自己。那种向前的张力正由此而来吧。

Links for 2012-02-01 [del.icio.us]

Sahana Chattopadhyay

Thu, 02/02/2012 - 02:00

Web driver script

Manoj Tharayil

Thu, 02/02/2012 - 00:34

Hasan from Trainline shared with us Selenium WebDriver script.

I was using Selenium before Web Driver came into the picture. Need to try this out.

 

using System;

using NUnit.Framework;

using OpenQA.Selenium;

using OpenQA.Selenium.IE;

using OpenQA.Selenium.Remote;

using OpenQA.Selenium.Support.UI;

namespace WebDriver

{

    [TestFixture]

class TrainlineTest

    {

        [Test]

public void webDriverTest()

        {

var ieCapabilities = DesiredCapabilities.InternetExplorer();

            ieCapabilities.SetCapability(InternetExplorerDriver.IntroduceInstabilityByIgnoringProtectedModeSettings, true);

var driver = new InternetExplorerDriver(ieCapabilities);

            driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(10));

           driver.Navigate().GoToUrl("http://buytickets.thetrainline.tw.testttl.com");

            driver.FindElement(By.Id("OriginStation")).SendKeys("London");

            driver.FindElement(By.Id("DestinationStation")).SendKeys("Manchester");

            driver.FindElement(By.Id("SingleJourneyCheckBox")).Click();

new SelectElement(driver.FindElement(By.Id("AdultsTravelling"))).SelectByText("2");

IWebElement query = driver.FindElement(By.Id("outwardDate"));

            query.SendKeys(Keys.Control + "a");

            query.SendKeys("23/02/2012");

            driver.FindElement(By.Name("extendedSearch")).Click();

Assert.IsTrue(driver.FindElement(By.Id("showTicketsIdButton")).Displayed, "Show Prices Button Not Present");

        }

   }

}

[原]On Story Estimation: 单一职责原则

Guanglei Li

Wed, 02/01/2012 - 23:41

 

估算是软件开发中还没有很好的解决的一个问题, 因此争论也很多, 水平也参差不齐. 我无法给出更好的估算技术, 只是想抛出几个问题和观点

 

1. 单一职责和问题优先

让我们从几个常见的问题开始:

  • 估实际工作量(人天)还是相对大小?
  • 如果两个类似的Story有一部分实现代码是可以彼此复用的, 那么它们的估算应该是一样的还是不一样的? 还是把复用的那部分拆出来单独估?
  • 修复Bug的工作量要不要估算? 要不要算进每个迭代的"速度"里?
  • Team一起估还是找一个人来估?
  • 做了一段时间后, 要不要重估?

这些问题通常会引起争论. 每种观点都有自己合理的一面, 这也是争论的前提之一. 但真正导致争论的, 是大家都忘了自己估算的目的, 忘了谁如何消费这个估算:

  • 有时我们为了投标报价
  • 有时为了跟客户讨价还价
  • 有时为了team自己收集数据发现问题
  • 有时需要在两种实现方案之间做取舍
  • ...

这么多目的, 怎么可能有一种方法满足所有的需求呢? 就算有, 那么这种通用的方法在某一个目的上也有可能不如专为这个目的而生的估算方法准确

我的观点是估算方法要与估算目的结合, 而估算本身要与目的分开:

  • 单一职责原则: 一个数, 不要赋予它太多含义. 它应该是明确的, 比如就是某对Pair要做多少天, 比如就是需要多少行代码, 比如就是相对复杂度是什么, 而不需要关心你拿这些数去做什么
  • 问题决定方案: 而你拿这些数来用的时候, 要为不同的目的选择不同的数, 不同的方法, 做些计算, 把整理后的结果呈现给受众, 原始的估算要不要暴露出来完全取决于当时的场景.

但这不妨碍人们去追求一种通用的估算方法满足大多数情况下的需求. 这没问题, 不过我们也可以从另外一个角度来解决估算问题

 

2. 消除估算的必要

因为估算始终是不准的, 大量的精力花在这上面, 不如想办法尽可能绕开它, 让真实的进度,成本来说话. 所以一个思路就是消除不必要的估算需求.

敏捷方法? 持续交付?

这是有帮助的, 尤其有助于消除对长期估算的准确度的需求. 你依然需要对整个项目的工期有个整体的把握, 但不必太精确, 当实际进度偏离的时候你能及时发现. 或许你还需要迭代级别的估算, 但因为任务比较具体, 此时的估算无论何种方法都可以, 因为所需的信息都相对明确


作者:chelsea 发表于2012-2-1 21:41:12 原文链接 阅读:662 评论:2 查看评论

Google Drawing – another great tool for distributed retrospectives

Paulo Caroli

Wed, 02/01/2012 - 12:09
Yesterday I used Google Drawing for a distributed retrospective. I was very pleased with the tool.

The team members talked over a phone bridge (skype or similar would work as well).

Google Drawing was used to collect data on the main data gathering exercise for the retrospective.

Here is the picture generated at the end of the retrospective.

How did I use Google Drawing?

  1. I created a new document (empty canvas)
  2. I prepared the canvas; in this case I placed a picture representing the speed car – abyss retrospective exercise in the middle of the canvas with 4 text boxes identifying the 4 exercise quadrants.
  3. I shared it as a public document and emailed the link to the whole team
  4. I gave the instruction verbally and asked people to use Text Boxes for their notes
  5. I changed the text box color to blue for the notes which became action items
  6. I exported the drawing as a .png and emailed it to the whole group

Simple is good!

The only problem we faced: a few of us got an error message when creating a text box (I believe this was due to all 10 team members creating text boxes at the same time). But this only happened a few times. A simple refresh took the problem away.

Agile Experience Design - the book

Lindsay Ratcliffe

Wed, 02/01/2012 - 09:39

Wow how remiss of me! I have completely failed to blog aboutmy biggest project of last year – the book! In November last year (2011) Marc McNeil and I published Agile Experience Design: A digital designers guide to agile, lean and continuous. To our knowledge it’s the first book to marketabout the topic of experience design in agile.
How it came aboutThere has been a lot of banter on the subject for a goodnumber of years on various SIG groups, and lots of great presentations deliveredat various conferences and published on the web that have sought to explain howto marry the two. However there was no one go to comprehensive reference point.I remember when I started with ThoughtWorks (agile customsoftware experts) as the only UX person in Australia wishing that I could finda definitive guide book on how to do UX in an agile environment. It is a verydifferent way of working but I was keenly aware that someone somewhere musthave solved the problem, and that I didn’t need to work it out for myself. Thebook ended up being the book I wished that I could have read back then.
I joined forces with Marc when I moved back from Australiato the UK and realised we were aligned in our thinking on the subject. We werealso still surprised that no one had published a book on the subject and so weset about doing just that.
An non-movable feastFrom start to finish we had FIVE months. Prior to signingthe contract I talked to Martin Fowler and Jez Humble,both successful authors, about the timescales and the unanimous opinion wasthat we were mad! Jez said ‘ You need at least 18 months to write the firstdraft, then you need some decompression time, then you need time to rewrite andedit.’ So we went back to the publisher, in the hope of revising the proposedpublication date. However we were faced with a ‘deal or no deal’. Marc and Iboth laughed and agreed that we might as well die trying as not try at all.
A very non-agile processIn agreeing to the terms we were also asked to commit to thelength of the book. At this point all we had written was two paragraphsdescribing the essence of the book. We had no idea. I flicked through a coupleof notable books on my shelf, of the ilk that I thought ours might be, stuck afinger in the air and suggested 100,000 words. When we submitted our firstdraft, it was 135,000 words long. Naively we had not appreciated that 100,000words had been cast in stone. We then had a very tough process to cut 35,000words (over a third of the final book) from the manuscript (and still deliveron time).
Concurrent workingSo five months is a doable time-frame, just, if you are afull-time author perhaps. But hey, we both had full-time jobs. This is the job thatgive us the experience and expertise to be able to write books. We both alsohave families. So we begged borrowed and stole time and worked bloody hard forfive intense months to produce the book. We are grateful to our families inparticular who made the bulk of the sacrifices, for allowing us to realise ourambition.
Collaborative andfeedback drivenTwo aspects that were sacrificed as a result of the timeframewas the ability to collaborate and also solicit feedback from peers andcolleagues on the work in progress. We started off with the best of intentionsand were able to include some contributions and get some feedback, but not asmuch as we might have liked. If word count and time had permitted we would haveliked to have included more anecdotes and lessons learnt from other practitioners.
Test and learnThis book was only ever intended as a guide, rather than arecipe book. It would be a contradiction in terms to say that there’s a onesize fits all approach to agile experience design. Every project will bedifferent because of the budget, timescales and people/process/technologyconstraints. However to stay true to the nature of agile experiencedesign I’m keen to hear about people’s experiences and how they have aplied,adopted or adapted some of the concepts and ideas in the book. I promise toshare the finding and attribute them to the contributers either on theaccompanying website (if I ever get the time to add some content to it) orperhaps even in version 2.0.

Keeping your routes RESTful

Jaco Pretorius

Wed, 02/01/2012 - 09:00

A while ago I blogged about RESTful routing in Rails. While Rails does help us in getting started with RESTful routing, it’s still very easy to lose your way and make a real mess of your routes.

To illustrate this, I’m going to recreate a problem I recently came across when working on RapidFTR – one of the social projects I’m involved in at ThoughtWorks.

Let’s see some code

To start off, I’m going to extend the example I was using in my last post about routing. I’m basically managing products – I’ve created a Product model, a Products controller and I have a single entry in my routes configuration.

resources :products

When I run rake routes I get the following list of routes.

List of routes

Right, now we have a new requirement – we need to be able to mark a product as a duplicate. We might have 2 admin users adding products and somehow we end up adding the same product twice. We don’t want to delete it (since some users might have bought the duplicate, etc) so we’re only going to mark it as a duplicate and link it to the non-duplicate product.

At the moment I can perform two actions on each product – view and edit. So I now want an additional action – mark as duplicate. This should take me to a page where I can select the non-duplicate version of the product.

Doing it the wrong way

Sounds easy enough – I’m probably going to need two additional actions on my controller – one to view the page and one to handle the page being submitted. To get started, let’s add 2 new routes.

get 'products/duplicate/:id' => 'products#new_duplicate', :as => 'new_duplicate'
post 'products/duplicate/:id' => 'products#create_duplicate'

Running rake routes reveals that we now have two additional routes.

Two Additional Routes

Now I just need to add two method to my Products controller. This could be done better (moving some of the functionality into the Product model, for example) – I put all the code into the controller to make it clear what’s going on.

  def new_duplicate
    @product = Product.find(params[:id])
    @all_products = Product.where(['id <> ?', params[:id]])
  end

  def create_duplicate
    @product = Product.find(params[:id])
    @duplicate_of = Product.find(params[:duplicate_of_id])
    @product.duplicate = true
    @product.duplicate_of = @duplicate_of.id
    if @product.save
      redirect_to products_path
    else
      render 'new_duplicate'
    end
  end

We can mark a product as duplicate! Hurrah! Are we done?

Doing it the right way

While this code certainly works, I don’t think it’s really the Rails way of doing it. It’s actually quite easy to end up with too many methods on your controllers – to avoid this, it helps to think in terms of resources, rather than models and controllers.

In this case, we can think of duplicates as being an additional resource. So instead of marking an existing product as a duplicate, we’re creating a new duplicate resource. As you’ll see, this enables us to use the regular REST verbs – new, create, edit, update, etc. Enough talking, let’s see how this would actually work!

I’m going to start off by changing the routes. Here I’m using a nested resource.

resources :products do
  resource :duplicate, :controller => 'duplicates', :only => [:new, :create]
end

Now our routes look a bit nicer.

Nicer routes

You’ll notice that our route now includes the :product_id, instead of just adding an id at the end of the route. This enforces the idea of a duplicate resource, which is available on product resources.

Now I only need to move my two actions to the newly created Duplicates controller.

class DuplicatesController < ApplicationController
  def new
    # same code as before
  end

  def create
    # same code as before
  end
end
More Examples

I first came across this concept in The Rails 3 Way – the common example seems to be in creating sessions. Instead of adding login and logout methods to the Users controller, we can think of sessions being a resource. So we might end up with a Session controller with new, create and destroy actions. Which actually makes a lot more sense.

If you would like to have a look at the code you can find it on Github. Happy coding.

Angular and Selenium

Paul Hammant

Wed, 02/01/2012 - 02:00

I’m the co-creator of the original Selenium 1.0 (or 0.something as it was then) but I mean Selenium2 (nee WebDriver) of course. As UI’s get more sophisticated, the ability to locate the right part of the page for purposes of a query or interaction, is increasingly hard. I have personal experience with GWT that, on occasion, has driven me nuts and a pathological fear of the the super-advanced frameworks like Cappuccino

Finding Elements for and Angular app is not especially hard. Indeed all of Backbone, Knockout, KnockBack, Spine, Ember, BatMan (and the rest) will paint relatively normal HTML and you could get busy with ID, CSS or XPATH based locators for widgets. This blog entry could end there, but I’d like to do a “what if”.

Model-Centric Angular Locators

Here is the model for from monday’s blog entry again:

scope.cart = {
    authenticity_token: "xotITlobeVi6BUnqBIqAd4eFy5+yJf0JlSyog8rK5hQ=",
    items: [ 
        { 
            imgSrc: "index_files/grace-wireless-player.jpg",
            link: "grace-wireless-internet-radio",
            name: "Grace Wireless Internet Radio",
            price: 179.99,
            qty: 1
        },
        { 
            imgSrc: "index_files/plantronics-headphone.jpg",
            link: "plantronics-m40-mobile-in-ear-headset",
            name: "Plantronics M40 Mobile in Ear Headset",
            price: 9.99,
            qty: 2
        }
    ]
};

Here is part of the Angular page:

<tbody id="line_items">
    <tr ng:repeat="item in cart.items" class="">
        <td><img alt="{{item.name}}" ng:src="{{item.imgSrc}}" /></td>
        <td class="description"><h4><a href="http://demo.spreecommerce.com/products/{{item.link}}">{{item.name}}</a></h4></td>
        <td class="unit-price"> {{item.price | currency}} </td>
        <td class="operator"> X </td>
        <td class="quantity"><input style="width: 32px;" name="item.qty" ng:validate="integer:1:5" /></td>
        <td class="operator"> = </td>
        <td class="total"> {{item.price*item.qty | currency}} </td>
        <td class="total"><a ng:click="cart.items.$remove(item)" class="delete button">Remove</a></td>
    </tr>
    <tr class="totals">
        <td colspan="6"> </td>
        <td colspan="2" class="totals"> Subtotal: {{cart.items.$sum('price*qty') | currency}} </td>
    </tr>
</tbody>

What I would like to be able to do is locate parts of the page via the model that’s presenting them. Please excuse the Java:

WebElement quantityInput = webDriver.findElement(id("cart")).findElement(angularModel("items.$filter('{ name: \"plantronics-m40-mobile-in-ear-headset\"}').qty"));
quantityInput.sendKeys("15");

The initial findElement() is for the DIV that contains the ‘MyController’ Angular reference, and is from the regular Selenium2 API. The ‘angularModel’ method is a Selenium2 locator yet to be written for Angular interop. The expression within is more or less handed over the wire to an Angular enabled Selenium2 controlled browser, and the lookup is against the model of course. The Angular/Selenium integration piece returns the widget that is bound to that model node. If there is no widget bound directly, then an exception is thrown all the way back to the test script. If there is more than one widget bound directly to the model node, then a different exception is thrown. Use of ‘Quantity’ in formulae would be considered secondary.

I wonder if $filter() as opposed to a more desirable $find(). The former will subset an array to all that match. What we want in this instance is a way to find an single matching element.

View-Centric Angular Locators

Let’s look for something less model-centric in the page, using a hypothetical Selenium/Angular locator that traverses view references.

WebElement cost = webDriver.findElement(id("cart")).findElement(angularView("item.price*item.qty"));
assertThat(cost.getText(), equalTo("$123.45"));

Neat huh? We could find anything Angular managed whether output or input. Of course, Angular’s recommended test idiom is via Misko’s other stroke of genius – JsTestDriver.

Command Line: A Freebie

What if we had a custom control for Angular that allows an effective command line interaction with the current model:

.. snip ..
      </table>
    </div>
    <p class="actions"> <a ng:click="todo()" class="continue">Continue shopping</a>  
      or   <a ng:click="todo()" class="button checkout">Checkout</a> </p>
    <div ng:commandline style="width: 500px; height: 100px;"/>
</div>
.. snip ..

We could interact with that using the same model traversal techniques as described above. ThoughtWorker colleagues would love for a command line interface to our “time and expenses” app. It is currently a Rails app, and was previously a pre-Django Python app when it was the test bed for the earliest version of Selenium 1.0. Before that it was a Lotus Notes app. Anyway, it could easily be an Angular app with a command line for expedited time and/or expense entering:

Conclusion

In the race for dominance between Backbone, Knockout, KnockBack, Spine, Ember, Batman, Sammy YUILibrary, JavaScriptMVC, Broke, Fidel and my current favorite Angular, part of the criteria for winning is going to include:

  • Elegant left-to-right style model traversal expressions.
  • Selenium2 integration for low effort full stack testing.
  • A command line interface :)
  • Disclaimer


    ThoughtWorks embraces the individuality of the people in the organization and hence the opinions expressed in the blogs may contradict each other and also may not represent the opinions of ThoughtWorks.

    Individual feeds