Как придумать идею для пета в портфолио

Позабыты хлопоты,

Остановлен бег.

Вкалывают роботы,

А не человек!

Всем привет! Я middle fullstack-разработчик с опытом работы в айти ±4 года. Прежде, чем меня взяли на палубу моей первой галеры драить сортиры грести в такт с остальными, мне нужно было иметь хоть что-то в резюме. Тогда я стал думать, какой проектик-бы запилить да так, чтобы не слишком сложно, но чтобы я точно осилил сделать все по феншую. И знаете, для меня это стало проблемой. В 2020 году уже никого не удивишь калькулятором на WinForms (если вообще когда либо можно было) и страничкой «Обо мне» с вырвиглазным дизайном. Делать крутые интерпрайз штуковины мне было не по зубам, а делать в меру сложные (для того моего уровня), но бесполезные вещи, мне не хотелось: было желание, чтобы у написанной мною вещи был простор для реального применения.
Надеюсь, моя статья либо даст готовый ответ, либо поможет с ходом мысли для придумывания.

Лень — двигатель прогресса

1f8d07be75ff271d3ea84a5891827d30.png

Изначально хотел написать статью про то, как лень программиста конвертируется в маленькие забавные проектики, но потом решил развернуть мысль пошишре.

Я «учусь», если так вообще можно выразиться, в дистанционном вузе типа Синергии. На тему качества преподавания там вопросов, разумеется, не возникает. Но вот чем Синергия-like вузы лучше классических заведений, так это тем, что они не пытаются делать вид, что занимаются серьезным делом (я отучился на очном отделении почти 3 курса со средним баллом 4.6, так что знаю, что говорю). Такой вуз сразу оглашает правила игры и сам же покорно следует им: тебе раз в семестр дается пачка тестов (и еще вроде как какие-то вебинары, в сумме по 20 минут на предмет, но кому не пофиг). Твоя задача — решить эти тесты загуглить ответы на эти тесты.

В каждом тесте содержится один из вариантов тестового вопроса:

  1. Вставьте пропущенное слово;

  2. Выберите 1 из вариантов ответа;

  3. Выберите несколько из вариантов ответа;

  4. Сопоставьте варианты из двух колонок 1 к 1;

  5. Сопоставьте варианты из двух колонок 1 ко многим;

К текущему моменту я прорешал порядка 25 таких тестов, и на этом примере можно было наблюдать, как прогрессировала моя лень:

  • Сначала я перепечатывал текст вопроса и ответов в гугл в поисках инфы;

  • Потом выяснилось, что некоторые тесты целиком лежат с решением в гугле, поэтому остается по ним только через ctrl+F ходить;

  • В какой-то момент тесты кончились, а вопросы стали плохо гуглиться (потому что ушлые дельцы решения более поздних тестов начали продавать за деньги), поэтому я прибегнул к помощи ChatGPT (далее жпт);

  • Довольно быстро мне надоело перепечатывать вопросы, а скопировать их не удавалось из-за навешенного на них user-select: none (Вуз хочет поиграть в недотрогу). Тогда я начал копировать тексты из девтулзов. Но и это довольно быстро надоело, т.к. на 1 вопрос в среднем приходилось делать по 5 копирований из разных мест;

  • И тут я вспомнил, что я владею JS-ом…

Мне захотелось сделать что-то, что по нажатию кнопки будет формировать готовый вопрос для отправки в жпт. Немного покумекав, я прикинул, что для это задачи хорошо подходят расширения для браузера, а, немного погуглив, выяснил, что делать их в общем-то не сложно.
По итогу задача свелась к паре document.querySelector по нажатию кнопки. Код прилагаю ниже:

Исходный код расширения

Приведенный ниже код не является оптимальным, красивым, хорошим, качественным, и вообще в приличном обществе за такой харам отбивают почки. Приведен в качестве демонстрации

const button = document.createElement('button');
button.innerHTML = `



`
button.id = 'copy-question';

document.body.appendChild(button);

button.addEventListener('click', () => {

  let question = document.querySelector('.test-question-text-2 > p');
  let answers = [...document.querySelectorAll('.test-answers  label'), ...document.querySelectorAll('.test-answers  p')];

  if (answers.length == 0) {
    let otherAnswers = Array.from(document.querySelectorAll('.test-answers > div'));
    otherAnswers = otherAnswers.filter(x => x.textContent !== '' && x.textContent !== null && x.textContent !== undefined && x.textContent.length > 4)
    if (otherAnswers.length == 0) {
      let copyText = 'Вставь 1 слово вместо многоточия: \n' + question.textContent + '\n';
      navigator.clipboard.writeText(copyText)
    }
    else {
      let copyText = question.textContent + '\n';
      otherAnswers.forEach((el, ind) => copyText += `${ind + 1}) ${el.textContent}\n`)
      navigator.clipboard.writeText(copyText)
    }
  }
  else {
    let copyText = question.textContent + '\n';
    answers.forEach((el, ind) => copyText += `${ind + 1}) ${el.textContent}\n`)
    navigator.clipboard.writeText(copyText)
  }
})
{
  "manifest_version": 3,
  "name": "DumbQuestionCopier",
  "version": "1",
  "description": "Копирует дурацкие вопросы из тестов Синергии",
  "content_scripts": [
    {
      "matches": [
        "УРЛ_НА_СДО"
      ],
      "js": [
        "content.js"
      ],
      "css": [
        "styles.css"
      ]
    }
  ]
}
#copy-question {
    box-sizing: border-box;
    position: fixed;
    bottom: 100px;
    right: -10px;
    padding: 10px 20px 10px 10px;
    max-width: 70px;
    max-height: 60px;
    background-color: #007BFF;
    color: white;
    border: none;
    border-radius: 5px;
    cursor: pointer;
    z-index: 9999;
    transition: background-color 0.1s;
}

#copy-question:hover {
    background-color: #0056b3;
}

#copy-question:active {
    background-color: #1f6ab9;

По итогу там было три варианта сервировки верстки ответов без внятных селекторов, поэтому пришлось колхозить, ну да и пожалуйста. После написания этой штуки захотелось заспидранить 1 тест. В результате спидрана удалось решить 1 экзамен по Таймменеджменту из 30 вопросов за 4:53 из часа положенных.

Хватит ли этого для портфолио?

Нет, конечно. Но ведь приведенный выше пример — это уже «боль», которую мы, как айтишники, призваны облегчать. А что, если к приведенной выше штуке докрутить запросы к жпт и вывод ответа где-нибудь на экране? А, может быть, развить тему, сильно уточнить формируемые вопросы к жпт, и приходящий результат парсить и в автоматическом режиме указывать вариант ответа? Поздравляю, вот вы и изобрели ботоводство. А, может быть, сделать все это на условном C# путем скачивания страниц, анализа и запроса дальше, только не через браузер, а со стороны сервера? Поздравляю, вот вы и изобрели парсер сайтов. А потом берем полученный опыт и пытаемся накрутить распознание документов, а потом… ну, в общем, вы поняли схему.

На этот малюсенький костяк, приведенный под спойлером выше, можно накрутить уйму улучшайзингов и сделать неплохой проект, может быть даже коммерческий. А там глядишь уже и в первое плаванье вышел…

А может сразу посурьезней чего?

Извольте. Вот к примеру реальный бизнес-кейс, который осилить может каждый, стоит только захотеть.

Одно время я работал на фанерном складе. Специфика простая — владелец склада оптом скупает всякий брак с завода (с корой, с трещинами, расслоившийся), который подходит для внутренних работ, для будок собакам, для лесов и тп, а потом продает подороже в розницу. Однако конкуренция тут серьезная с другими такими-же дельцами.
Закупка происходила следующим образом — на почту заинтересованным лицам два раза в неделю приходила экселька с доступной номенклатурой. Заинтересованное лицо должно оперативно пометить цветом интересующие его пункты и отправить обратно. Соответственно, кто успел — тот и съел. И, как вы понимаете, многие заинтересованные лица в преддверии нужного часа судорожно сидели в томительном ожидании, а потом неистово бросались делать заливку. И, какой бы быстрой рукой на диком западе ты не был, нет-нет, да и профукаешь нужные тебе товары.
И тогда я им предложил такое решение — давайте я сделаю сервис, который будет мониторить вашу почту, скачивать оттуда эксельку, обрабатывать ее по правилу и отсылать обратно. Все это будет занимать полминуты, и никакой дротист с черным поясном не успеет за вами.
Договорились.

Для меня это стало определенным вызовом, т.к. на тот момент я никогда:

  • Не работал с фоновыми процессами;

  • Не работал с почтой;

  • Не работал с эксель таблицами;

Я посчитал, что это будет отличный пункт в портфолио. Жаль только, заказчики мне попались не очень добросовестные, из-за чего условий для выборки я так и не дождался, а проект так и не смог закончить.

Можно сказать, что шутка вееесьмааа узко направленная. Но, почему бы не попробовать проанализировать разные кейсы и попридумывать штук сверху?

76eab8ef82eb0e93752eda9df1f8e33d.png
  • А что если рассылка может быть не только по почте, а еще и в мессенджерах и соц-сетях? Вот и паттерн Адаптер пригодился;

  • А что если требуется гибкая настройка мониторинга по времени сканирования? Вот и с шедулерами разобрались;

  • Может UI для конфигурации накрутить? Вот и с вебом соприкоснулись;

Тьфу, еще одна недоделка?

Нет проблем — кейс, благодаря которому меня взяли на первую работу.

В начале второго курса я начал догадываться, что я ни на толику не приближаюсь к заветной цели преуспеть в гребле. Тогда я решил накопить на какие-нибудь вкатунские курсы типа УмелойКоробки или МозгКомпьютеромана. Бог отвел, и я додумался их спиратить воспользоваться open-source источниками. Когда я быстренько просмотрел все до конца, я понял, что узнал ровно 0.5 новых для себя полезных штук за весь курс.

Тем не менее, там затрагивалась тема, которая мне показалась интересной, — телеграмм боты. ТБ решал простую проблему — проблему интерфейса. В формошлёпство я еще не умел, винформы устарели, WPF мне не был близок, а консольки никому не упёрлись. А бот — это отличное современное решение проблем с простым пользовательским интерфейсом. Осталось только придумать смысл бота. Тогда я порылся в недрах самого себя и отыскал там мою главную на тот момент страсть — анекдоты. Так родилась идея телеграмм бота для рассылки анекдотов.

85249de6b0f94c7728ce4c0211030183.png

Тут я решил зарыться в такую штуку, как базы данных, конфигурирование приложения (про appsettings из коробки я еще не знал), немного в паттерны, документирование кода, планирование архитектуры в конце концов. Тёртым калачам может показаться, что всё, что я перечислил, — элементарщина, но не будем забывать, что речь идет о зелёном недо-джуне 4-летней давности — у меня не было плана, как попасть в айти, был только путь…


Честно говоря, я рассчитывал, что это будет только начало моего портфолио, но судьба повернулась ко мне нужным местом, и мне через кумовство нетворкинг удалось попасть на около-собес, где выяснилось, что компании требуется как раз что-нибудь типа телеграмм бота для покрытия одного бизнес-кейса. Иначе говоря, пара кнопок и инпут для отправки данных на сервак. Целое приложение было бы оверхедом.
Я продемонстрировал своего бота, моему будущему руководству это понравилось, и меня взяли на должность администратора баз данных (?), которому еще до кучи нужно по фасту разработать бота. О налаженных процессах речи не шло, но, думаю, в налаженные процессы с моей авоськой знаний и не пустили бы. На этой должности я неплохо разобрался в sql на боевой практике (и даже без единого truncate database!), имел удовольствие написать пару утилиток на c# , которые делали рутину по нажатию кнопки, а позже повысился до разраба.

Подведем итоги, как можно генерировать идеи для петов:

  • Ленитесь! Ищите, что вам делать лень, и как бы это сделать попроще с помощью программирования;

  • Быстрее, выше, сильнее! Придумайте, как можно обогнать конкурентов в том или ином деле с помощью автоматизации;

  • Пошел нафиг этот UI\UX! Для простоты реализации используйте мощностя ботов или пишите проекты без потребности в интерфейсе;

  • Не забывайте про хиханьки-да-хахоньки! Пользуйте лучшую мотивацию для разработки мега-сложных проектов — по-приколу;

© Habrahabr.ru