Estoy realmente interesado en las tendencias que vemos en el mercado laboral de ingeniería de software. A veces es realmente difícil contar una narrativa cohesiva y precisa sobre lo que está sucediendo porque sucede muy rápido y muy pocas personas recopilan datos al respecto.
Por ejemplo, aquí hay algunas preguntas cuya respuesta me gustaría saber:
Agregué todas las respuestas sobre el empleo de desarrolladores de los últimos 9 años de las encuestas de Stack Overflow para poder comenzar a responder algunas de estas preguntas. Si tiene curiosidad acerca de las perspectivas laborales para los desarrolladores , con suerte, estos son datos útiles.
Todos los números en las tablas representan el porcentaje de encuestados que se identificaron como un tipo de trabajo determinado.
Las preguntas formuladas por SO han cambiado a lo largo de los años, por lo que debemos tomar eso con un gran grano de sal.
He normalizado las respuestas. Por ejemplo, "desarrollador, back-end" y "desarrollador web back-end" los he agrupado como "back-end".
El desbordamiento de pila permitió a las personas seleccionar 0-muchos títulos de trabajo después de 2015, antes de eso, parece que estaban limitados a uno.
En algunos años, los desarrolladores tenían más opciones de trabajo para elegir.
He desechado muchos tipos de trabajos fuera de tema, como "desarrollador de servicios empresariales" y "funcionario electo".
Estos son solo datos de desbordamiento de pila, por lo que están sesgados por el tamaño de su base de usuarios cada año.
Dicho esto, entremos en los datos. Dejaré el script que escribí para crear los datos agregados, así como un enlace a los datos sin procesar al final de este artículo.
año | completa pila | Interfaz | back-end |
---|---|---|---|
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, la proporción de desarrolladores "front-end" a desarrolladores "full-stack" era 15/85, mientras que la proporción de desarrolladores "back-end" a desarrolladores "full-stack" era 24/76.
La tendencia de "más full-stack, menos especialización" continúa a lo largo de los diez años completos de datos. Es importante tener en cuenta que en 2017/2018, la encuesta cambió drásticamente, por lo que vemos un gran cambio en los números.
Parece razonable concluir que la tendencia de la última década ha sido que hay un porcentaje cada vez menor de desarrolladores que solo realizan trabajo de front-end o solo de back-end. Cada vez más se están duplicando como ingenieros de pila completa.
Tenga en cuenta que esto también podría deberse a que ha habido más pequeñas y medianas empresas a lo largo de los años. Las empresas más pequeñas suelen requerir más generalistas, pero ahora solo estoy adivinando.
La proporción de ingenieros de front-end/back-end se ha mantenido bastante constante, con un poco menos del doble de ingenieros de back-end que de front-end.
Esto realmente me sorprendió, esperaba que la proporción de ingenieros front-end y back-end fuera más cercana a lo largo de los años.
año | back-end | DevOps | operaciones |
---|---|---|---|
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 |
En mi secuencia de comandos, traté de dividir las funciones más "operativas tradicionales" en la categoría "operaciones", y las cosas "DevOps" en la función "DevOps". Por ejemplo, "SRE" lo he considerado como "DevOps", mientras que "administrador de sistemas" es "operaciones".
¿Qué diablos pasó en 2017? Honestamente, los datos parecen estar rotos. Busqué los datos manualmente porque, según el sitio web , afirman que el 24% de los desarrolladores web dijeron que eran back-end, y el 75% de los encuestados afirmaron ser desarrolladores web.
Por el momento, me parece que deben haber tenido algunos calificadores en esos números porque simplemente no se están sumando en mi lado. Voy a excluir 2017 de mi análisis en las interpretaciones.
DevOps parece estar ganando terreno a las operaciones tradicionales. En 2013, nadie se identificaba como una persona "DevOps", pero para 2020 y 2021, los números se ven muy similares.
Vale la pena señalar que en 2016, los números de DevOps en realidad eclipsaron los números de "operaciones" durante un solo año. Mi mejor suposición es que 2016 fue cuando muchas empresas simplemente comenzaron a cambiar el nombre de sus equipos de "operaciones" a equipos de "DevOps" para verse bien.
Es difícil preocuparse demasiado por estos números porque, en mi opinión, DevOps se está haciendo mal . No confío en que los títulos de "operaciones" y los títulos de "DevOps" sean tan diferentes en la mayoría de las empresas.
"DevOps" parece tener la menor tendencia a la baja en los últimos años, de hecho, tuvo un buen salto en 2022. Sin embargo, si observa "DevOps" y "ops" juntos, entonces la categoría todavía tiene una tendencia a la baja.
Curiosamente, "ops" ha tenido una tendencia a la baja desde el principio, mientras que "back-end" tuvo una tendencia al alza hasta 2016, cuando la tendencia se revirtió y ha estado baja desde entonces.
Al principio, supuse que simplemente estábamos viendo la misma tendencia que vimos en el desarrollo web: más generalistas, menos especialistas.
Sin embargo, me volví escéptico porque cuando analicé todas las categorías laborales, noté que casi todas tenían una tendencia a la baja... lo que claramente no puede ser el caso cuando analizamos porcentajes: es un juego de suma cero.
Decidí agregar una nueva sección a mi guión para profundizar más. Calculé cuántos trabajos en promedio reclamaba cada encuestado y obtuve estos datos:
año | back-end | DevOps | operaciones | 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 entre 2013 y 2015, los desarrolladores estaban restringidos a enviar una sola respuesta, lo que ayuda a explicar los números súper bajos. Sin embargo, desde 2019->2021 el número promedio de trabajos por usuario disminuyó , lo que es antitético a la teoría de "más generalistas".
También vale la pena señalar que, a medida que pasaron los años, Stack Overflow agregó categorías más especializadas, que luego me tomé la libertad de agrupar en estos grupos más amplios.
Así que en realidad hay buena evidencia de que los desarrolladores se están especializando más, o al menos que hay más formas posibles en las que uno puede especializarse.
Dicho esto, incluso después de ver estos datos, creo que todavía hay un buen caso para argumentar que los desarrolladores de back-end harán cada vez más trabajo de "DevOps" , especialmente en las empresas más pequeñas.
año | type_data_science | ingeniero_de_datos | back-end |
---|---|---|---|
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 |
Es muy interesante para mí que la ingeniería de datos realmente solo comenzó a aparecer en los datos de la encuesta en 2019. Hasta entonces, supongo que los ingenieros de back-end y los científicos de datos asumieron ese papel. Esa nueva especialización es ciertamente interesante.
El aprendizaje automático ha crecido absolutamente durante la última década, pero parece que puede haber habido una especie de "burbuja exagerada" en 2017.
He hablado sobre mis interpretaciones personales con respecto a los datos que me parecieron más interesantes, pero aquí están todos los datos que agregué para que pueda revisarlos usted mismo:
año | avg_jobs_per_user | completa pila | Interfaz | back-end | DevOps | operaciones | móvil | escritorio | incrustado | Ciencia de los datos | ingeniero_de_datos | juego | administración | control de calidad | educación | diseño | analista | comercializador | pasar por alto |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
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 | 19.48 | 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 |
Aquí hay un enlace a los datos CSV sin procesar en Stack Overflow.
Aquí está el script de Python completo que usé para procesar los números. Perdón por el descuido del código, no dediqué mucho tiempo al código.
La parte más interesante de la secuencia de comandos es probablemente la función get_mapped_job
cerca de la parte inferior, ahí es donde agrego todos los muchos tipos de trabajo informados por los usuarios de desbordamiento de pila en los pocos que incluí en el 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()
También publicado aquí