Взгляд на тенденции в работе разработчиков: метаанализ опросов Stack Overflow
25 октября 2022 г.Меня очень интересуют тенденции, наблюдаемые на рынке труда разработчиков программного обеспечения. Иногда очень сложно составить целостное и точное повествование о том, что происходит, потому что это происходит чертовски быстро, и очень немногие люди собирают данные по этому вопросу.
Например, вот несколько вопросов, на которые я хотел бы получить ответ:
* Означает ли «DevOps» и более широкое использование облака меньшее количество традиционных рабочих мест? * Означают ли такие вещи, как Firebase и Supabase, меньше внутренних заданий? * Означают ли такие вещи, как попутный ветер, меньше дизайнеров? * Мы переходим на более специализированные или более универсальные роли? * Люди все еще специализируются на администраторах баз данных?
Я собрал все ответы о занятости разработчиков из опросов Stack Overflow за последние 9 лет, чтобы начать отвечать на некоторые из этих вопросов. Если вам интересны перспективы работы для разработчиков, надеюсь, это полезные данные.
Во-первых, примечание к данным
- Все цифры в таблицах представляют собой процент участников опроса, которые определили себя как работу определенного типа.
2. Вопросы, которые задает SO, с годами изменились, поэтому мы должны воспринимать это с большой долей скептицизма.
3. Я нормализовал ответы. Например, "разработчик, бэкэнд" и "бэкэнд веб-разработчик" я сгруппировал как "бэкэнд".
4. После 2015 года переполнение стека позволяло людям выбирать 0-много наименований должностей, до этого они, по-видимому, ограничивались одним.
5. В некоторые годы у разработчиков было больше вариантов работы.
6. Я выбросил много не относящихся к теме вакансий, таких как "разработчик корпоративных услуг" и "выборное должностное лицо".
7. Это только данные Stack Overflow, поэтому они смещены из-за размера их пользовательской базы каждый год.
Тем не менее, давайте перейдем к данным. Я оставлю сценарий, который написал для создания агрегированных данных, а также ссылку на необработанные данные внизу этой статьи.
Веб-тенденции: полный стек, интерфейс и серверная часть
| год | полный стек | интерфейс | бэкэнд | |----|----|----|----| | 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 |
В 2013 г. соотношение между разработчиками внешнего интерфейса и разработчиками полного стека составляло 15 / 85, а соотношение разработчиков бэкенда и разработчиков полного стека — 24 / 76.< /p>
Тенденция «больше полного стека, меньше специализации» сохраняется на протяжении всех десяти лет данных. Важно отметить, что в 2017/2018 г. опрос резко изменился, поэтому мы наблюдаем большие изменения в цифрах.
Интерпретация №1
Кажется разумным сделать вывод, что тенденция последнего десятилетия заключалась в том, что процент разработчиков, выполняющих только работу с интерфейсом или только бэк-энд, сокращается. закончить работу. Все больше и больше специалистов работают по совместительству в качестве полнофункциональных инженеров.
Имейте в виду, что это также возможно из-за того, что с годами стало больше малых и средних компаний. Небольшим компаниям обычно требуется больше универсалов, но сейчас я просто предполагаю.
Интерпретация № 2
Соотношение между инженерами клиентской части и инженерами внутренней части остается довольно стабильным: инженеров внутренней части почти в два раза больше, чем инженеров внешнего интерфейса.
Меня это на самом деле удивило, я ожидал, что с годами соотношение между фронтенд- и бэкенд-инженерами будет ближе.
Тенденции в области ИТ-операций: серверная часть, DevOps и традиционные операции
| год | бэкэнд | DevOps | операции | |----|----|----|----| | 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 |
В своем сценарии я попытался разделить больше "традиционных ролей" на категорию "эксплуатация", а "DevOps" - на роль "DevOps". Например, «SRE» я рассматривал как «DevOps», а «системный администратор» — как «ops».
Предупреждение о данных за 2017 год
Что, черт возьми, произошло в 2017 году? Честно говоря, данные просто кажутся сломанными. Я просмотрел данные вручную, потому что, согласно веб-сайту, они утверждают, 24% веб-разработчиков заявили, что они занимаются бэкендом, а 75% респондентов заявили, что являются веб-разработчиками.
На данный момент мне кажется, что у них должны быть какие-то квалификаторы для этих чисел, потому что это просто не складывается с моей стороны. Я собираюсь исключить 2017 год из своего анализа интерпретаций.
Интерпретация 1
Похоже, что DevOps вытесняет традиционные операции. В 2013 году никто не называл себя специалистом по DevOps, но к 2020 и 2021 году цифры выглядят очень одинаково.
Стоит отметить, что в 2016 году показатели DevOps фактически затмили показатели «операций» за один год. Насколько я понимаю, в 2016 году многие компании начали просто переименовывать свои «операционные» команды в «DevOps», чтобы выглядеть круто.
Трудно обращать внимание на эти цифры, потому что, по моему мнению, DevOps в основном выполняется неправильно. . Я не верю, что в большинстве компаний названия "эксплуатация" и "девопс" сильно различаются.
Интерпретация 2
Категория DevOps, по-видимому, в последние годы меньше всего снижается, на самом деле, в 2022 году произошел хороший скачок. Однако, если вы посмотрите на "DevOps" и "операции" вместе, то категория по-прежнему немного снижается.
Интересно, что с самого начала «эксплуатация» падала, а «бэкэнд» — вверх до 2016 года, когда тенденция изменилась, и с тех пор она снижается.
Сначала я предположил, что мы просто наблюдаем ту же тенденцию, что и в веб-разработке: больше универсалов, меньше специалистов.
Однако я стал настроен скептически, потому что, просматривая все категории вакансий, я заметил, что почти все из них имеют тенденцию к снижению... чего явно не может быть, когда мы' смотреть на проценты - это игра с нулевой суммой.
Я решил добавить новый раздел в свой скрипт, чтобы копнуть дальше. Я подсчитал, сколько вакансий в среднем претендует каждый участник опроса, и получил следующие данные:
| год | бэкэнд | DevOps | операции | 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 |
Похоже, что с 2013 по 2015 год разработчикам разрешалось отправлять только один ответ, что помогает объяснить очень низкие цифры. Однако с 2019 по > 2021 года среднее количество рабочих мест на одного пользователя снижалось, что противоречит теории "большего числа универсалов".
Также стоит отметить, что с годами Stack Overflow фактически добавил более специализированные категории, которые я затем позволил себе сгруппировать в эти более широкие группы.
Так что на самом деле есть веские доказательства того, что разработчики больше специализируются или, по крайней мере, есть больше возможных способов специализации.
Тем не менее, даже после просмотра этих данных я думаю, что все еще есть веские основания утверждать, что back-end разработчики будут выполнять все больше и больше задач DevOps, особенно в небольших компаниях.
Тенденции данных: наука о данных, инженерия данных и серверная часть
| год | type_data_science | data_engineer | бэкэнд | |----|----|----|----| | 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 |
Интерпретация
Мне очень интересно, что инженерия данных действительно начала появляться в данных опросов только в 2019 году. До этого я предполагаю, что инженеры по обработке данных и специалисты по обработке данных поглотили эту роль. Эта новая специализация, безусловно, интересна.
Машинное обучение значительно выросло за последнее десятилетие, но, похоже, в 2017 году образовался небольшой «пузырь хайпа»?
Остальные данные
Я говорил о своих личных интерпретациях данных, которые мне показались наиболее интересными, но вот все данные, которые я собрал, чтобы вы могли проверить их самостоятельно:
| год | avg_jobs_per_user | полный стек | интерфейс | бэкэнд | DevOps | операции | мобильный | рабочий стол | встроенный | наука_данных | data_engineer | игра | управление | контроль качества | образование | дизайн | аналитик | маркетолог | игнорировать | |----|----|----|----|----|----|----|----|----|---- |----|----|----|----|----|----|----|----|----|---- | | 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 |
Необработанные данные CSV
Вот ссылка на необработанные данные CSV в Stack Overflow.
Мой сценарий
Вот полный скрипт Python, который я использовал для обработки чисел. Извините за неряшливость кода, я не тратил кучу времени на код.
Наиболее интересной частью скрипта, вероятно, является функция get_mapped_job
внизу, где я объединяю все многочисленные типы заданий, о которых сообщают пользователи переполнения стека, в те несколько, которые я включил в диаграмму.
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()
Также опубликовано здесь
Оригинал