Уведомления

Группа в Telegram: @pythonsu

#1 Март 18, 2020 15:28:39

xahotaf452@hxqmail.com
Зарегистрирован: 2020-03-18
Сообщения: 1
Репутация: +  0  -
Профиль   Отправить e-mail  

Не взяли на работу из-за неправильно выполненного тестового задания, посмотрите?

Привет.
Устраиваюсь в одну контору на Junior Python 40 тыс.р до вычета. Сегодня ответили: “Бла бла бла…На данный момент не готовы сотрудничать по этой вакансии: есть замечания к тестовому”.
Выполнил тестовое за полтора дня - итого часов 8, учитывая, что ранее вообще на питоне не писал.
Прилагаю ТЗ и написанный скрипт + пояснения. Там плевое дело.
Опытные товарищи, посмотрите пожалуйста, где же я наделал “замечаний”. Может действительно это никуда не потянет.

Отредактировано xahotaf452@hxqmail.com (Март 18, 2020 15:28:50)

Прикреплённый файлы:
attachment ТЗ+скрипт+мои пояснения.zip (4,6 KБ)

Офлайн

#2 Март 18, 2020 17:33:36

FishHook
От:
Зарегистрирован: 2011-01-08
Сообщения: 8312
Репутация: +  568  -
Профиль   Отправить e-mail  

Не взяли на работу из-за неправильно выполненного тестового задания, посмотрите?

xahotaf452@hxqmail.com
Ну, как вам сказать, я бы вас наверное тоже не взял, и это действительно никуда не потянет.
Конечно, позиция джуниорская и много отвас не ожидают, но ваш код слишком наивен даже для джуна.
У вас реализована только одна функция. Это функция error. В которой вы захардкодили способ отображения ошибки с помошью функции print. Полезность этой функции сомнительна, чем это лучше простого использования print - не понятно. Очевидно, что вы подгоняете решение под ТЗ, типа это у вас такое повторное использование кода. Вы считаете, что остальной код не надо инкапсулировать в функции или методы, и вас больше нет подзадач которые можно повторно использовать? Очевидно, что вы не знакомы с концепцией разработки сверху вниз, не знаете что такое принцип единичной отвественности, никогда в жизни не слышали про юнит-тестирование. Алгоритм странный, зачем вам два цикла? Первым циклом вы собираете некий список словарей и тут же вторым циклом его перебираете. А зачем? Какой смысл во втором цикле? Это бы работало, если бы у вас был словарь с ключом ‘username’, а у вас список, который вы не изменяете. Я подозреваю, что ТЗ вы вообще не выполнили. На каких данных вы это тестировали? Каким образом?



Офлайн

#3 Март 18, 2020 19:52:47

AD0DE412
Зарегистрирован: 2019-05-12
Сообщения: 1130
Репутация: +  44  -
Профиль   Отправить e-mail  

Не взяли на работу из-за неправильно выполненного тестового задания, посмотрите?

В АРХИВЕ xahotaf452@hxqmail.com

————————————
ПОЯСНЕНИЯ
Скрипт для получения задач пользователей

Позволяет получить задачи по пользователям и сохранить инфу в файлы. Похож на генерацию файлов sitemap.xml для сайтов. Подразумевается использование с периодическим запуском на фоне как демона.
Требования и использование

Для работы скрипта необходим интерпретатор Python 3

Запуск python /path/to/script/get_users_tasks.py
Вариант 2 - актуализация всех файлов пачкой

Если требуется чтобы файлы актуализировались все пачкой или никак. Если юзеров и задач будет огромное кол-во, лучше не хранить в памяти все данные для создания файлов, а брать по несколько и записывать на диск, дабы не поймать out of memory.
Возможный алгоритм

Копируем боевую директорию DIR1 в DIR2. Генерируем файлы по актуальным данным в DIR2. По завершении создаем симлинк TASKS на DIR2 ln -s /path/dir2 /path/tasks. Теперь внешняя программа (человек) будет тянуть свежие файлы из DIR2. После первой итерации скрипта как демона предусматриваем смену симлинка, также после генерации rm /path/tasks.

Преимущества:

изолированность версий, на бою будут все актуальные файлы одной версии.

Недостатки:

возможен простой внешней программы, которая использует файлы, если сервер упадет между выполнением команд rm /path/tasks …server down… ln -s /path/dir{n} /path/tasks. Нивелируется автоматической проверкой и исправлением после подъема сервера.
требует больше места на харде, т.к. полностью копируется текущая актуальная директория.

Вариант 3 - используем СУБД

Храним данные в BLOB полях, весь процесс строим на транзакциях. Можно организовать динамическую генерацию файлов по запросу скриптом-прокладкой. Например GoogleBot пришел за /path/sitemap_1.xml, /path/sitemap_2.xml, а статичных файлов нет, там запросы обрабатывает дежурный скрипт, который генерирует сайтмап на лету и отдает.

Преимущества:

лучший вариант для данного рода задач.

Недостатки:

придется переделать прием входных данных у внешней программы с файлов на БД, в том числе скриптом обрабочиком.

————————————
ТЗ
Есть API для получения списка задач и api для получения списка юзеров:
https://jsonplaceholder.typicode.com/todos
https://jsonplaceholder.typicode.com/users
Используя только эти API составить отчёты по всем юзерам в отдельных текстовых файлах.

После запуска скрипта, рядом должна появиться директория “tasks” с текстовыми файлами. Файл называть по username пользователя в формате “Antonette.txt”
Внутри файла на первой строке писать полное имя, и рядом в < > записывать email. Через пробел от email записывать время составления отчёта в формате 23.09.2020 15:25
На второй строке записывать название компании, в которой работает юзер.
Третья строка должна быть пустой.
На четвёртой строке “Завершённые задачи:” и далее список названий завершённых задач.
После завершённых задач через пустую строку записать “Оставшиеся задачи:” и вывести остальные задачи.
Если название задачи больше 50 символов, то обрезать до 50 символов и добавить троеточие.

Пример файла:
```
Ervin Howell <Shanna@melissa.tv> 23.09.2020 15:25
Deckow-Crist

Завершённые задачи:
distinctio vitae autem nihil ut molestias quo

Оставшиеся задачи:
suscipit repellat esse quibusdam voluptatem incidu…
laborum aut in quam
```

Если файл для пользователя уже существует, то существующий файл переименовать, добавив в него время составления этого старого отчёта в формате “Antonette_2020-09-23T15:25.txt”
Таким образом, актуальный отчёт всегда будет без даты в названии. Старые отчёты не удаляются, а переименовываются.

Код должен быть чистым, без необоснованных повторений, с выделенем функций, где это уместно, с говорящими именами.
Код сделать максимально эффективным, но не в ущерб читабельности. Подсказка: следует избегать частых записей на диск.
Предусмотреть возможные сбои в сети или при записи на диск. Не должно быть наполовину сформированных файлов. Либо файл есть и он целиком корректный, либо его нет.
Если по юзеру однажды был создан отчёт, то всегда должен существовать актуальный отчёт без даты в названии. Не должно быть такого, что из-за сбоя в сети или т.п. остались только файлы с датами в названиях.
Если какие-то моменты не обговорены в задаче, то продумайте плюсы и минусы возможных вариантов, и выберите наиболее подходящий на ваш взгляд, чтобы потом можно было обосновать своё решение.
Предусмотреть крайние случаи (у пользователя нет задач, и т.п.).
Код должен быть оформлен по pep8.
Использовать местное время.
Программа должна корректно работать на linux (Debian, Ubuntu).
Можно использовать любые библиотеки.

————————————
КОД

 # -*- coding: utf-8 -*-
import os
import requests
import json
import time
TASKS_DIR = os.path.dirname(__file__) + '/tasks'
USERS_GET_LINK = 'https://jsonplaceholder.typicode.com/users'
TASKS_GET_LINK = 'https://jsonplaceholder.typicode.com/todos'
def error(text, is_exit=True):
    print(text)
    if is_exit:
        exit(0)
if not os.path.isdir(TASKS_DIR):
    try:
        os.mkdir(TASKS_DIR)
    except Exception:
        error(u'Не удалось создать боевую директорию')
try:
    users_data = requests.get(USERS_GET_LINK)
except Exception:
    error(u'Не удалось получить пользователей | get_http_error')
users_data = users_data.text
try:
    users_data_json = json.loads(users_data)
except Exception:
    error(u'Не удалось получить пользователей | json_error')
try:
    tasks_data = requests.get(TASKS_GET_LINK)
except Exception:
    error(u'Не удалось получить задачи | get_http_error')
tasks_data = tasks_data.text
try:
    tasks_data_json = json.loads(tasks_data)
except Exception:
    error(u'Не удалось получить задачи | json_error')
files_arr = []
for user in users_data_json:
    file_data = user['name'] + '<' + user['email'] + '> ' +\
        time.strftime('%d.%m.%Y %H:%M', time.localtime()) + '\n' +\
        user['company']['name'] + '\n\n'
    compl_tasks = ''
    uncompl_tasks = ''
    for task in tasks_data_json:
        if task['userId'] == user['id']:
            if len(task['title']) > 50:
                task_title = task['title'][:50] + '...'
            else:
                task_title = task['title']
            if task['completed']:
                compl_tasks += task_title + '\n'
            else:
                uncompl_tasks += task_title + '\n'
    file_data += u'Завершённые задачи:\n' + compl_tasks + '\n'
    file_data += u'Оставшиеся задачи:\n' + uncompl_tasks
    files_arr.append({'username': user['username'], 'data': file_data})
old_files_c = 0
new_files_c = 0
for file in files_arr:
    username = file['username']
    data = file['data']
    file_path = TASKS_DIR + '/' + username + '.txt'
    if os.path.isfile(file_path):
        new_path = TASKS_DIR + '/' + username + '_' +\
            time.strftime('%Y-%m-%dT%H:%M',
                          time.localtime(os.path.getctime(file_path))) + '.txt'
        try:
            os.rename(file_path, new_path)
            old_files_c += 1
        except Exception:
            error(u'Не удалось переименовать старый файл ' + file_path +
                  ' в ' + new_path + '\n', False)
    try:
        with open(file_path, 'w') as f:
            f.write(data.encode('utf-8'))
        new_files_c += 1
    except Exception:
        error(u'Не удалось создать актуальный файл ' + file_path + '\n', False)
print(u'Успешно создано новых файлов ' + str(new_files_c) +
      u'\nПереименованно старых: ' + str(old_files_c))



1. пжлст, форматируйте код, это в панели создания сообщений, выделите код и нажмите что то вроде
2. чтобы вставить изображение залейте его куда нибудь (например), нажмите и вставьте ссылку на его url

есчщо

Офлайн

#4 Март 18, 2020 19:54:05

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 10026
Репутация: +  857  -
Профиль   Отправить e-mail  

Не взяли на работу из-за неправильно выполненного тестового задания, посмотрите?

xahotaf452@hxqmail.com
Прилагаю ТЗ и написанный скрипт + пояснения. Там плевое дело.
Да довольно сложная задача. Ты должен написать код, который можно всегда перестроить под изменения в API. И с этим ты не справился. Если в API хоть что-то поменять (формат пользователей, например, или типы задач новые добавить), то твой код, который ты написал, можно только выкинуть. В нём нельзя следом за изменением в API поменять лишь маленький кусочек, чтобы всё продолжало работать правильно. И вот если представить, что ты не один такой код написал, а тысячу таких кодов написал, то сразу становится ясно, что после этого API нельзя менять, потому что все эти коды сломаются и их нужно будет выбрасывать и писать новые. А бизнес - это такая вещь, которая может потребовать резкого изменения API, из-за постоянно меняющихся, динамичных условий на рынке, где куча конкурентов сидит.

Так что вместо того, чтобы заполнять их проект твоим вот этим кодом, они просто ищут более компетентного джуна.

xahotaf452@hxqmail.com
учитывая, что ранее вообще на питоне не писал.
У тебя не в питоне проблема, ты в программировании не понимаешь. Тебе нужно программирование изучать. То есть питон - это кисточка и краски, а программирование - это изобразительное искусство. Вот если у тебя есть кисточка и краски, то ты всё равно нарисовать картину не сможешь, потому что рисовать не умеешь. А если художнику дать карандаш и бумагу, он нарисует такое, что ты и близко не повторишь.



Отредактировано py.user.next (Март 18, 2020 19:58:03)

Офлайн

#5 Март 18, 2020 20:13:49

AD0DE412
Зарегистрирован: 2019-05-12
Сообщения: 1130
Репутация: +  44  -
Профиль   Отправить e-mail  

Не взяли на работу из-за неправильно выполненного тестового задания, посмотрите?

> записывать email. Через пробел от email записывать время составления отчёта в формате 23.09.2020 15:25
На второй строке записывать название компании, в которой работает юзер.
Третья строка должна быть пустой.

я думаю вам нужно было создать класс (классы) с вот этим всем и методами к нему ну и так далее ну то есть машину для обработки данных а вы ее .. вручную что ли
зы эээ это предположение т.к. я даже не джун то есть из совсем неопытных
ззы https://pypi.org/project/sitemap-generator/



1. пжлст, форматируйте код, это в панели создания сообщений, выделите код и нажмите что то вроде
2. чтобы вставить изображение залейте его куда нибудь (например), нажмите и вставьте ссылку на его url

есчщо

Отредактировано AD0DE412 (Март 18, 2020 20:26:29)

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version