Em um relatório recente disponível aqui, exploramos um pouco algumas relações entre projetos open source escritos em Java e Ruby, agora daremos sequência a esta análise com mais perguntas sobre os projetos.
data <- read_csv('data/projetos.csv')## Parsed with column specification:
## cols(
## gh_project_name = col_character(),
## team = col_double(),
## lang = col_character(),
## sloc_end = col_integer(),
## sloc_med = col_double(),
## activity_period = col_integer(),
## num_commits = col_integer(),
## commits_per_month = col_double(),
## tests_per_kloc = col_double(),
## total_builds = col_integer(),
## build_success_prop = col_double(),
## builds_per_month = col_double(),
## tests_added_per_build = col_double(),
## tests_successful = col_double(),
## test_density = col_double(),
## test_size_avg = col_double()
## )
Os Dados
Vamos primeiramente entender um pouco mais sobre os dados que serão utilizados. Mais uma vez, analisaremos dados de projetos open source armazenados e versionados fazendo uso do GitHub.
gh_project_name
O nome dos projetos, será utilizado apenas para visualização a título de curiosidade.
lang
A linguagem majoritária do projeto em questão, vamos observar as categorias desta variável.
lang_count <- data %>%
select(gh_project_name, lang, team) %>%
group_by(lang) %>%
summarise(count = n())
lang_count %>%
plot_ly(x = ~lang, y = ~count, type = "bar")Mais uma vez, nosso foco nesta análise está em comparar as linguagens Java e Ruby, portanto removeremos as observações que representam projetos Javascript.
data <- data %>%
filter(lang != "javascript")num_commits
O número de commits que a equipe realizou.
data %>%
plot_ly(x = ~gh_project_name ,y = ~num_commits, type = "scatter") %>%
layout(xaxis = list(title = "Projeto",showticklabels = FALSE)) %>%
layout(yaxis = list(title = "Número de commits realizados"))## No scatter mode specifed:
## Setting the mode to markers
## Read more about this attribute -> https://plot.ly/r/reference/#scatter-mode
Como podemos ver, alguns projetos com uma quantidade muito elevada de commits concentraram a maioria dos pontos muito em baixo na visualização, isto é um problema pois não conseguimos ter uma visão real sobre a maioria dos projetos. Para resolver este problema, utilizaremos uma tecnica que consiste em mudar a escala y do gráfico. Atualmente, visualizamos o eixo y em uma escala linear, esta escala atribui a cada valor o mesmo espaço na visualização, uma outra escala é a logarítmica, ela dá mais ênfase para valores menores. Usando a escala logarítmica, seremos capazes de entender melhor a distribuição dos projetos em relação a esta variável.
data %>%
plot_ly(x = ~gh_project_name ,y = ~num_commits, type = "scatter") %>%
layout(xaxis = list(title = "Projeto",showticklabels = FALSE)) %>%
layout(yaxis = list(title = "Número de commits realizados", type = "log"))## No scatter mode specifed:
## Setting the mode to markers
## Read more about this attribute -> https://plot.ly/r/reference/#scatter-mode
Agora podemos ver que a maior parte dos projetos estão em uma faixa entre 100 e 15 mil commits, é uma variação muito grande!
sloc_end
A quantidade máxima de linhas, que o projeto já possuiu.
sloc_med
Quantidade média de linhas que o projeto possuiu ao longo do tempo.
team
A quantidade de membros do time por projeto, esta variável será mais explorada na primeira pergunta que buscamos responder a seguir.
build_success_prop
Levando em consideração todas as builds de cada projeto, esta variável captura a proporção destas, que tiveram sucesso. Será explorada na segunda pergunta deste relatório.
test_size_avg
O tamanho médio dos testes em linhas de código.
Muitos commits e qualidade de código
Times que realizam commits muito frequentemente afetam a qualidade do código sendo produzido?
Vamos tentar responder a esta pergunta, observando as variáveis relacionadas.
data %>%
plot_ly(y = ~num_commits, x = ~(build_success_prop*100), type = "scatter", color = ~lang, colors = "Set1") %>%
layout(yaxis = list(title = "Número de commits", type = "log"),
xaxis = list(title = "Porcentagem de sucessos nos builds"))## No scatter mode specifed:
## Setting the mode to markers
## Read more about this attribute -> https://plot.ly/r/reference/#scatter-mode
A partir da visualização, vemos que os pontos estão bem dispersos ao longo do eixo x, não parece intuitivo que exista uma relação que sugira que quando uma variável cresce, a outra acompanha a tendência. Entretanto, para poder dar suporte as nossas observações, calcularemos a correlação entre estas variáveis, uma medida estatística que quantifica esta tendência que buscamos nos dados. A correlação pode ser calculada de três métodos diferentes e sempre será um valor entre -1 e 1, onde -1 representa uma correlação inversa forte e 1 representa uma correlação linear forte.
pearson <- c(cor(data$build_success_prop, data$num_commits, method = "pearson"))
kendall <- c(cor(data$build_success_prop, data$num_commits, method = "kendall"))
spearman <- c(cor(data$build_success_prop, data$num_commits, method = "spearman"))
cors <- data_frame(pearson, kendall, spearman)
kable(cors)| pearson | kendall | spearman |
|---|---|---|
| -0.0354749 | -0.025606 | -0.0378659 |
A tabela apresenta os três valores referentes as três formas de calcular a correlação entre as variáveis. Todos podem ser interpretados como indicativos de ausência de correlação ou de correlação fraca. Baseados nestes dados, podemos concluir que pelo menos para os dados que possuímos, o número de commits não representa qualquer influência na qualidade do código.
Correlações com o número de commits
Entretanto, algumas dúvidas sobre nossa análise surgem. Ter muitos commits pode ser uma informação que depende do contexto do projeto, por exemplo, podemos entender que projetos com mais membros possuam a tendência a ter mais commits, ou até projetos mais longos. Desta maneira, a comparação de todos os projetos não seria justa. Para decidir se estas observações procedem, podemos buscar entender que variável possui maior correlação com o número de commits.
time_x_commits <- data %>%
plot_ly(x = ~team, y = ~num_commits, type = "scatter", name = "Time x Commits") %>%
layout(xaxis = list(type = "log"),
yaxis = list(type = "log"))
tamanho_x_commits <- data %>%
plot_ly(x = ~sloc_end, y = ~num_commits, type = "scatter", name = "Projeto x Commits") %>%
layout(xaxis = list(type = "log"),
yaxis = list(type = "log"))
subplot(time_x_commits, tamanho_x_commits)## No scatter mode specifed:
## Setting the mode to markers
## Read more about this attribute -> https://plot.ly/r/reference/#scatter-mode
## No scatter mode specifed:
## Setting the mode to markers
## Read more about this attribute -> https://plot.ly/r/reference/#scatter-mode
Pelos gráficos acima, somos levados a acreditar que o tamanho do time tem uma relação mais forte com o número de commits, uma vez que a forma do gráfico referente a time, forma uma massa de dados em que o número de commits parece crescer mais ou menos quão maior o time.
variavel <- c("Tamanho do time", "Tamanho do projeto")
pearson <- c(cor(data$num_commits, data$team, method = "pearson"),
cor(data$num_commits, data$sloc_end, method = "pearson"))
kendall <- c(cor(data$num_commits, data$team, method = "kendall"),
cor(data$num_commits, data$sloc_end, method = "kendall"))
spearman <- c(cor(data$num_commits, data$team, method = "spearman"),
cor(data$num_commits, data$sloc_end, method = "spearman"))
tabela_cors <- data_frame(variavel, pearson, kendall, spearman)
kable(tabela_cors)| variavel | pearson | kendall | spearman |
|---|---|---|---|
| Tamanho do time | 0.5960980 | 0.3527356 | 0.4858465 |
| Tamanho do projeto | 0.1766263 | 0.1601898 | 0.2384767 |
Os valores da tabela nos levam a crer que a correlação é muito fraca ou inexistente, desta forma, talvez a influência do tamanho do time e do projeto não sejam realmente tão relevantes.
Linguagens e o tamanho dos projetos
Quais as diferenças das linguagens em relação ao tamanho dos projetos?
Java e Ruby são duas linguagens bem diferentes, a principal diferença pode ser observada na sintaxe. Java é uma linguagem famosa por ser verborrágica, ou seja, precisar de mais linhas de código para realizar tarefas que outras linguagens (como o Ruby), realizariam em poucas linhas. Por esta fama, é facil presumir que os projetos escritos em Java sejam mais longos que os escritos em Ruby. Entretanto, estará esta hipótese correta? Para descobrir, analisaremos os tamanhos dos projetos.
data %>%
plot_ly(x = ~lang, y = ~sloc_end, type = "box", boxpoints = "all", color = ~lang, colors = "Set1") %>%
layout(xaxis = list(title = "Linguagem"),
yaxis = list(title = "Maior número de linhas de código no projeto", type = "log"))Este é o boxplot, uma visualização muito útil quando queremos analisar a distribuição de uma variável, a caixa demarca valores importantes, 50% dos projetos, estão na faixa de valores demarcados por ela, e a linha que corta a caixa ao meio representa a mediana da distribuição. Em outras palavras, a mediana nos diz que o projeto Java mediano possui cerca de 14 mil linhas de código, enquanto que o projeto mediano Ruby possui cerca de 1500 linhas. Estes valores não variam muito, na visualização podemos observar isso pelo tamanho da caixa, e temos caixas curtas. Isso implica dizer que grande parte dos projetos possui realmente valores de número de linhas de código próximos as medianas citadas. Vale salientar, que estamos lidando com uma escala logarítmica no eixo do número de linhas de código, então cada milímetro de distância entre os projetos representa na verdade uma grande variação.
Mas o que acontece se ao invés de usarmos o valor máximo de linhas que um projeto possuiu durante todo o seu tempo de desenvolvimento, usarmos o valor mediano?
data %>%
plot_ly(x = ~lang, y = ~sloc_med, type = "box", boxpoints = "all", color = ~lang, colors = "Set1") %>%
layout(xaxis = list(title = "Linguagem"),
yaxis = list(title = "Maior número de linhas de código no projeto", type = "log"))As mesmas tendências se repetem! Podemos concluir então com um pouco mais de precisão, que de fato os projetos Java tendem a ser mais longos que os projetos Ruby.
Tiramos conclusões sobre projetos inteiros, entretanto, será que estes achados se repetem para unidades menores dos projetos? Funções, metodos e outros, em Java, são maiores que seus correspondentes em Ruby?
Quais as diferenças das linguagens em relação ao tamanho dos testes?
Nos nossos dados, possuímos informações a respeito dos testes escritos nos projetos, utilizaremos agora estes, para comparar o tamanho destas unidade entre as duas linguagens estudadas.
data %>%
plot_ly(y = ~test_size_avg, x = ~gh_project_name, type = "scatter", color = ~lang, colors = "Set1") %>%
layout(yaxis = list(title = "Tamanho médio dos testes (em linhas de código)"),
xaxis = list(title = "Projeto", showticklabels = FALSE))## No scatter mode specifed:
## Setting the mode to markers
## Read more about this attribute -> https://plot.ly/r/reference/#scatter-mode
Aqui, mais uma vez temos o problema de alguns projetos com valores extremos poluindo a nossa visualização, como a maior parte dos projetos estão mais próximos de valores pequenos, utilizaremos mais uma vez a escala logarítmica.
data %>%
plot_ly(y = ~test_size_avg, x = ~gh_project_name, type = "scatter", color = ~lang, colors = "Set1") %>%
layout(yaxis = list(title = "Tamanho médio dos testes (em linhas de código)", type = "log"),
xaxis = list(title = "Projeto", showticklabels = FALSE))## No scatter mode specifed:
## Setting the mode to markers
## Read more about this attribute -> https://plot.ly/r/reference/#scatter-mode
Os pontos vermelhos (representando projetos Java), parecem estar um pouco mais concentrados em cima. Se levarmos em consideração que estamos usando a escala logarítmica, sabemos que esta pequena diferença pode representar ordens de grandeza maiores. Para obtermos dados mais conclusivos, faremos mais uma vez, uso do boxplot.
data %>%
plot_ly(y = ~test_size_avg, x = ~lang, type = "box", color = ~lang, colors = "Set1") %>%
layout(yaxis = list(title = "Tamanho médio dos testes (em linhas de código)", type = "log"),
xaxis = list(title = "Linguagem", showticklabels = FALSE))Agora podemos ter uma ideia melhor da distribuição dos dados. A faixa de valores que os projetos assumem é muito extensa, de 0 a cerca de 3000. Podemos ver também que há muitos pontos extremos, e que a mediana de projetos Java é maior que a mediana de projetos Ruby.
- Mediana do tamanho dos testes nos projetos Java: 16.1966205.
- Mediana do tamanho dos testes nos projetos Ruby: 9.055918.
Mais importante, a caixa referente a Java está posicionada mais acima em relação a caixa do Ruby, isto implica dizer que se separarmos os 75% projetos que possuem os maiores testes em java e em Ruby, o subgrupo dos projetos Java ainda possui testes maiores do que o equivalente em Ruby.
Portanto sim, além de os projetos Java serem maiores que os projetos Ruby em geral, agora sabemos que os testes escritos em Java são de fato maiores.
Uma observação muito importante que deve ser feita, é que nada nesta análise, pode servir como argumento de causalidade. Vários fatores podem ser a causa da diferença no tamanho dos testes / projetos, como por exemplo a amostra dos projetos que selecionamos, e os hábitos dos programadores.