Estou realmente interessado nas tendências que vemos no mercado de trabalho de engenharia de software. Às vezes é muito difícil contar uma narrativa coesa e precisa sobre o que está acontecendo porque acontece muito rápido e muito poucas pessoas estão coletando dados sobre o assunto.
Por exemplo, aqui estão algumas perguntas para as quais eu gostaria de saber a resposta:
Agreguei todas as respostas sobre o emprego de desenvolvedores dos últimos 9 anos de pesquisas do Stack Overflow para começar a responder a algumas dessas perguntas. Se você está curioso sobre as perspectivas de emprego para desenvolvedores , esperamos que esses dados sejam úteis.
Todos os números nas tabelas representam a porcentagem de respondentes da pesquisa que se identificaram como um determinado tipo de trabalho.
As perguntas feitas pelo SO mudaram ao longo dos anos, então devemos levar isso com um grande grão de sal.
Eu normalizei as respostas. Por exemplo, "desenvolvedor, back-end" e "desenvolvedor web back-end" agrupados como "back-end".
O estouro de pilha permitiu que as pessoas selecionassem 0-muitos cargos após 2015, antes disso, parece que eles estavam limitados a um.
Em alguns anos, os desenvolvedores tinham mais opções de trabalho para escolher.
Joguei fora muitos tipos de trabalho fora do tópico, como "desenvolvedor de serviços corporativos" e "funcionário eleito".
Esses são apenas dados do Stack Overflow, portanto, são influenciados pelo tamanho de sua base de usuários a cada ano.
Dito isso, vamos aos dados. Vou deixar cair o script que escrevi para criar os dados agregados, bem como um link para os dados brutos na parte inferior deste artigo.
ano | pilha completa | a parte dianteira | Processo interno |
---|---|---|---|
2013 | 24,5 | 4.31 | 7,88 |
2014 | 25,72 | 5.02 | 9.3 |
2015 | 25,93 | 4,76 | 8.07 |
2016 | 37,88 | 5.13 | 10.82 |
2017 | 51.05 | 2.47 | 5.08 |
2018 | 44,87 | 35.22 | 53,92 |
2019 | 47,5 | 29,98 | 45,75 |
2020 | 42.08 | 28.38 | 42.24 |
2021 | 39,42 | 21.85 | 34,84 |
2022 | 39.17 | 21.72 | 36,99 |
Em 2013, a proporção de desenvolvedores "front-end" para desenvolvedores "full-stack" era de 15/85, enquanto a proporção de desenvolvedores "back-end" para desenvolvedores "full-stack" era de 24/76.
A tendência de "mais full-stack, menos especialização" continua por todos os dez anos de dados. É importante observar que em 2017/2018 a pesquisa mudou drasticamente, por isso vemos uma grande mudança nos números.
Parece razoável concluir que a tendência da última década foi que há uma porcentagem cada vez menor de desenvolvedores que fazem apenas trabalho de front-end ou apenas trabalho de back-end. Mais e mais estão dobrando como engenheiros full-stack.
Lembre-se de que também pode ter havido mais empresas de pequeno a médio porte ao longo dos anos. Empresas menores geralmente exigem mais generalistas, mas agora estou apenas supondo.
A proporção de engenheiros de front-end/back-end permaneceu bastante consistente, com um pouco menos que o dobro de engenheiros de back-end do que engenheiros de front-end.
Isso realmente me surpreendeu, eu esperava que a proporção de engenheiros de front-end para back-end fosse mais próxima ao longo dos anos.
ano | Processo interno | DevOps | ops |
---|---|---|---|
2013 | 7.88 | 0 | 2,96 |
2014 | 9.3 | 1.61 | 2,85 |
2015 | 8.07 | 1.23 | 1,77 |
2016 | 10.82 | 1,92 | 1,79 |
2017 | 5.08 | 7.81 | 13.66 |
2018 | 53,92 | 9.66 | 18.33 |
2019 | 45,75 | 11.43 | 15.93 |
2020 | 42.24 | 10.51 | 13.11 |
2021 | 34,84 | 9,75 | 10.82 |
2022 | 36,99 | 13.2 | 11.8 |
Em meu script, tentei dividir mais funções de "operações tradicionais" na categoria "operações" e as coisas "DevOps" na função "DevOps". Por exemplo, "SRE" considerei como "DevOps", enquanto "administrador de sistemas" é "ops".
O que diabos aconteceu em 2017? Os dados honestamente parecem quebrados. Pesquisei os dados manualmente porque, de acordo com o site , eles afirmam que 24% dos desenvolvedores da web disseram que eram back-end e 75% dos entrevistados afirmaram ser desenvolvedores da web.
No momento, parece-me que eles devem ter alguns qualificadores nesses números, porque simplesmente não está somando para mim. Vou excluir 2017 da minha análise nas interpretações.
O DevOps parece estar ganhando terreno nas operações tradicionais. Em 2013, ninguém se identificava como uma pessoa "DevOps", mas em 2020 e 2021, os números são muito semelhantes.
Vale ressaltar que, em 2016, os números de DevOps na verdade eclipsaram os números de "operações" em um único ano. Meu melhor palpite é que 2016 foi quando muitas empresas começaram a simplesmente renomear suas equipes "ops" como equipes "DevOps" para parecerem legais.
É difícil se importar muito com esses números porque o DevOps está sendo feito de maneira errada , na minha opinião. Não acredito que os títulos "ops" e os títulos "DevOps" sejam tão diferentes na maioria das empresas.
"DevOps" parece estar diminuindo menos nos últimos anos, na verdade, teve um bom salto em 2022. No entanto, se você olhar para "DevOps" e "ops" juntos, a categoria ainda está diminuindo um pouco.
Curiosamente, "ops" tem tendência de queda desde o início, enquanto "back-end" estava em alta até 2016, quando a tendência se inverteu e caiu desde então.
A princípio, presumi que estávamos simplesmente vendo a mesma tendência que vimos no desenvolvimento da Web: mais generalistas, menos especialistas.
No entanto, fiquei cético porque, quando olhei para todas as categorias de trabalho, notei que quase todas estavam em tendência de queda... o que claramente não pode ser o caso quando olhamos para porcentagens - é um jogo de soma zero.
Decidi adicionar uma nova seção ao meu script para me aprofundar mais. Calculei quantos empregos, em média, cada participante da pesquisa reivindicava e obtive estes dados:
ano | Processo interno | DevOps | ops | avg_jobs_per_user |
---|---|---|---|---|
2013 | 7.88 | 0 | 2,96 | 1 |
2014 | 9.3 | 1.61 | 2,85 | 1 |
2015 | 8.07 | 1.23 | 1,77 | 1 |
2016 | 10.82 | 1,92 | 1,79 | 1,89 |
2017 | 5.08 | 7.81 | 13.66 | 2.48 |
2018 | 53,92 | 9.66 | 18.33 | 2.79 |
2019 | 45,75 | 11.43 | 15.93 | 2.84 |
2020 | 42.24 | 10.51 | 13.11 | 2.59 |
2021 | 34,84 | 9,75 | 10.82 | 2.21 |
2022 | 36,99 | 13.2 | 11.8 | 2.27 |
Parece que, de 2013 a 2015, os desenvolvedores ficaram restritos a enviar apenas uma única resposta, o que ajuda a explicar os números super baixos. No entanto, de 2019 a 2021, o número médio de empregos por usuário caiu , o que é antitético à teoria dos "mais generalistas".
Também vale ressaltar que, com o passar dos anos, o Stack Overflow na verdade adicionou categorias mais especializadas, que tomei a liberdade de agrupar nesses grupos mais amplos.
Portanto, há boas evidências de que os desenvolvedores estão se especializando mais ou, pelo menos, de que existem mais maneiras possíveis de se especializar.
Dito isto, mesmo depois de olhar para esses dados, acho que ainda há um bom argumento a ser feito de que os desenvolvedores de back-end farão cada vez mais trabalhos de "DevOps" , especialmente em empresas menores.
ano | type_data_science | engenheiro de dados | Processo interno |
---|---|---|---|
2013 | 0 | 0 | 7.88 |
2014 | 0 | 0 | 9.3 |
2015 | 2.12 | 0,69 | 8.07 |
2016 | 3.83 | 0,7 | 10.82 |
2017 | 9.14 | 0 | 5.08 |
2018 | 7.17 | 0 | 53,92 |
2019 | 7.27 | 6.55 | 45,75 |
2020 | 6.19 | 5.8 | 42.24 |
2021 | 5.12 | 5 | 34,84 |
2022 | 4,67 | 4,91 | 36,99 |
É super interessante para mim que a engenharia de dados realmente só começou a aparecer nos dados da pesquisa em 2019. Até então, acho que engenheiros de back-end e cientistas de dados engoliram essa função. Essa nova especialização é certamente interessante.
O aprendizado de máquina cresceu absolutamente na última década, mas parece que pode ter havido uma "bolha de hype" em 2017?
Falei sobre minhas interpretações pessoais sobre os dados que achei mais interessantes, mas aqui estão todos os dados que agreguei para que você mesmo possa inspecionar:
ano | avg_jobs_per_user | pilha completa | a parte dianteira | Processo interno | DevOps | ops | Móvel | Área de Trabalho | embutido | data_science | engenheiro de dados | jogos | gestão | controle de qualidade | Educação | Projeto | analista | comerciante | ignorar |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
2013 | 1 | 24,5 | 4.31 | 7.88 | 0 | 2,96 | 6.48 | 9.53 | 2.16 | 0 | 0 | 0 | 7.49 | 0 | 0 | 0 | 0 | 0 | 34,7 |
2014 | 1 | 25,72 | 5.02 | 9.3 | 1.61 | 2,85 | 7.57 | 9.43 | 2.42 | 0 | 0 | 0 | 5.9 | 0 | 0 | 0 | 0 | 0 | 30.18 |
2015 | 1 | 25,93 | 4,76 | 8.07 | 1.23 | 1,77 | 7.28 | 6,65 | 2.33 | 2.12 | 0,69 | 0,63 | 1.44 | 0,63 | 0 | 0,57 | 0 | 0,23 | 35,66 |
2016 | 1,89 | 37,88 | 5.13 | 10.82 | 1,92 | 1,79 | 7.39 | 6.05 | 2.26 | 3,83 | 0,7 | 0,52 | 10.04 | 0,68 | 0 | 0,59 | 1.02 | 0,21 | 98,65 |
2017 | 2.48 | 51.05 | 2.47 | 5.08 | 7.81 | 13.66 | 16.2 | 20.3 | 6.52 | 9.14 | 0 | 3.37 | 0,5 | 2.44 | 1.42 | 3,94 | 3,69 | 0,3 | 100 |
2018 | 2,79 | 44,87 | 35.22 | 53,92 | 9.66 | 18.33 | 19.02 | 15,99 | 4,87 | 7.17 | 0 | 4.7 | 7,99 | 6.27 | 3,68 | 12.16 | 7,65 | 1.13 | 26.63 |
2019 | 2.84 | 47,5 | 29,98 | 45,75 | 11.43 | 15.93 | 16.54 | 19h48 | 8.15 | 7.27 | 6.55 | 4,99 | 6.34 | 7.15 | 10.18 | 10.33 | 7.08 | 1.1 | 28.37 |
2020 | 2.59 | 42.08 | 28.38 | 42.24 | 10.51 | 13.11 | 14.71 | 18.28 | 7.37 | 6.19 | 5.8 | 4.33 | 5.54 | 6.12 | 8.67 | 8.25 | 6.24 | 1 | 30.18 |
2021 | 2.21 | 39,42 | 21.85 | 34,84 | 9,75 | 10.82 | 11.74 | 13.23 | 5.51 | 5.12 | 5 | 2.53 | 6.37 | 4.33 | 5.56 | 5.53 | 4.54 | 0,76 | 34.51 |
2022 | 2.27 | 39.17 | 21.72 | 36,99 | 13.2 | 11.8 | 10.42 | 13.03 | 5.35 | 4,67 | 4,91 | 2.51 | 10.44 | 4.23 | 5,78 | 5.14 | 4.37 | 0,71 | 32.06 |
Aqui está um link para os dados CSV brutos no Stack Overflow.
Aqui está o script Python completo que usei para analisar os números. Desculpe pelo desleixo do código, não perdi muito tempo no código.
A parte mais interessante do script é provavelmente a função get_mapped_job
próxima à parte inferior, onde agrego todos os muitos tipos de trabalho relatados pelos usuários de estouro de pilha nos poucos que incluí no gráfico.
import csv outpath = "csv/out.csv" type_devops = "devops" type_ops = "ops" type_backend = "backend" type_frontend = "frontend" type_mobile = "mobile" type_fullstack = "fullstack" type_desktop = "desktop" type_embedded = "embedded" type_data_science = "data_science" type_ignore = "ignore" type_management = "management" type_education = "education" type_design = "design" type_marketer = "marketer" type_data_engineer = "data_engineer" type_game = "game" type_analyst = "analyst" type_qa = "qa" def main(): files = [ (2013, [6]), (2014, [6]), (2015, [5]), (2016, [8, 9, 10]), (2017, [14, 15, 16, 17]), (2018, [9]), (2019, [12]), (2020, [13]), (2021, [11]), (2022, [11]), ] out_dict = {} jobs_per_user_dict = {} for f_tup in files: counts = {} path = f"csv/{f_tup[0]}.csv" print(f"generating report for {path}") out_dict[f_tup[0]]: {} with open(path, "r") as csvfile: rows = csv.reader(csvfile, delimiter=",") count = 0 rows_cpy = [] jobs_per_user = [] for row in rows: count += 1 rows_cpy.append(row) for row in rows_cpy: try: jobs = get_jobtext_from_cells(f_tup[1], row) mapped_jobs = set() for job in jobs: mapped_jobs.add(get_mapped_job(job)) jobs_per_user.append(mapped_jobs) for mapped_job in mapped_jobs: if mapped_job not in counts: counts[mapped_job] = 0 counts[mapped_job] += 1 except Exception as e: print(e) avg_jobs_per_user = 0 for user_jobs in jobs_per_user: avg_jobs_per_user += len(user_jobs) jobs_per_user_dict[f_tup[0]] = round( avg_jobs_per_user / len(jobs_per_user), 2 ) for job in counts: counts[job] /= count counts[job] *= 100 counts[job] = round(counts[job], 2) out_dict[f_tup[0]] = counts write_out(out_dict, jobs_per_user_dict) def get_jobtext_from_cells(indexes, row): if len(indexes) == 0: return [] job_texts = [] for i in indexes: cell = row[i] cell_job_texts = cell.split(";") job_texts += cell_job_texts return job_texts def write_out(out_dict, jobs_per_user_dict): types = [ type_fullstack, type_frontend, type_backend, type_devops, type_ops, type_mobile, type_desktop, type_embedded, type_data_science, type_data_engineer, type_game, type_management, type_qa, type_education, type_design, type_analyst, type_marketer, type_ignore, ] with open(outpath, "w") as csvfile: w = csv.writer(csvfile) w.writerow(["year", "avg_jobs_per_user"] + types) for year in out_dict: row = [year, jobs_per_user_dict[year]] for t in types: row.append(out_dict[year][t] if t in out_dict[year] else 0) w.writerow(row) def get_mapped_job(job): job = job.lower().strip() if job == "": return type_ignore if job == "devops specialist": return type_devops if job == "designer": return type_design if job == "c-suite executive": return type_management if job == "analyst or consultant": return type_analyst if job == "back-end developer": return type_backend if job == "windows phone": return type_mobile if job == "i don't work in tech": return type_ignore if job == "growth hacker": return type_marketer if job == "desktop developer": return type_desktop if job == "analyst": return type_analyst if job == "executive (vp of eng., cto, cio, etc.)": return type_management if job == "mobiledevelopertype": return type_mobile if job == "engineer, data": return type_data_engineer if job == "graphics programmer": return type_game if job == "systems administrator": return type_ops if job == "developer, game or graphics": return type_game if job == "desktop software developer": return type_desktop if job == "nondevelopertype": return type_ignore if job == "elected official": return type_ignore if job == "engineering manager": return type_management if job == "web developer": return type_fullstack if job == "machine learning specialist": return type_data_science if job == "data or business analyst": return type_analyst if job == "devtype": return type_fullstack if job == "response": return type_ignore if job == "developer, qa or test": return type_qa if job == "machine learning developer": return type_data_science if job == "developer, front-end": return type_frontend if job == "database administrator": return type_ops if job == "android": return type_mobile if job == "webdevelopertype": return type_fullstack if job == "blackberry": return type_mobile if job == "system administrator": return type_ops if job == "mobile developer - android": return type_mobile if job == "developertype": return type_fullstack if job == "ios": return type_mobile if job == "developer with a statistics or mathematics background": return type_ignore if job == "qa or test developer": return type_qa if job == "educator or academic researcher": return type_education if job == "engineer, site reliability": return type_devops if job == "marketing or sales professional": return type_marketer if job == "student": return type_ignore if job == "back-end web developer": return type_backend if job == "educator": return type_education if job == "front-end developer": return type_frontend if job == "developer, desktop or enterprise applications": return type_desktop if job == "senior executive/vp": return type_management if job == "occupation": return type_ignore if job == "scientist": return type_ignore if job == "developer, full-stack": return type_fullstack if job == "graphic designer": return type_design if job == "developer, embedded applications or devices": return type_embedded if job == "embedded application developer": return type_embedded if job == "quality assurance": return type_qa if job == "graphics programming": return type_game if job == "senior executive (c-suite, vp, etc.)": return type_management if job == "it staff / system administrator": return type_ops if job == "business intelligence or data warehousing expert": return type_data_engineer if job == "full stack web developer": return type_fullstack if job == "developer, mobile": return type_mobile if job == "front-end web developer": return type_frontend if job == "desktop applications developer": return type_desktop if job == "other (please specify):": return type_ignore if job == "mobile developer": return type_mobile if job == "devops": return type_devops if job == "enterprise level services developer": return type_ignore if job == "data scientist": return type_data_science if job == "executive (vp of eng, cto, cio, etc.)": return type_management if job == "mobile developer - ios": return type_mobile if job == "game or graphics developer": return type_game if job == "which of the following best describes your occupation?": return type_ignore if job == "other": return type_ignore if job == "desktop or enterprise applications developer": return type_desktop if job == "c-suite executive (ceo, cto, etc.)": return type_management if job == "embedded applications/devices developer": return type_embedded if job == "product manager": return type_ignore if job == "mobile application developer": return type_mobile if job == "mobile developer - windows phone": return type_mobile if job == "data scientist or machine learning specialist": return type_data_science if job == "educator or academic": return type_education if job == "embedded applications or devices developer": return type_embedded if job == "quality assurance engineer": return type_qa if job == "enterprise level services": return type_ignore if job == "full-stack developer": return type_fullstack if job == "na": return type_ignore if job == "academic researcher": return type_education if job == "manager of developers or team leader": return type_management if job == "marketing or sales manager": return type_marketer if job == "developer, back-end": return type_backend if job == "full-stack web developer": return type_fullstack if job == "designer or illustrator": return type_design if job == "programmer": return type_ignore if job == "developer": return type_ignore if job == "manager": return type_management if job == "engineer": return type_ignore if job == "sr. developer": return type_ignore if job == "full stack overflow developer": return type_fullstack if job == "ninja": return type_ignore if job == "mobile dev (android, ios, wp & multi-platform)": return type_mobile if job == "expert": return type_ignore if job == "rockstar": return type_ignore if job == "hacker": return type_ignore if job == "guru": return type_ignore if job == "self_identification": return type_ignore if job == "occupation_group": return type_ignore if job == "cloud infrastructure engineer": return type_devops if job == "project manager": return type_management if job == "security professional": return type_ops if job == "blockchain": return type_backend if ( job == "mathematics developers (data scientists, machine learning devs & devs with stats & math backgrounds)" ): return type_data_science raise Exception(f"job not mapped: {job}") main()
Também publicado aqui