Skip to content

Software Development Blogs: Programming, Software Testing, Agile Project Management

Methods & Tools

Subscribe to Methods & Tools
if you are not afraid to read more than one page to be a smarter software developer, software tester or project manager!

Feed aggregator

Episode 216: Adrian Cockcroft on the Modern Cloud-based Platform

Adrian Cockcroft discusses the challenges in creating a dynamic, flexible, cloud-based platform with SE Radio host Stefan Tilkov. After briefly discussing the definition of “cloud computing,” Adrian explains the history behind Netflix’s move to the cloud (which he led). After highlighting some of the differences that have developers and architects must face, Adrian talks about […]
Categories: Programming

R: Cleaning up and plotting Google Trends data

Mark Needham - Tue, 12/09/2014 - 19:14

I recently came across an excellent article written by Stian Haklev in which he describes things he wishes he’d been told before starting out with R, one being to do all data clean up in code which I thought I’d give a try.

My goal is to leave the raw data completely unchanged, and do all the transformation in code, which can be rerun at any time.

While I’m writing the scripts, I’m often jumping around, selectively executing individual lines or code blocks, running commands to inspect the data in the REPL (read-evaluate-print-loop, where each command is executed as soon as you type enter, in the picture above it’s the pane to the right), etc.

But I try to make sure that when I finish up, the script is runnable by itself.

I thought the Google Trends data set would be an interesting one to play around with as it gives you a CSV containing several different bits of data of which I’m only interested in ‘interest over time’.

It’s not very easy to automate the download of the CSV file so I did that bit manually and automated everything from there onwards.

The first step was to read the CSV file and explore some of the rows to see what it contained:

> library(dplyr)
 
> googleTrends = read.csv("/Users/markneedham/Downloads/report.csv", row.names=NULL)
 
> googleTrends %>% head()
##                   row.names Web.Search.interest..neo4j
## 1 Worldwide; 2004 - present                           
## 2        Interest over time                           
## 3                      Week                      neo4j
## 4   2004-01-04 - 2004-01-10                          0
## 5   2004-01-11 - 2004-01-17                          0
## 6   2004-01-18 - 2004-01-24                          0
 
> googleTrends %>% sample_n(10)
##                   row.names Web.Search.interest..neo4j
## 109 2006-01-08 - 2006-01-14                          0
## 113 2006-02-05 - 2006-02-11                          0
## 267 2009-01-18 - 2009-01-24                          0
## 199 2007-09-30 - 2007-10-06                          0
## 522 2013-12-08 - 2013-12-14                         88
## 265 2009-01-04 - 2009-01-10                          0
## 285 2009-05-24 - 2009-05-30                          0
## 318 2010-01-10 - 2010-01-16                          0
## 495 2013-06-02 - 2013-06-08                         79
## 28  2004-06-20 - 2004-06-26                          0
 
> googleTrends %>% tail()
##                row.names Web.Search.interest..neo4j
## 658        neo4j example                   Breakout
## 659 neo4j graph database                   Breakout
## 660           neo4j java                   Breakout
## 661           neo4j node                   Breakout
## 662           neo4j rest                   Breakout
## 663       neo4j tutorial                   Breakout

We only want to keep the rows which contain (week, interest) pairs so the first thing we’ll do is rename the columns:

names(googleTrends) = c("week", "score")

Now we want to strip out the rows which don’t contain (week, interest) pairs. The easiest way to do this is to look for rows which don’t contain date values in the ‘week’ column.

First we need to split the start and end dates in that column by using the strsplit function.

I found it much easier to apply the function to each row individually rather than passing in a list of values so I created a dummy column with a row number in to allow me to do that (a trick Antonios showed me):

> googleTrends %>% 
    mutate(ind = row_number()) %>% 
    group_by(ind) %>%
    mutate(dates = strsplit(week, " - "),
           start = dates[[1]][1] %>% strptime("%Y-%m-%d") %>% as.character(),
           end =   dates[[1]][2] %>% strptime("%Y-%m-%d") %>% as.character()) %>%
    head()
## Source: local data frame [6 x 6]
## Groups: ind
## 
##                        week score ind    dates      start        end
## 1 Worldwide; 2004 - present     1   1 <chr[2]>         NA         NA
## 2        Interest over time     1   2 <chr[1]>         NA         NA
## 3                      Week    90   3 <chr[1]>         NA         NA
## 4   2004-01-04 - 2004-01-10     3   4 <chr[2]> 2004-01-04 2004-01-10
## 5   2004-01-11 - 2004-01-17     3   5 <chr[2]> 2004-01-11 2004-01-17
## 6   2004-01-18 - 2004-01-24     3   6 <chr[2]> 2004-01-18 2004-01-24

Now we need to get rid of the rows which have an NA value for ‘start’ or ‘end':

> googleTrends %>% 
    mutate(ind = row_number()) %>% 
    group_by(ind) %>%
    mutate(dates = strsplit(week, " - "),
           start = dates[[1]][1] %>% strptime("%Y-%m-%d") %>% as.character(),
           end =   dates[[1]][2] %>% strptime("%Y-%m-%d") %>% as.character()) %>%
    filter(!is.na(start) | !is.na(end)) %>% 
    head()
## Source: local data frame [6 x 6]
## Groups: ind
## 
##                      week score ind    dates      start        end
## 1 2004-01-04 - 2004-01-10     3   4 <chr[2]> 2004-01-04 2004-01-10
## 2 2004-01-11 - 2004-01-17     3   5 <chr[2]> 2004-01-11 2004-01-17
## 3 2004-01-18 - 2004-01-24     3   6 <chr[2]> 2004-01-18 2004-01-24
## 4 2004-01-25 - 2004-01-31     3   7 <chr[2]> 2004-01-25 2004-01-31
## 5 2004-02-01 - 2004-02-07     3   8 <chr[2]> 2004-02-01 2004-02-07
## 6 2004-02-08 - 2004-02-14     3   9 <chr[2]> 2004-02-08 2004-02-14

Next we’ll get rid of ‘week’, ‘ind’ and ‘dates’ as we aren’t going to need those anymore:

> cleanGoogleTrends = googleTrends %>% 
    mutate(ind = row_number()) %>% 
    group_by(ind) %>%
    mutate(dates = strsplit(week, " - "),
           start = dates[[1]][1] %>% strptime("%Y-%m-%d") %>% as.character(),
           end =   dates[[1]][2] %>% strptime("%Y-%m-%d") %>% as.character()) %>%
    filter(!is.na(start) | !is.na(end)) %>%
    ungroup() %>%
    select(-c(ind, dates, week))
 
> cleanGoogleTrends %>% head()
## Source: local data frame [6 x 3]
## 
##   score      start        end
## 1     3 2004-01-04 2004-01-10
## 2     3 2004-01-11 2004-01-17
## 3     3 2004-01-18 2004-01-24
## 4     3 2004-01-25 2004-01-31
## 5     3 2004-02-01 2004-02-07
## 6     3 2004-02-08 2004-02-14
 
> cleanGoogleTrends %>% sample_n(10)
## Source: local data frame [10 x 3]
## 
##    score      start        end
## 1      8 2010-09-26 2010-10-02
## 2     73 2013-11-17 2013-11-23
## 3     52 2012-07-01 2012-07-07
## 4      3 2005-06-19 2005-06-25
## 5      3 2004-12-12 2004-12-18
## 6      3 2009-09-06 2009-09-12
## 7     71 2014-09-14 2014-09-20
## 8      3 2004-12-26 2005-01-01
## 9     62 2013-03-03 2013-03-09
## 10     3 2006-03-19 2006-03-25
 
> cleanGoogleTrends %>% tail()
## Source: local data frame [6 x 3]
## 
##   score      start        end
## 1    80 2014-10-19 2014-10-25
## 2    80 2014-10-26 2014-11-01
## 3    84 2014-11-02 2014-11-08
## 4    81 2014-11-09 2014-11-15
## 5    83 2014-11-16 2014-11-22
## 6     2 2014-11-23 2014-11-29

Ok now we’re ready to plot. This was my first attempt:

> library(ggplot2)
> ggplot(aes(x = start, y = score), data = cleanGoogleTrends) + 
    geom_line(size = 0.5)
## geom_path: Each group consist of only one observation. Do you need to adjust the group aesthetic?
2014 12 09 17 57 49

As you can see, not too successful! The first mistake I’ve made is not telling ggplot that the ‘start’ column is a date and so it can use that ordering when plotting:

> cleanGoogleTrends = cleanGoogleTrends %>% mutate(start =  as.Date(start))
> ggplot(aes(x = start, y = score), data = cleanGoogleTrends) + 
    geom_line(size = 0.5)

2014 12 09 18 00 03

My next mistake is that ‘score’ is not being treated as a continuous variable and so we’re ending up with this very strange looking chart. We can see that if we call the class function:

> class(cleanGoogleTrends$score)
## [1] "factor"

Let’s fix that and plot again:

> cleanGoogleTrends = cleanGoogleTrends %>% mutate(score = as.numeric(score))
> ggplot(aes(x = start, y = score), data = cleanGoogleTrends) + 
    geom_line(size = 0.5)

2014 12 09 18 02 39

That’s much better but there is quite a bit of noise in the week to week scores which we can flatten a bit by plotting a rolling mean of the last 4 weeks instead:

> library(zoo)
> cleanGoogleTrends = cleanGoogleTrends %>% 
    mutate(rolling = rollmean(score, 4, fill = NA, align=c("right")),
           start =  as.Date(start))
 
> ggplot(aes(x = start, y = rolling), data = cleanGoogleTrends) + 
    geom_line(size = 0.5)

2014 12 09 18 05 26

Here’s the full code if you want to reproduce:

library(dplyr)
library(zoo)
library(ggplot2)
 
googleTrends = read.csv("/Users/markneedham/Downloads/report.csv", row.names=NULL)
names(googleTrends) = c("week", "score")
 
cleanGoogleTrends = googleTrends %>% 
  mutate(ind = row_number()) %>% 
  group_by(ind) %>%
  mutate(dates = strsplit(week, " - "),
         start = dates[[1]][1] %>% strptime("%Y-%m-%d") %>% as.character(),
         end =   dates[[1]][2] %>% strptime("%Y-%m-%d") %>% as.character()) %>%
  filter(!is.na(start) | !is.na(end)) %>%
  ungroup() %>%
  select(-c(ind, dates, week)) %>%
  mutate(start =  as.Date(start),
         score = as.numeric(score),
         rolling = rollmean(score, 4, fill = NA, align=c("right")))
 
ggplot(aes(x = start, y = rolling), data = cleanGoogleTrends) + 
  geom_line(size = 0.5)

My next step is to plot the Google Trends scores against my meetup data set to see if there’s any interesting correlations going on.

As an aside I made use of knitr while putting together this post – it works really well for checking that you’ve included all the steps and that it actually works!

Categories: Programming

Four Steps to Supercharge Deep Linking for Android Apps

Google Code Blog - Tue, 12/09/2014 - 19:12
ul {list-style-position: inside;} App deep links are the new kid on the block in Search results, and they’re picking up speed faster than you can say “Schema.org ViewAction”! For signed-in users, 15% of Google searches on Android now return deep links to apps through App Indexing. And over just the past quarter, we've seen the number of clicks on app deep links jump by 10x.

Based on feedback from developers since we launched publicly App Indexing back in June, we’d like to share with you four key steps to monitor app performance and drive user engagement:

1. Make sure you get access to Webmaster Tools
App indexing is a team effort between you (as an app developer) and your website management team. We recommend working with your webmaster to get access to Webmaster Tools to carefully track app-related issues. Here’s what’s available right now:
  • Errors in indexed pages within apps
  • Weekly clicks and impressions from app deep link via Google search
  • Stats on your sitemap (if that’s how you implemented the app deep links)
...and we plan to add a lot more in the coming months!

Any verified site owner can add a new user. Pick restricted or full permissions, depending on the level of access you’d like. Screen Shot 2014-11-13 at 22.30.47.png
2. Understand how your app is doing in search results
How are users engaging with your app from search results? We’ve introduced two new ways for you to track performance for your app deep links:
  • We now send a weekly clicks and impressions update to the Message center in your Webmaster Tools account.
  • You can now track how much traffic app deep links drive to your app using referrer information - specifically, the referrer extra in the ACTION_VIEW intent. We're working to integrate this information with Google Analytics for even easier access. Learn how to track referrer information on our Developer site.

3. Make sure key app resources can be crawled
Blocked resources are one of the top reasons for the “content mismatch” errors you see in Webmaster Tools’ Crawl Error report. We need access to all the resources necessary to render your app page. This allows us to assess whether your associated web page has the same content as your app page.

To help you find and fix these issues, we’ll now show you the specific resources we can’t access that are critical for rendering your app page. If you see a content mismatch error for your app, look out for the list of blocked resources in “Step 5” of the details dialog: apps roboted content (1).png
4. Watch out for Android App errors
To help you identify errors when indexing your app, we’ll send you messages for all app errors we detect, and will also display most of them in the “Android apps” tab of the Crawl errors report.

In addition to the currently available “Content mismatch” and “Intent URI not supported” error alerts, we’re introducing three new error types:
  • APK not found: we can’t find the package corresponding to the app
  • No first-click free: the link to your app does not lead directly to the content, but requires login to access
  • Back button violation: after following the link to your app, the back button did not return to Search results.

In our experience, the majority of errors are usually caused by a general setting in your app (e.g. a blocked resource, or a region picker that pops up when the user tries to open the app from Search results). Taking care of that generally resolves it for all involved URIs.

Be sure to visit our codelab to learn how to get your Android app indexed by Google Search. As always, if you have questions, feel free to drop by Stack Overflow or the Webmaster help forum.

Posted by Mariya Moeva, Webmaster Trends Analyst
Categories: Programming

Google Play services and DEX method limits

Android Developers Blog - Tue, 12/09/2014 - 18:42

Posted by Laurence Moroney, Developer Advocate

A constraint for some Android apps is the total number of methods that the underlying compiled .dex file can support. It’s limited by 16 bits, or 65,536 values.

When you include third-party libraries in your application, you will have all of their methods in your .dex file. Larger APIs, such as those included in Google Play services, will then begin eating into the limit very quickly.

You can learn more about this, and ways that you can work around it with the Android Studio 1.0 build system here.

Additionally, with Google Play services version 6.5 or later, it is possible for you to include Google Play services in your application using a number of smaller client libraries, so that only Google Play services APIs you use will get compiled into your .dex file, and therefore their methods won't count towards your method limit.

Prior to version 6.5, you would typically have a line like this in your build.gradle file:

compile 'com.google.android.gms:play-services:6.5.87'

Starting with version 6.5, of Google Play services, you’ll be able to pick from a number of individual APIs, and you can see which ones have their own include files in the documentation. For example, if all you want to use is Maps, you would instead have:

compile 'com.google.android.gms:play-services-maps:6.5.87'

Note that this will transitively include the ‘base’ libraries, which are used across all APIs. You can include them independently with the following line:

compile 'com.google.android.gms:play-services-base:6.5.87'

The complete list of API names is below. More details can be found on the Android Developer site.

com.google.android.gms:play-services-base:6.5.87
com.google.android.gms:play-services-ads:6.5.87
com.google.android.gms:play-services-appindexing:6.5.87
com.google.android.gms:play-services-maps:6.5.87
com.google.android.gms:play-services-location:6.5.87
com.google.android.gms:play-services-fitness:6.5.87
com.google.android.gms:play-services-panorama:6.5.87
com.google.android.gms:play-services-drive:6.5.87
com.google.android.gms:play-services-games:6.5.87
com.google.android.gms:play-services-wallet:6.5.87
com.google.android.gms:play-services-identity:6.5.87
com.google.android.gms:play-services-cast:6.5.87
com.google.android.gms:play-services-plus:6.5.87
com.google.android.gms:play-services-appstate:6.5.87
com.google.android.gms:play-services-wearable:6.5.87
com.google.android.gms:play-services-all-wear:6.5.87

Note: At the time of writing, the correct version to use is 6.5.87. As this is a very granular number, it will get updated quite quickly, so be sure the check the latest version when you are coding. Often people will use a ‘+’ to denote versions, such as 6.5.+ to use the latest 6.5 build. However, it’s typically discouraged to use a ‘+’ as it can lead to inconsistencies.

Also, there are some changes to the names of the libraries that will impact you if you build applications for Android Wear. Previously you may have used play-services-wearable to include the entire Google Play services library for your wearable, and if you want to continue doing so, you should now use play-services-all-wear instead. You can continue to use play-services-wearable which will instead give you just the Wearable Data Layer API (see here). Should you do this, and you want to continue working with other Google Play services features, such as the Location APIs on your wearable, you would need to add play-services-location.

Join the discussion on

+Android Developers
Categories: Programming

Quote of the Month December 2014

From the Editor of Methods & Tools - Tue, 12/09/2014 - 18:23
Stories shouldn’t be small because they need to fit into an iteration, but because the world shouldn’t end just because a story turns out to be wrong. Stories are based on assumptions about business value, and those assumptions might turn out to be right or wrong.The key questions for story sizing shouldn’t be about the iteration length, but about how much business stakeholders want to invest in learning whether a proposed change will actually give them what they assumed. Source: Fifty Quick Ideas to Improve your User Stories, Gojko Adzic and ...

Sponsored Post: Campanja, Hypertable, Sprout Social, Scalyr, FoundationDB, AiScaler, Aerospike, AppDynamics, ManageEngine, Site24x7

Who's Hiring?
  • Campanja is an Internet advertising optimization company born in the cloud and today we are one of the nordics bigger AWS consumers, the time has come for us to the embrace the next generation of cloud infrastructure. We believe in immutable infrastructure, container technology and micro services, we hope to use PaaS when we can get away with it but consume at the IaaS layer when we have to. Please apply here.

  • Performance and Scale EngineerSprout Social, will be like a physical trainer for the Sprout social media management platform: you will evaluate and make improvements to keep our large, diverse tech stack happy, healthy, and, most importantly, fast. You'll work up and down our back-end stack - from our RESTful API through to our myriad data systems and into the Java services and Hadoop clusters that feed them - searching for SPOFs, performance issues, and places where we can shore things up. Apply here.

  • UI EngineerAppDynamics, founded in 2008 and lead by proven innovators, is looking for a passionate UI Engineer to design, architect, and develop our their user interface using the latest web and mobile technologies. Make the impossible possible and the hard easy. Apply here.

  • Software Engineer - Infrastructure & Big DataAppDynamics, leader in next generation solutions for managing modern, distributed, and extremely complex applications residing in both the cloud and the data center, is looking for a Software Engineers (All-Levels) to design and develop scalable software written in Java and MySQL for backend component of software that manages application architectures. Apply here.
Fun and Informative Events
  • Sign Up for New Aerospike Training Courses.  Aerospike now offers two certified training courses; Aerospike for Developers and Aerospike for Administrators & Operators, to help you get the most out of your deployment.  Find a training course near you. http://www.aerospike.com/aerospike-training/
Cool Products and Services
  • Aerospike Hits 1M writes per second with 6x Fewer Servers than Cassandra. A new Google Compute Engine benchmark demonstrates how the Aerospike database hit 1 million writes per second with just 50 nodes - compared to Cassandra's 300 nodes. Read the benchmark: http://www.aerospike.com/blog/1m-wps-6x-fewer-servers-than-cassandra/

  • Hypertable Inc. Announces New UpTime Support Subscription Packages. The developer of Hypertable, an open-source, high-performance, massively scalable database, announces three new UpTime support subscription packages – Premium 24/7, Enterprise 24/7 and Basic. 24/7/365 support packages start at just $1995 per month for a ten node cluster -- $49.95 per machine, per month thereafter. For more information visit us on the Web at http://www.hypertable.com/. Connect with Hypertable: @hypertable--Blog.

  • FoundationDB launches SQL Layer. SQL Layer is an ANSI SQL engine that stores its data in the FoundationDB Key-Value Store, inheriting its exceptional properties like automatic fault tolerance and scalability. It is best suited for operational (OLTP) applications with high concurrency. Users of the Key Value store will have free access to SQL Layer. SQL Layer is also open source, you can get started with it on GitHub as well.

  • Diagnose server issues from a single tab. The Scalyr log management tool replaces all your monitoring and analysis services with one, so you can pinpoint and resolve issues without juggling multiple tools and tabs. It's a universal tool for visibility into your production systems. Log aggregation, server metrics, monitoring, alerting, dashboards, and more. Not just “hosted grep” or “hosted graphs,” but enterprise-grade functionality with sane pricing and insane performance. Trusted by in-the-know companies like Codecademy – try it free!

  • aiScaler, aiProtect, aiMobile Application Delivery Controller with integrated Dynamic Site Acceleration, Denial of Service Protection and Mobile Content Management. Cloud deployable. Free instant trial, no sign-up required.  http://aiscaler.com/

  • ManageEngine Applications Manager : Monitor physical, virtual and Cloud Applications.

  • www.site24x7.com : Monitor End User Experience from a global monitoring network.

If any of these items interest you there's a full description of each sponsor below. Please click to read more...

Categories: Architecture

Project Communication Tips and Tricks

Software Requirements Blog - Seilevel.com - Tue, 12/09/2014 - 17:00
Ever had one of those projects where it seemed you spent most of your time either trying to track down the right person to talk to or trying to get team members to talk to each other?  How do you deal with a project team or stakeholder group that has significant communications dysfunctions? Having struggled […]
Categories: Requirements

Risk Management is Project Management for Adults

Herding Cats - Glen Alleman - Tue, 12/09/2014 - 16:49

In a recent presentation, Tim speaks further about managing in the presence of uncertainty and the application of agile in software development. Plans NEVER go right, planning in presence of uncertainty, requires - DEMANDS actually - estimating risk, uncertainties, unknowns - on the project. When we hear about making decisions in the absence of estimating the probability of the drivers, impacts, and outcomes. As he says This is a crock just as the making decisions in the absence of estimating is a crock. Ignoring the probabilistic behaviour of impacts from the future - microeconomics - is as Tim suggests childish behaviour.

Screen Shot 2014-12-08 at 8.35.51 PM

Managing in the Presence of Uncertainty

Here's an extract from a much larger briefing on managing complex, software intensive systems, in our domain - Enterprise IT. The critical issue here is uncertainty is always present. Failure to recognize this, failure to deal with it, failure to make decisions based on the underlying statistical and probabilistic aspects of this uncertainty is as Tim suggest childish.

If we're looking where we need estimates, look here potential - potential being something that might occur in the future. Potential cost, potential schedule, potential event. 

Screen Shot 2014-12-09 at 8.36.26 AM

 

Effective risk management - and therefore effective project management and effective value delivery - requires navigating through this causal chain, assessing the current potential for loss, and implementing strategies for minimizing the potential for loss. The next section builds on the concepts in this section by examining two fundamental approaches for analyzing risk.

Managing in the presence of uncertainty from Glen Alleman

So when we hear...

Decisions can be made in the absence of estimates. Ask how, ask to be shown the tangible evidence, ask for the mechanics this can be possible.

Related articles Show Me Your Math Estimating Guidance Software Estimating for Non Trival Projects
Categories: Project Management

Over goes big and goes home with Android

Android Developers Blog - Tue, 12/09/2014 - 16:21

Posted by Leticia Lago, Google Play team

Over has taken a simple idea, adding text and artwork to photos, and turned it into a creative tool that enables anyone to easily and intuitively add a unique twist to any image.

The Over team recently decided to bring their successful app to Android. “We love unlocking human creativity and Android offers a massive opportunity for doing just that. It was a no-brainer,” says Aaron Marshall, Founder, CEO, and Designer at Over. “Moving to Cape Town was eye-opening in many ways. It made me experience first-hand how many people outside the US use Android. We see users in emerging markets using mobile devices as their primary device, and believe there is a lot of opportunity in providing them with creative tools for mobile.”

The entire team was new to the platform, and were quickly impressed by the ease of development and the power of the distribution tools in the Developer Console on Google Play.

In this video, the Over team talk about their experiences learning and working with Android.

Over engineer Johan Nell, who arrived with Java experience but hadn’t worked with Android, says that he and fellow engineer Herko Lategan “were able to get a working prototype out in the first week.”

Android plays a big part in Over living up to its mantra of “go big, and go home”. As Aaron explains, “we don’t think you should be sacrificing your family to create wealth, or add value, or change the world. Being able to experiment and iterate quickly is crucial in helping us achieve this goal.”

To learn about starting a successful business with Android, be sure to check out these resources:

  • The Secrets to App Success on Google Play [ebook] — a detailed playbook on the best practices and tools you can use to maximize the reach, retention, and revenue of your new app.
  • Getting Started [training] — check out this comprehensive learning resource that takes you from first principles through to the most powerful Android APIs.
Join the discussion on

+Android Developers
Categories: Programming

Who Picks the Sprint Length on a Scrum Team?

Mike Cohn's Blog - Tue, 12/09/2014 - 15:00

An important consideration for every Scrum team is how long its sprints should be. Choose a length that’s too long, and it will be hard to keep change out of the sprint. Choose a length that’s too short, and a team may struggle with completing significant work within the sprint or weaken their definition of done to do so.

But who is it that gets to select a team’s sprint length?

Of course, the answer is the whole team – that collective of ScrumMaster plus product owner plus team members such as programmers, testers, designers, DBAs, analysts and so on.

But what if that broad set of individuals cannot agree? Do they argue endlessly, perhaps sticking with their waterfall or ad hoc process until consensus finally emerges?

No. The ScrumMaster is ultimately the one who gets to choose a team’s sprint length.

A good ScrumMaster will do everything possible to arrive at a consensus. But, when the ScrumMaster exhausts his or her collaborative, facilitative skills without arriving at a consensus, the good ScrumMaster makes the decision.

This should not happen often. I hope most ScrumMasters never need to say, “I’ve listened to everyone, but here’s what we’re doing.” But since the ScrumMaster can be considered a team’s process owner, the ultimate decision does belong to the ScrumMaster.

Let’s consider one example from my past.

In this case, I was consulting to a team doing four-week sprints. They were struggling to pull the right amount of work into their sprints. For the six months before I’d met them, team members were consistently dropping about a third of the work each sprint.

They were a good team doing high-quality work. They simply didn’t know how much of it they could do in four weeks. Their optimism was getting the better of them, and they were consistently overcommitting.

I asked the team to think about how they’d like to solve the problem and tell me their suggestions the next day. I was thrilled the next day when they announced that they should clearly change the length of their sprints. “Yes,” I told them, “Definitely.”

They were relieved that I agreed with them and said so: “Wow! We didn’t think you’d let us go to six-week sprints!”

I had to inform them that while I agreed with changing sprint length, the better solution would be to go to shorter rather than longer sprints.

We ended with me—as a consulting ScrumMaster—setting a two-week length.

Why did I do this?

The team was already pulling too much work into a four-week sprint. They were, in fact, probably pulling six weeks of work into each four-week sprint. But, if they had gone to a six-week sprint, they probably would have pulled eight or nine weeks of work into those!

This team needed more chances to learn how much work fit into a sprint (of any length). As their ScrumMaster—especially coming to the team as a consultant—I could see that more easily than they could.

I want to end by repeating my caution that this is not something that should happen very often. I can count on one hand the number of times when I’ve flat-out chosen a length for the team after failing to gain consensus.

I’ll stand by the value of having done so in each case. But I only did so after significant effort to gain consensus. Overriding team members on something as important as sprint length should be done with great caution. But, it’s a process issue and, therefore, in the domain of the ScrumMaster.

What about you? Were there times when your team couldn’t agree on a sprint length? How did you resolve it?

Find the last Sunday of each Month

Phil Trelford's Array - Tue, 12/09/2014 - 08:20

Rosetta Code has a number of programming tasks with example solutions in multiple languages. One of those tasks is find the last Sunday of each month. Here’s a sample in C#:

DateTime date;
for (int i = 1; i <= 12; i++)
{
   date = new DateTime(year, i, DateTime.DaysInMonth(year, i), System.Globalization.CultureInfo.CurrentCulture.Calendar);
   while (date.DayOfWeek != DayOfWeek.Sunday)
   {
      date = date.AddDays(-1);
   }
   Console.WriteLine(date.ToString("yyyy-MM-dd"));
}

I thought it might be fun to write an F# version, code golf style, that fits in a tweet:

[for m in 1..12->Seq.find(fst>>int>>(=)0)[for d in System.DateTime.DaysInMonth(2014,m).. -1.. 1->System.DateTime(2014,m,d).DayOfWeek,(m,d)]]

— Philae Trelford (@ptrelford) December 8, 2014

The general gist of that solution was to create a list of all days in each month in reverse order and find the first Sunday (which will be the last):

[for month in 1..12->
   [for day in System.DateTime.DaysInMonth(2014,month).. -1.. 1->
      System.DateTime(2014,month,day).DayOfWeek,(month,day)]
   |> Seq.find (fun (dayOfWeek,_) -> dayOfWeek = System.DayOfWeek.Sunday)
]

 

Enter Petricek

Then Tomas Petricek came up with a neat solution that had enough space left over to execute against @fsibot:

.@tomaspetricek [1/26/2014 12:00:00 AM; 2/23/2014 12:00:00 AM; 3/30/2014 12:00:00 AM; 4/27/2014 12:00:00 AM; 5/25/2014 12:00:00 AM; 6 [...]

— fsibot (@fsibot) December 8, 2014

Tomas’s solution evaluates each day of the year, yielding the last Sundays as dates:

[for days in 0.0 .. 365.0 do 
   let day = System.DateTime(2014,1,1).AddDays(days) in 
   if int day.DayOfWeek = 0 && day.AddDays(7.).Month <> day.Month 
   then yield day
]

 

Wellum Reprise

Meanwhile Richard Wellum suggested an alternate solution in C#, which I was able to translate to standalone F# with space left over for a pretty print:

.@ptrelford ["January 26"; "February 23"; "March 30"; "April 27"; "May 25"; "June 29"; "July 27"; "August 31"; "September 28"; "Octob [...]

— fsibot (@fsibot) December 9, 2014

Richard's solution is to calculate the last day of the month, find the day of week and subtract that value to reach the Sunday. Here's a version with variable names:

[for month in 1..12->
   let lastDay = System.DateTime(2014,month,1).AddMonths(1).AddDays(-1.) in 
   lastDay.AddDays(-(lastDay.DayOfWeek|>int|>float)).ToString("m")
]

Conclusion

Finding the last Sunday of each month in a tweet now appears to be a solved problem :)

Categories: Programming

Agile Metrics: Philosophy

This measurement that encourages behavior.

This measurement that encourages behavior.

Discussions of software development, maintenance and enhancement measurement are generally tense, even at the best of times. Measurement has a significant amount of baggage, ranging from using measures to grade individuals for team activities to measurement without sharing the results with those being measured. Add the philosophies of Agile into the mix and the discussion becomes even more difficult, because, to be optimally efficient, Agile measurement requires an organization to adopt a different set of measurement philosophies that are more inline with the principles found in the Agile Manifesto.

  • Reinforce desired Agile behavior – Measurement has a very strong behavioral competent. You get what you measure, therefore the measures selected need to support and promote the behavior you want in the organization. For example, organizations often try to measure individual productivity or velocity, which reinforces individualism. Where the more Agile behavior would be team collaboration, asking for help and swarming to problems. Measure team productivity and velocity rather than focusing on individuals.
  • Focus on results – Agile techniques are geared to delivering potentially implementable functionality early and often. Potentially implementable functionality equates to value for the organization. Agile measurement should focus on the value that is delivered. Examples of value would include functionality delivered, stories completed or estimated business value.
  • Measure trends – The direction a measure is trending is typically more important than an individual observation (common cause versus special cause variation). Given the short cycles (sprints) most Agile teams use, teams can accumulate enough observations of their processes and the functionality being delivered to understand whether they are improving or not.
  • Easy to collect – All measurement requires effort, typically from both the people doing the measurement and those being measured. The overhead of measurement is time that is not being used to deliver value therefore it should be minimized. The measurement information you collect should be easily collected (or in perfect world) be a natural byproduct of the tools and techniques being used on the project.
  • Includes context – Just knowing black and white numbers does not allow nuanced interpretation of performance. Collecting and storing (write story down and save it as text attached to the measurement data) the context that helped generate a specific result will help teams and managers to understand and use the data.
  • Creates real conversation – Measurement needs to generate a dialog in which all stakeholders of IT and projects can understand the value that is being delivered, discuss performance and find ways to improve the delivery of value.
  • Measure only what is absolutely needed – Define and collect measures and metrics that will be actively used to guide the organization or make decisions. Collecting more information than you will need to answer questions and make decisions will generate more overhead for teams to overcome.

All organizations and teams need the feedback that measurement generates. Organizations typically measure for two reasons. The first is to generate specific behaviors, and second to predict the future.  Organizational goals provide the rational for what to measure and the type of measure determines whether it drives behavior or provides direction. In organizations that leverage Agile techniques measurement will be more effective if it embraces Agile measurement philosophies.


Categories: Process Management

Google Play services 6.5

Android Developers Blog - Mon, 12/08/2014 - 20:47
Posted by Ian Lake, Developer Advocate

To offer more seamless integration of Google products within your app, we've now rolled out Google Play services 6.5.

Google Play services 6.5 includes new features in Google Maps, Google Drive and Google Wallet as well as the recently launched Google Fit API. We are also providing developers with more granular control over which Google Play services APIs your app depends on to help you maintain a lean app.

Google Maps

We’re making it easier to get directions to places from your app! The Google Maps Android API now offers a map toolbar to let users open Google Maps and immediately get directions and turn by turn navigation to the selected marker. This map toolbar will show by default when you compile against Google Play services 6.5.

In addition, there is also a new ‘lite mode’ map option, ideal for situations where you want to provide a number of smaller maps, or a map that is so small that meaningful interaction is impractical, such as a thumbnail in a list. A lite mode map is a bitmap image of a map at a specified location and zoom level.

In lite mode, markers and shapes are drawn client-side on top of the static image, so you still have full control over them. Lite mode supports all of the map types, the My Location layer, and a subset of the functionality of a fully-interactive map. Users can tap on the map to launch Google Maps when they need more details.

The Google Maps Android API also exposes a new getMapAsync(OnMapReadyCallback) method to MapFragment and MapView which will notify you exactly when the map is ready. This serves as a replacement for the now deprecated getMap() method.

We’re also exposing the Google Maps for Android app intents available to your apps including displaying the map, searching, starting turn by turn navigation, and opening Street View so you can build upon the familiar and powerful maps already available on the device.

Drive

You can now add both public and application private custom file properties to a Drive file which can be used to build very efficient search queries and allow apps to save information which is guaranteed to persist across editing by other apps.

We’ve also made it even easier to make syncing your files to Drive both user and battery friendly with the ability to control when files are uploaded by network type or charging status and cancel pending uploads.

Google Wallet

In addition to the existing ‘Buy with Google’ button available to quickly purchase goods & services using Google Wallet, this release adds a ‘Donate with Google’ button for providing the same ease of use in collecting donations.

Google Fit

The Google Fit SDK was recently officially released as part of Google Play services and can be used to super-charge your fitness apps with a simple API for working with sensors, recording activity data, and reading the user’s aggregated fitness data.

In this release, we’ve made it easier for developers to add activity segments (predefined time periods of running, walking, cycling, etc) when inserting sessions, making it easy to support pauses or multiple activity type workouts. We’ll also be adding additional samples to help kick-start your Google Fit integration.

Granular Dependency Management

As we’ve continued to add more APIs across the wide range of Google services, it can be hard to maintain a lean app, particularly if you're only using a portion of the available APIs. Now with Google Play services 6.5, you’ll be able to depend only on a minimal common library and the exact APIs your app needs. This makes it very lightweight to get started with Google Play services.

SDK Now Available

You can get started developing today by downloading the Google Play services SDK from the Android SDK Manager.

To learn more about Google Play services and the APIs available to you through it, visit the Google Play Services section on the Android Developer site.

Join the discussion on

+Android Developers
Categories: Programming

Android Studio 1.0

Android Developers Blog - Mon, 12/08/2014 - 20:46
h3 { font-size:20px; font-family:Roboto,sans-serif; font-weight:400; line-height:1.25em; margin-top:1.1em; } h4 { font-size:16px; font-family:Roboto,sans-serif; font-weight:900; line-height:1.25em; margin-top:1.3em; } ul.featurelist li { margin-top:1.3em; line-height:1.25em; }

By Jamal Eason, Product Manager, Android

Today we are excited to introduce Android Studio 1.0. Android Studio is the official Integrated Development Environment (IDE) from the Android team. It is built on the popular IntelliJ IDEA (Community Edition) Java IDE.

We first released a preview of Android Studio at I/O last year. We value the on-going feedback from you, thanks! We are making Android Studio 1.0 available for download as a stable release on the Android Developer site.

Download Android Studio

If you are currently developing for Android or thinking about getting started, now is the time to download Android Studio 1.0 (or upgrade if you are using an earlier version). Similar to the Chrome release channels, Android Studio will continue to receive updates on four different release channels: Stable, Beta, Dev, and Canary. Canary builds are at the bleeding edge of development, while the stable release is fully tested. With this range of release channels you can choose how quickly you want to get the latest features for Android Studio.

Android Studio features

With the release of Android Studio, you have access to a new set of features to enable your development workflow. Some of the key features of Android Studio are listed below, but make sure to check out the Android Studio page for a full feature overview.

Startup experience
  • First-run setup wizard — The getting started experience now installs the right Android SDK, sets up your development environment settings, and creates an optimized emulator for testing your app. Plus, we include a set of code templates to help you get started.
  • Sample Importing & templates — Android Studio includes wizards that enable you to start with new project templates or import Google code samples.
Code and resource editing, user interface design
  • Code Editing — Android Studio takes advantage of all the intelligent code editing capabilities of IntelliJ IDEA such as advanced code completion, refactoring, and code analysis.
  • Internationalization string editing — Manage string translations of your app in Android Studio.
  • User interface design — Edit and preview your Android Layouts across multiple screen sizes, languages, and even API versions.
Performance analysis
  • Memory monitor — View the memory usage of your app over time to help find ways to improve the performance of your app.
Unified build system
  • Android Studio uses a Gradle-based build system that provides a lot of flexibility and extensibility, as well as the ability to build from within and outside of the IDE. This unified build system decouples the build from Studio itself, meaning that Studio updates never impact the output of your build.
  • Some of the key features of the build systems are: build variant support to better handle different build types (debug vs. release), or different versions of the same app (paid vs. free), multi-apks handling through splits, multi-dex support, and dependency management for 3rd party libraries.
Instant access to Google Cloud Services
  • Android Studio even enables an easy way to add Google Cloud Backends & Endpoints to your app, as well as Google Cloud Messaging (find out more).
Time to migrate & update

If you are an Eclipse user, check out our migration steps or you can just import your projects right into Android Studio with the import wizard, shown below:

If you were using one of the early versions of Android Studio, you should also upgrade to version 1.0 since we have added a host of new features and have addressed many bugs.

We have also released version 1.0 of the Gradle plugin with a file format that is now stable. The communication between Android Studio and the Gradle plugin is now stable, so updating one will not require updating the other. Check the technical release notes for additional tips for updating your previous Android Studio projects.

Give us your feedback

We are always seeking to bring you the best Android development experience. We already have plans to add features ranging from improved testing and better support for game development, but we want to know how you work and what capabilities you'd like to have for your Android development.

Please take a moment to complete a short survey (less than 5 minutes). Your responses will help shape the next set of features offered in Android Studio.

Questions?

We develop Android Studio and the corresponding tools in open source, so you can also file bugs via the public Android bug tracker and we will do our best to address your issues or questions. If you have specific questions or need help in your migration, feel free to connect with the Android developer tools team on our Google+ community page.

Join the discussion on

+Android Developers
Categories: Programming

R: dplyr – mutate with strptime (incompatible size/wrong result size)

Mark Needham - Mon, 12/08/2014 - 20:02

Having worked out how to translate a string into a date or NA if it wasn’t the appropriate format the next thing I wanted to do was store the result of the transformation in my data frame.

I started off with this:

data = data.frame(x = c("2014-01-01", "2014-02-01", "foo"))
> data
           x
1 2014-01-01
2 2014-02-01
3        foo

And when I tried to do the date translation ran into the following error:

> data %>% mutate(y = strptime(x, "%Y-%m-%d"))
Error: wrong result size (11), expected 3 or 1

As I understand it this error is telling us that we are trying to put a value into the data frame which represents 11 rows rather than 3 rows or 1 row.

It turns out that storing POSIXlts in a data frame isn’t such a good idea! In this case we can use the as.character function to create a character vector which can be stored in the data frame:

> data %>% mutate(y = strptime(x, "%Y-%m-%d") %>% as.character())
           x          y
1 2014-01-01 2014-01-01
2 2014-02-01 2014-02-01
3        foo       <NA>

We can then get rid of the NA row by using the is.na function:

> data %>% mutate(y = strptime(x, "%Y-%m-%d") %>% as.character()) %>% filter(!is.na(y))
           x          y
1 2014-01-01 2014-01-01
2 2014-02-01 2014-02-01

And a final tweak so that we have 100% pipelining goodness:

> data %>% 
    mutate(y = x %>% strptime("%Y-%m-%d") %>% as.character()) %>%
    filter(!is.na(y))
           x          y
1 2014-01-01 2014-01-01
2 2014-02-01 2014-02-01
Categories: Programming

R: dplyr – mutate with strptime (incompatible size/wrong result size)

Mark Needham - Mon, 12/08/2014 - 20:02

Having worked out how to translate a string into a date or NA if it wasn’t the appropriate format the next thing I wanted to do was store the result of the transformation in my data frame.

I started off with this:

data = data.frame(x = c("2014-01-01", "2014-02-01", "foo"))
> data
           x
1 2014-01-01
2 2014-02-01
3        foo

And when I tried to do the date translation ran into the following error:

> data %>% mutate(y = strptime(x, "%Y-%m-%d"))
Error: wrong result size (11), expected 3 or 1

As I understand it this error is telling us that we are trying to put a value into the data frame which represents 11 rows rather than 3 rows or 1 row.

It turns out that storing POSIXlts in a data frame isn’t such a good idea! In this case we can use the as.character function to create a character vector which can be stored in the data frame:

> data %>% mutate(y = strptime(x, "%Y-%m-%d") %>% as.character())
           x          y
1 2014-01-01 2014-01-01
2 2014-02-01 2014-02-01
3        foo       <NA>

We can then get rid of the NA row by using the is.na function:

> data %>% mutate(y = strptime(x, "%Y-%m-%d") %>% as.character()) %>% filter(!is.na(y))
           x          y
1 2014-01-01 2014-01-01
2 2014-02-01 2014-02-01

And a final tweak so that we have 100% pipelining goodness:

> data %>% 
    mutate(y = x %>% strptime("%Y-%m-%d") %>% as.character()) %>%
    filter(!is.na(y))
           x          y
1 2014-01-01 2014-01-01
2 2014-02-01 2014-02-01
Categories: Programming

Three Increasingly Mature Views of Estimate Making in IT Projects - Update

Herding Cats - Glen Alleman - Mon, 12/08/2014 - 19:02

There remains serious misunderstandings of how, why, when, and for what purpose estimates of cost, schedule and delivered capabilities are made in the development of software systems using other peoples money.

There are three distinct approaches to the problem:

The first paper shows the self-selected projects and how they have completed - for the most part - lonfer the ideal initial estimates. These estimates are not calibrated, meaning they are not assessed for credibility, error bands, or confidence. The paper mentions the the solid line, initial versus actual is the ideal line where actuals meet estimated value. In any stochastic estimating process, it will be unlikely ant estimate will result in a match with the actual for the very simple reason that the work processes are random and when the estimates don't contain the probabilistic confidence intervals, the actual MUST be different that the estimate.

As well, no root cause for the unfavorable performance of the actuals compared to the initial estimates is provided. This is a core failure to understand the process of estimating, rot cause analysis, and the discovery of the corrective actions needed to improve both the estimating processes as well as project performance management.

This fundamental failure is not limited to the self-selected set of projects in the paper. This failure mode can be found a wide variety of project domains in and out of the software business.

The second paper speaks the the major flaws Standish Report - meaningless figures. self-selected samples, perverted accuracy, unrealistic rates and misleading definitions. The paper states the root causes and suggested corrective actions.

The third paper shows how to quantify IT forecasts (estimates of future outcomes) in a mathematically sound manner.

All five papers are useful in the right context. Little re-introduces Boehm's cone of uncertainty, assessment of Standish shows the traps that can be easily fallen into when good statistical practices are not followed, the third provides the mathematical foundation for restoring those sound practices, and the RAND report shows the mechanics of the corrective actions to restore credibility in software estimating.

A risk based view of the estimating problem developed for the recent successful launch and recovery of Orion, then called Crew Exploration Vehicle.

Probabilistic Schedule and Cost Analysis from Glen Alleman Related articles Software Estimating for Non Trival Projects
Categories: Project Management

How to make the Internet a nicer place to live

Eric.Weblog() - Eric Sink - Mon, 12/08/2014 - 19:00

Have you by chance noticed how UGLY online discussions can be?

Look around Twitter, or Facebook, or anywhere people are interacting on the Internet. You will find plenty of ugly stuff:

  • Name-calling
  • Put-downs
  • Assuming bad motives
  • Harrassment
  • Bullying
  • Denigrating accomplishments
  • Stereotyping
  • Insults
  • Ad hominem attacks
  • Threats
  • Sarcasm
  • Accusations

Much effort has been expended trying to give online communities ways to minimize the ugliness. We have upvotes and downvotes and filtering and identity and flagging and moderation. (A notable recent example is that Jeff Atwood has created Discourse, a discussion platform primarily designed to help online conversations be more civilized.)

If you are interested in knowing how YOU can help make the Internet a nicer place to live, read on.

The most important thing you can do

Obviously, the first thing is to not be ugly. But how?

Next time you are tempted to post something ugly, instead, post something "expressive".

Here's what I mean by "expressive": Behind the ugly thing you want to post, there is an emotion. Identify it. And express it.

An expressive statement starts with "I". It describes how you feel. In their basic form, expressive statements are short and simple. For example:

  • I am disappointed.
  • I feel afraid.
  • I am angry.

An expressive statement can (and usually does) include information about the situation that triggered the emotion:

  • I am disappointed that F# doesn't have higher kinded types.
  • I feel worried about the trend toward really cheap software.
  • I am angry that Xamarin's pricing is too high for me to afford.

An expressive statement is you saying something about you. It does not make statements about anyone else or their work. And it doesn't contain any ugly stuff. Putting "I feel" in front of something unkind doesn't change it from ugly to expressive. The following examples are not expressive statements:

  • I feel angry because Joe won't stop lying about the project status. (accusation)
  • I am tired of Jane being such a drama queen. (name-calling)
  • I feel disappointed that web apps are built on JavaScript instead of on a real language. (sarcasm)

At the very least, being expressive provides an alternative to being ugly. And sometimes, it accomplishes even more. Being real and forthright is usually a step toward good communication and shared understanding.

Example: The open sourcing of .NET Core

A few weeks ago, Microsoft released a lot of .NET stuff as open source. Online reactions to this announcement have varied greatly. Some (or dare I say, most) have applauded with vigor and joy.

Others have been, well, kinda ugly.

I'm sure the ugly responses have been frustrating for the folks at Microsoft. In the midst of trying to do something positive, they are receiving sarcasm and accusations of deceit.

Why is this? Why on earth would anybody see Microsoft's move as anything but positive? And even if they have a negative reaction, why would they be ugly about it?

Simply put, there are a lot of emotions in play.

Millions of developers are connected to the .NET platform. There is tremendous diversity, including countless use cases and a myriad of business goals. People have tied their personal and business success to .NET in a lot of very different ways. When the stakes are high, the emotions can be strong.

We should acknowledge the validity of the gamut of emotions people have about .NET. There are good reasons and plenty of history behind those feelings. Surely they give us license to focus on specific Microsoft program managers and call them names, right?

Actually, let's not. :-)

Instead, let's try something more expressive, like one of the following:

  • "I want to be optimistic about this move by Microsoft, but I am not sure I can trust them because of all the times I have felt disappointed about their announcements in the past."

  • "I have been worried for years about the future of the desktop parts of .NET. My business still depends on a good API for desktop UI. I wish Microsoft had open sourced Windows Forms too."

  • "I am worried that this move will increase the momentum of .NET at the expense of the platform I prefer."

  • "I feel frustrated because the .NET team did this instead of addressing the bug I logged."

That's the difference between being expressive and being ugly. Say how you feel. Make it about you.

Aren't I going to look dorky if I do this?

Yes.

Dorky > Ugly

Caveats and exceptions

Broadly speaking, being genuinely expressive is always preferable to being ugly. Or to say it another way, being ugly (as defined by the context of this blog entry) is probably the worst thing you can do online, but in some cases, expressing the underlying emotion isn't going to be all that much better.

There is plenty of wisdom in what they taught you in kindergarten: If you don't have something nice to say, then don't say anything at all.

For example, suppose you go on Twitter or your blog and say "I don't like Zed Shaw". Are you making the Internet a better place by publicly saying that you dislike someone? No. But that expressive statement is a lot less bad than the more popular path of calling Zed names or criticizing his work. He's a smart guy, and he has done some great stuff, but his online interactions are sometimes rather polarizing. You don't have to like him. But when he does something that stirs your emotions, a reaction that says something real about you is a lot better than something ugly.

It is also important to note that not all emotions are appropriate for public expression.

For example, in the tech world, we have a disturbing trend of ugly situations involving online harassment of women. The important thing to understand about these awful episodes that behind every ugly posting there was an emotion. Would those situations have been less bad if each of those ugly postings had been replaced by a public expression of the emotion behind it? Strictly speaking, yes, being real would have been less bad than being ugly. But maybe only a little. For some of those feelings, public expression would still be pretty darn inappropriate.

Sometimes it is better to express your emotions privately. Tell a friend. Process your strong feelings with someone you trust.

And don't underestimate the value of just keeping your mouth shut.

BTW, being expressive also works outside of tech

My primary audience is software developers, so I'm mostly just trying to help people (for example) stop saying "NoSQL sucks" and start saying "I feel threatened by NoSQL because I've spent my career learning SQL."

But just in case it's not obvious, being expressive is a way to avoid being ugly in ALL kinds of conversations about difficult issues.

Race. Gay marriage. Immigration. Israel. Iraq. Syria. Drugs. Religion. Politics. Poverty. The list could go on.

In most cases, online discussion of any of these topics will turn ugly at an alarming speed. And in most cases, being forthright about what we feel is a better choice than saying something unkind.

Want to do more?

If you practice the habit of being expressive instead of being ugly, congratulations, you are making the Internet a better place.

But if you want to do more, you can:

When you see people online being expressive instead of ugly, upvote them.

Being expressive is a courageous choice. There is vulnerability in saying what you feel. Name-calling is safer.

So when you see somebody choosing to be expressive instead of ugly, affirm their choice, even if [you suspect that] they have beliefs that are different from yours.

Want to do even more?

If you can do the previous two things, you are a hero. There really is no need to do anything more.

But maybe you want to be a SUPER hero. You want to be remembered as the Nelson Mandela or the Gandhi or the Mother Teresa of the Internet, someone who made every online community a nicer place just by entering it.

If you aspire to be famous for your good deeds, here is the third thing you can do:

See through the ugly.

When you see people online being ugly instead of expressive, look deeper:

  • Try to see the emotion behind their words, even though they didn't express it.
  • Try to understand their real point of view, not the one that they are articulating.
  • Try to empathize with the perspective they're not showing.

All the suggestions in this article are difficult. This one is by far the hardest. It is basically unreasonable. It asks you to assume the best of someone when they are showing you their worst. Being a superhero isn't easy.

Bottom line

Our online discussions would be so very different if we were all more adept at dealing with our emotions.

In many cases, we could avoid saying something awful by taking a moment to identify the feeling that is driving us, and to express it in a forthright and genuine (and probably dorky) manner.

Try it.

 

Get your Google Drive App listed on the Google Apps Marketplace

Google Code Blog - Mon, 12/08/2014 - 18:59
The Google Apps Marketplace brings together hundreds of third-party applications that integrate and enhance Google Drive, part of Google Apps for Work, our suite of collaboration and productivity tools for businesses. To improve discoverability and increase adoption, it’s important to make your Google Drive app integration available on the marketplace.

Today, we want to share with you four easy steps to get listed immediately and enable admins to install your application for all users in their domain. For more details, check out the Google Apps Marketplace documentation.

Step 1: Open your Drive project on Google Cloud console. Turn on “Google Apps Marketplace SDK” for your project. Screen Shot 2014-08-20 at 11.50.10 PM.png

Step 2: Click the gear icon to configure “Google Apps Marketplace SDK”. Refer to Google Apps Marketplace documentation for details. In the scopes section, be sure to request the same scopes as your Google Drive application, and check the “Enable Drive extension” checkbox.

Step 3: Go to the Chrome Web Store developer console and select your published Drive application.

Step 4: Update the following line in your Drive application’s Chrome Web Store manifest, upload and publish.

"container":"GOOGLE_DRIVE"
with
“container”: [”GOOGLE_DRIVE”, ”DOMAIN_INSTALLABLE”]

You’re done! You application is now available to all Google Apps for Work customers to install on a domain-wide basis through the Google Apps Marketplace. Refer to Publishing your app documentation for details. You can access Google Apps Marketplace inside Google Admin Console and verify your newly listed application.

Please subscribe to the Google Apps Marketplace G+ community for the latest updates.
Posted by Hiranmoy Saha, Software Engine, Google Apps Marketplace
Categories: Programming

Get your Google Drive App listed on the Google Apps Marketplace

Google Code Blog - Mon, 12/08/2014 - 18:59
The Google Apps Marketplace brings together hundreds of third-party applications that integrate and enhance Google Drive, part of Google Apps for Work, our suite of collaboration and productivity tools for businesses. To improve discoverability and increase adoption, it’s important to make your Google Drive app integration available on the marketplace.

Today, we want to share with you four easy steps to get listed immediately and enable admins to install your application for all users in their domain. For more details, check out the Google Apps Marketplace documentation.

Step 1: Open your Drive project on Google Cloud console. Turn on “Google Apps Marketplace SDK” for your project. Screen Shot 2014-08-20 at 11.50.10 PM.png

Step 2: Click the gear icon to configure “Google Apps Marketplace SDK”. Refer to Google Apps Marketplace documentation for details. In the scopes section, be sure to request the same scopes as your Google Drive application, and check the “Enable Drive extension” checkbox.

Step 3: Go to the Chrome Web Store developer console and select your published Drive application.

Step 4: Update the following line in your Drive application’s Chrome Web Store manifest, upload and publish.

"container":"GOOGLE_DRIVE"
with
“container”: [”GOOGLE_DRIVE”, ”DOMAIN_INSTALLABLE”]

You’re done! You application is now available to all Google Apps for Work customers to install on a domain-wide basis through the Google Apps Marketplace. Refer to Publishing your app documentation for details. You can access Google Apps Marketplace inside Google Admin Console and verify your newly listed application.

Please subscribe to the Google Apps Marketplace G+ community for the latest updates.
Posted by Hiranmoy Saha, Software Engine, Google Apps Marketplace
Categories: Programming