Je suis vraiment intéressé par les tendances que nous voyons sur le marché du travail en génie logiciel. Parfois, il est vraiment difficile de raconter un récit cohérent et précis sur ce qui se passe parce que ça se passe tellement vite, et très peu de gens collectent des données à ce sujet.
Par exemple, voici quelques questions auxquelles j'aimerais connaître la réponse :
J'ai regroupé toutes les réponses sur l'emploi des développeurs des 9 dernières années d'enquêtes Stack Overflow afin de commencer à pouvoir répondre à certaines de ces questions. Si vous êtes curieux de connaître les perspectives d'emploi pour les développeurs , nous espérons que ces données seront utiles.
Tous les chiffres dans les tableaux représentent le pourcentage de personnes interrogées qui se sont identifiées comme un type d'emploi donné.
Les questions posées par SO ont changé au fil des ans, nous devons donc prendre cela avec un grain de sel géant.
J'ai normalisé les réponses. Par exemple, "développeur, back-end" et "développeur web back-end" que j'ai regroupés en "backend".
Le débordement de pile a permis aux gens de sélectionner 0 à plusieurs titres d'emploi après 2015, avant cela, il semble qu'ils étaient limités à un.
Certaines années, les développeurs avaient plus d'options d'emploi parmi lesquelles choisir.
J'ai jeté beaucoup de types d'emplois hors sujet comme "développeur de services d'entreprise" et "élu".
Il ne s'agit que de données Stack Overflow, elles sont donc biaisées par la taille de leur base d'utilisateurs chaque année.
Cela dit, entrons dans les données. Je vais supprimer le script que j'ai écrit pour créer les données agrégées ainsi qu'un lien vers les données brutes au bas de cet article.
an | un paquet entier | l'extrémité avant | backend |
---|---|---|---|
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 |
En 2013, le ratio développeurs "front-end"/développeurs "full-stack" était de 15/85, tandis que le ratio développeurs "back-end"/développeurs "full-stack" était de 24/76.
La tendance "plus de full-stack, moins de spécialisation" se poursuit tout au long des dix années de données. Il est important de noter qu'en 2017/2018, l'enquête a radicalement changé, c'est pourquoi nous constatons un grand changement dans les chiffres.
Il semble raisonnable de conclure que la tendance de la dernière décennie a été qu'il y a un pourcentage décroissant de développeurs qui ne font que du travail frontal ou uniquement du travail principal. De plus en plus sont doublés en tant qu'ingénieurs full-stack.
Gardez à l'esprit que cela pourrait également être dû au fait qu'il y a eu davantage de petites et moyennes entreprises au fil des ans. Les petites entreprises ont généralement besoin de plus de généralistes, mais maintenant je ne fais que deviner.
Le ratio ingénieurs front-end/back-end est resté assez constant, avec un peu moins de deux fois plus d'ingénieurs back-end que d'ingénieurs front-end.
Cela m'a en fait surpris, je m'attendais à ce que le rapport entre les ingénieurs front-end et back-end soit plus proche au fil des ans.
an | backend | DevOps | opérations |
---|---|---|---|
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 | 18h33 |
2019 | 45,75 | 11h43 | 15.93 |
2020 | 42.24 | 10.51 | 13.11 |
2021 | 34,84 | 9,75 | 10.82 |
2022 | 36,99 | 13.2 | 11.8 |
Dans mon script, j'ai essayé de diviser plus de rôles "ops traditionnels" dans la catégorie "ops", et les trucs "DevOps" dans le rôle "DevOps". Par exemple, "SRE" que j'ai considéré comme "DevOps", tandis que "administrateur système" est "ops".
Que s'est-il passé en 2017 ? Honnêtement, les données semblent juste brisées. J'ai creusé les données manuellement car selon le site Web , ils affirment que 24% des développeurs Web ont déclaré qu'ils étaient back-end et 75% des répondants ont déclaré être des développeurs Web.
Pour le moment, j'ai l'impression qu'ils ont dû avoir des qualifications sur ces chiffres, car cela ne correspond tout simplement pas à ma fin. Je vais exclure 2017 de mon analyse dans les interprétations.
DevOps semble gagner du terrain sur les opérations traditionnelles. En 2013, personne ne s'identifiait comme une personne "DevOps", mais en 2020 et 2021, les chiffres sont très similaires.
Il convient de souligner qu'en 2016, les chiffres DevOps ont en fait éclipsé les chiffres "ops" pendant une seule année. Ma meilleure hypothèse est que 2016 était à peu près le moment où de nombreuses entreprises ont simplement commencé à rebaptiser leurs équipes "ops" en équipes "DevOps" afin d'avoir l'air cool.
Il est difficile de trop se soucier de ces chiffres, car DevOps est généralement mal fait à mon avis. Je ne crois pas que les titres "ops" et les titres "DevOps" soient si différents dans la plupart des entreprises.
"DevOps" semble avoir le moins baissé ces dernières années, en fait, il a fait un bon bond en 2022. Cependant, si vous regardez "DevOps" et "ops" ensemble, alors la catégorie a encore un peu tendance à baisser.
Fait intéressant, "ops" a eu une tendance à la baisse depuis le début, tandis que "back-end" a eu une tendance à la hausse jusqu'en 2016, date à laquelle la tendance s'est inversée et elle est en baisse depuis.
Au début, j'ai supposé que nous voyions simplement la même tendance que celle que nous avons vue dans le développement Web : plus de généralistes, moins de spécialistes.
Cependant, je suis devenu sceptique parce que lorsque j'ai examiné toutes les catégories d'emplois, j'ai remarqué que presque toutes avaient tendance à baisser... ce qui ne peut clairement pas être le cas lorsque nous examinons les pourcentages - c'est un jeu à somme nulle.
J'ai décidé d'ajouter une nouvelle section à mon script pour approfondir. J'ai calculé combien d'emplois en moyenne chaque enquêteur revendiquait et j'ai obtenu ces données :
an | backend | DevOps | opérations | 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 | 18h33 | 2,79 |
2019 | 45,75 | 11h43 | 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 |
Il semble que de 2013 à 2015, les développeurs étaient limités à ne soumettre qu'une seule réponse, ce qui aide à tenir compte des nombres extrêmement bas. Cependant, de 2019 à 2021, le nombre moyen d'emplois par utilisateur a diminué , ce qui est contraire à la théorie "plus généraliste".
Il convient également de souligner qu'au fil des années, Stack Overflow a en fait ajouté des catégories plus spécialisées, que j'ai ensuite pris la liberté de regrouper dans ces groupes plus larges.
Il y a donc de bonnes preuves que les développeurs se spécialisent davantage, ou à tout le moins qu'il existe plus de façons possibles de se spécialiser.
Cela dit, même après avoir examiné ces données, je pense qu'il y a encore de bonnes raisons de penser que les développeurs back-end feront de plus en plus de travail "DevOps" , en particulier dans les petites entreprises.
an | type_data_science | data_engineer | backend |
---|---|---|---|
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 |
C'est super intéressant pour moi que l'ingénierie des données n'ait vraiment commencé à apparaître dans les données de l'enquête qu'en 2019. Jusque-là, je suppose que les ingénieurs back-end et les data scientists ont englouti ce rôle. Cette nouvelle spécialisation est certainement intéressante.
L'apprentissage automatique s'est absolument développé au cours de la dernière décennie, mais il semble qu'il y ait eu une sorte de "bulle de battage médiatique" en 2017 ?
J'ai parlé de mes interprétations personnelles concernant les données que j'ai trouvées les plus intéressantes, mais voici toutes les données que j'ai agrégées pour que vous puissiez les inspecter vous-même :
an | avg_jobs_per_user | un paquet entier | l'extrémité avant | backend | DevOps | opérations | portable | bureau | embarqué | data_science | data_engineer | Jeu | la gestion | AQ | éducation | motif | analyste | agent de commercialisation | ignorer |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
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 | 18h33 | 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 | 11h43 | 15.93 | 16.54 | 19h48 | 8h15 | 7.27 | 6,55 | 4,99 | 6.34 | 7.15 | 10.18 | 10h33 | 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 | 10h42 | 13.03 | 5.35 | 4,67 | 4,91 | 2.51 | 10h44 | 4.23 | 5,78 | 5.14 | 4.37 | 0,71 | 32.06 |
Voici un lien vers les données CSV brutes sur Stack Overflow.
Voici le script Python complet que j'ai utilisé pour calculer les chiffres. Désolé pour la négligence du code, je n'ai pas perdu beaucoup de temps dans le code.
La partie la plus intéressante du script est probablement la fonction get_mapped_job
près du bas, c'est là que j'agrège tous les nombreux types de travaux signalés par les utilisateurs de débordement de pile dans les quelques-uns que j'ai inclus dans le graphique.
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()
Également publié ici