• Что делать если команда говнокодит?

    Мы стараемся не запускать эту проблему посредством code review, пытаясь распределить нагрузку по ревью между наиболее опытными участниками. Если в коде есть проблемы - тикет возвращается на доработку с замечаниями. Даже если банально не мержится с главной веткой. Попробуйте наладить этот процесс.

    Также мы всё собираемся настроить Continuous Integration. Jenkins может прогонять по коду проверку на соблюдение стандартов и покрытие тестами, а затем показывать результаты в красивом виде. Если чей-то коммит показывает более чем N ошибок в расчёте на единицу объёма кода - можно возвращать на исправление.

    Прямо уж откровенной копипасты и лапши у нас вроде бы нет почти. Мы стараемся избегать её, придумывать декларативные абстракции во всех случаях, где много тупого императивного кода, писать в функциональном стиле. Я думаю, что необходимы постоянные целенаправленные усилия в этом направлении, чтоб не допускать засилья энтропии.

    Ещё пара идей.
    • можно отправить разработчиков на какой-нибудь онлайн-курс по чистому коду, хотя я таких даже не знаю, но наверняка должны быть
    • или устраивать "хакатоны чистого кода", на коих команда разбивается на пары-тройки, каждая из коих пишет какую-нибудь маленькую, но полезную, а главное чистую и оттестированную штуковину, причём тема - по собственному выбору. Потраченное время - оплачиваемое, разумеется. Это уже зависит от руководства фирмы, согласится ли оно на такие развлечения.


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

    Ну и важно, чтобы у самих разработчиков была установка на хороший код, профессиональная гордость. У фрилансеров её, бывает, нет, а есть отношение "тяп-ляп, лишь бы работало и лишь бы часы оплатили, а там хоть потоп". Учитывая, что их заказчики занимаются code review нечасто, развитие такого отношения закономерно. Но всё-таки хочется писать красивые программы. Такое желание обязано быть.

    Я, конечно, сам не волшебник, я только учусь, и работа с командой - такая штука, которой надо постоянно учиться. Видимо, вы тоже учитесь; успехов в этом.
    Ответ написан
    2 комментария
  • ..............................?

    Мне, признаться, ничего не понятно, но почему вы пишете "псевдокод"? Синтаксис arr[0][1] - не псевдокод, он совершенно корректен. Он не решает задачу?

    Кроме того непонятно, как вы хотите транспонировать матрицу не применяя циклы? такой функции у родных списков Python нет. Есть такие функции у массивов в numpy.
    Ответ написан
    Комментировать
  • Как прописываются пути к django на серверах хостера?

    Самый простой способ - обратиться к автору, что было бы просто и естественно.

    • Если вы не обращаетесь к нему - это наводит на мысль о неком конфликте между вами. Другого объяснения не видно. При хороших отношениях он бы не отказался просто развернуть вам проект, это быстро, и вам это бы много не стоило даже при оплате по времени. Если он держал проект у себя, вы им пользовались, а потом просто пропал - ну... всякое бывает, но странно.
    • Коль скоро вы уже пользовались проектом прежде, пока он был на сервере разработчика, и теперь хотите продолжать - это значит, что с функциональной точки зрения проект вас устраивает.


    Если бы я читал ваш вопрос на фрилансе как заказ, то для меня бы это было звоночком. Если допустить, что конфликт между вами и автором произошёл по вашей вине, такая же ситуация может случиться и с другим исполнителем ваших заказов.
    Ответ написан
    1 комментарий
  • Как лучше создать версии сайта для разных городов в Django?

    Делать app для каждого города и копировать весь код, учитывая, что он одинаковый? нет смысла.

    Лучше рассмотреть проблему иначе. Начнём с зарегистрированных пользователей. Создайте модель City, обозначающую город. Также создайте custom user profile model под названием, скажем, Profile, которая привязана к User отношением one to one. В модели Profile добавьте внешний ключ на City.

    Наконец, реализуйте:
    • Выбор города (можно через AJAX)
    • Вывод на каждой странице сайта только той информации, что соответствует выбранному в request.user.profile.city городу.


    Если же поддержка города нужна и для анонимных пользователей (скорее всего это так), то стоит использовать переменную сессии в качестве дополнительного слоя. В одном из проектов у меня это делается так:

    1. Если есть переменная сессии, то используется она для фильтрации всего и вся
    2. Если её нет, но пользователь зарегистрирован - то берётся значение из БД и сохраняется в сессию, далее как в первом пункте
    3. Если и того нет - у меня запрещён доступ, так надо; ну а у вас пользователю (в вашем случае) надо предложить выбрать значение из списка.


    Таким образом и анонимусы поддерживаются, и при сбросе сессии у зарегистрированного юзера не теряется выбранный вариант.
    Ответ написан
    Комментировать
  • Как сделать у формы django поле "disabled" прямо в template?

    Это можно сделать в форме. Да и то, саму логику стоит писать во view. Сначала передать форме аргумент, который определяет, делать ли поля disabled. А затем, уже в форме, проставлять атрибуты полям.

    class MyView(...):
        form_class = MyForm
    
        def get_form_kwargs(self, ...):   # название метода условно, не уверен, что он так называется в generic views и даже что он есть :)
            kwargs = super(MyView, self).get_form_kwargs(...)
            kwargs.update({'disabled': not self.request.user.has_perm(...)})
            return kwargs
    
    class MyForm(...):
        def __init__(self, *args, **kwargs):
            is_disabled = kwargs.pop('disabled')
            super(MyForm, self).__init__(*args, **kwargs)
    
            if is_disabled:
                self.fields['foo'].widget.attrs.update({'disabled': 'disabled'})
    Ответ написан
    1 комментарий
  • Как правильно писать методы в CBV в Django?

    Я не думаю, что вам нужно делать всё с нуля. Надо использовать Django REST Framework, там уже есть базовые классы и уже есть логика, которую вы описали. В частности, имеется и авторизация по API token. Нужно только почитать документацию, разобрать, как там всё работает, и сделать свои классы, наследуя APIView (или что-то другое, что вам больше подойдёт).
    Ответ написан
    Комментировать
  • Насколько легко трудоустроиться программисту в 40+, 50+ итд лет?

    Чушь, на самом деле.

    1) Довод первый, личный. Ну вот у нас в команде есть разработчик, которому за 40, занимается JavaScript. Ощущения исключительно положительные. Товарищ имеет большой опыт и очень хорошо знает что делает. Да ещё и изучает что-то новое, куда-то движется в своей области.

    Ну, правда, знал я одного или двух товарищей, которым тоже за 40 и которые обладают опытом, но при этом обладают ещё и первосортной наглостью, более всего заботясь о том, чтоб засчитать побольше часов (неплохо оплачиваемых), а не о том, чтоб их код без ошибок работал. :) Просто у человека нет совести и желания профессионально делать свою работу, это бывает в любом возрасте.

    2) Довод второй, социологический. Как известно, у человека в течение последних веков продолжительность и всей жизни в целом, и составной её части - детства стала гораздо больше. В пушкинские времена крестьянские девочки в 13-14 лет были на выданье, на них ложилась вся тяжесть семейной жизни. Сейчас это совершеннейшие дети, им только в куклы играть.

    Двадцать лет назад парень 20 лет был взрослым и уже зачастую женился. Сейчас 20 - это молодо-зелено; крепко стать на ноги к этому возрасту, стать профессионалом в интеллектуально ёмкой отрасли деятельности - да невозможно практически; посему и о семье говорить рано, что бы там ни вопили охранители. Ну и естественным образом, коль скоро детство и молодость растягиваются, то и период активной интеллектуальной деятельности - тоже должен сдвигаться. Захватывая и 40 лет, и 50, а может и 60-70. Тут уж зависит от индивидуальных усилий.

    3) Довод третий, профессиональный. Слышал ли кто-нибудь, чтобы грамотного, квалифицированного профессора математики выгоняли в 50 лет? Конечно, он наверняка уже не может генерировать идеи, как он это делал в 20; математика - дело молодых. Но опыт его огромен, он пользуется уважением, учит студентов и аспирантов; совет его ценится и может серьёзно помочь молодым коллегам; он далеко не вне профессии. Почему так происходит? Потому что математика - это устоявшаяся область, математика - это профессия в полном смысле.

    Программирование пока не вполне созрело как профессия, потому что оно несколько моложе математики (ну, не менее чем на пять тысяч лет, если считать от Московского математического папируса с задачами по стереометрии). О том, что программирование должно стать профессией - см. пост Роберта Мартина, который мне очень нравится: blog.cleancoder.com/uncle-bob/2016/07/27/TheChurn.html

    UPD. Другие ораторы упомянули о психологических причинах: тим-лиду, которому 25, боязно показать команде своё невежество в сравнении дядькой, которому 40. Ну это больше говорит о тим-лиде, а не о дядьке. Тим-лиду следует посидеть вечерком в тиши и подумать, правильно ли он живёт в этом мире, коли руководствуется мерками каменного века и правилом "я начальник, ты дурак".
    Ответ написан
    2 комментария
  • Почему код не работает?

    • Строковые переменные не в кавычках
    • Не надо сравнивать result с bool2, ведь вы только что туда записали значение. Достаточно только одного оператора if. Попробуйте :)
    Ответ написан
    5 комментариев
  • Python3: Почему юнит-тест не работает?

    Попробуйте положить файл с тестируемыми функциями и файл с тестом в одну папку. Вы импортируете из модуля funcs_to_test, но как Python его найдёт?
    Ответ написан
  • Какой набор инструментов порекомендуете для работы с картами на Python?

    • Для хранения геоданных: PostgreSQL/PostGIS. django.contrib.gis обеспечивает родную поддержку, плюс библиотеки geos, geopy для расчётов расстояний и прочего.
    • Для взаимодействия с front-end - Django REST Framework со сторонними модулями, которые обеспечивают ей понимание gis-полей.
    • Для рисования карт на front end: js-библиотека Leaflet с использованием свободно доступных слоёв (google maps или open street map) и своим кодом, взаимодействующая с back end через вышеупомянутый API.
    Ответ написан
    1 комментарий
  • Какие есть книги или статьи для развития критического мышления?

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

    • К. Ю. Еськов. История Земли и жизни на ней; его же - записи лекций и даже художественные книжки (Последний кольценосец; Евангелие от Афрания)
    • А. В. Марков. Эволюция человека (в двух томах); Рождение сложности; Теория эволюции в свете новых открытий; многочисленные лекции, включая курс эволюции на биофаке МГУ
    • Любые, на самом деле, книжки с грифами фонда Династия или фонда Эволюция, какие отвечают вашим интересам
    Ответ написан
    Комментировать
  • Как выводит списка наиболее посещаемых страниц django?

    1) Django это фреймворк. Ничего само по себе не сохраняется.
    2) Вам потребуется или найти, или написать самому, middleware для подсчёта этих просмотров, и view для их вывода.
    3) Пожалуйста, пишите вопросы внимательно. Повторы слов, отсутствие запятых и точек. Умение грамотно выражать свои мысли - одно из необходимых качеств профессионального разработчика.
    Ответ написан
    Комментировать
  • Как организовать построчное чтение из файла с последующим удалением строки в Python?

    Не могу даже сказать, возможно ли это каким-либо извращением сделать, поскольку никогда не пытался. Такой подход в любом случае является плохим тоном. Нужно читать из одного файла, обрабатывать, и писать результат в другой файл.
    Ответ написан
    1 комментарий
  • Как освоить магию url в Django?

    Получив запрос на ссылку /post_list/, url matcher проходит по всем шаблонам в urls.py по очереди. Первй, который подходит - это:

    url(r'', include('blog.urls')),

    Поскольку регулярное выражение пустое, то Django берёт весь ваш URL и начинает искать его в blogs.urls, находя:

    url(r'^$', views.index, name='index'),

    Вам нужно как минимум ссылку на index убрать из blogs/urls.py в projectname/urls.py.
    Ответ написан
    1 комментарий
  • Какую систему выбрать для документирования рабочих процессов в фирме?

    Мы используем notion.so и довольны как летающие слоны.

    • Может не подойти тот факт, что это SaaS; но в любой момент можно экспортировать всю базу документов в формате Markdown.
    • После определённого объёма документов придётся перейти на тарифный план с оплатой по $8 в месяц за каждого пользователя с правами на редактирование. Все, кто не нуждается в редактировании, могут быть добавлены как гости (без включения в команду), они будут иметь доступ только на чтение и их может быть сколько угодно.
    Ответ написан
    Комментировать
  • Как вывести в файл результата переменной python?

    Самое простое -

    print("hey!")

    и потом вызвать ваш скрипт как

    python myscript.py > ~/myscript.log

    Для отладки, я думаю, это то что нужно. Если же вам нужны разные сообщения, уровни их, регулярный мониторинг логов - то действительно лучше logging.
    Ответ написан
    Комментировать
  • Можно ли реализовать запись в словарь по адресу в строковом формате в Python 3?

    У вас есть контроль над форматом строки адреса? Например, сделать её так:

    data.0.format

    Было бы проще. Теперь по поводу самого парсинга. Вы можете написать две функции.

    def parse_path(address):
        # парсим адрес address и возвращаем список его фрагментов.
        # пример: "['data'][0]['format']" -> ['data', 0, 'format']
        # Думаю, что регулярные выражения вкупе с небольшой обвязкой могут помочь.
        return path
    
    def recursive_set(datastructure, path, value):
        head, tail = path[0], path[1:]
        if tail:
            # есть ещё что делать дальше.
            return recursive_set(datastructure[head], tail, value)
        else:
            # Дальше ползти некуда, завершаем рекурсию.
            datastructure[head] = value
    
    recursive_set(
        {'data': ...},
        parse_address("['data'][0]['format']"),
        'doc'
    )
    Ответ написан
    1 комментарий