пятница, 2 июня 2017 г.

Олимпиадное vs Промышленное программирование

Задачи

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


Время

В промышленном программировании больше всего время тратится на чтение кода. Поэтому нужно тратить время на то, как назвать сущности, как структурировать код, разбить его на функции, классы, файлы. Организовывать структуру проектов.
В олимпиадном все решение, как правило, помещается в одном файле. Приоритет - скорость решения исходной задачи. Недочеты форматирования или неинформативные имена сущностей никого не заботят. Завтра это все будет ненужным.

Код

В промышленном программировании код пишется для дальнейшего сопровождения (то есть многократного чтения для расширения и правок). Он должен быть гибким, расширяемым. И самое главное - хорошо читаемым.
В олимпиадном программировании код пишется на один раз (write-only). Никто не собирается его в дальнейшем вычитывать, расширять или править баги.

Навыки

Главный навык в промышленном программировании - это общение. У кого-то спросить, кому-то подсказать. Пройти и провести ревью. Сделать проект лучше, чем был до внесения изменений.
В олимпиадном программировании в приоритете - алгоритмы и структуры данных. Максимально быстро и "грязно" придумать решение, уложившись в формальные требования, набрать и отладить. Все. Дальше хоть трава не расти.

Выводы

В результате мы наблюдаем два почти противоположных направления развития для программистов. И основная проблема, подтвержденная даже такими компаниями, как Google, что развитие в одном из направлений отрицательно коррелирует с развитием в другом.
То есть, практикуясь в промышленном программировании, привыкаешь много общаться, писать аккуратно, а в олимпиадном - как можно быстрее написать эффективное решение.
В итоге, приобретаешь "вредные" для другого направления навыки. И нужно прикладывать немало усилий, чтобы хотя-бы осознавать проблемы из-за различий в подходах.

понедельник, 22 мая 2017 г.

FizzBuzz на Python

Программа, печатает числа от 1 до 100, но если число кратно трем вместо числа выводит "Fizz", если число кратно пяти выводит "Buzz". Если число одновременно кратно и трем и пяти - "FizzBuzz".

Python 2
for i in range(1, 101):  # последнее число исключается из цикла
    if i % 15 == 0:
        print 'FizzBuzz'
    elif i % 3 == 0:
        print 'Fizz'
    elif i % 5 == 0:
        print 'Buzz'
    else:
        print i

Если хочется немного оптимизировать, можно заменить range на xrange, тогда не будет создаваться список из исходных чисел. В python 3 range это и есть xrange.

В Python 3 нужно вызывать print как функцию
for i in range(1, 101):
    if i % 15 == 0:
        print('FizzBuzz')
    elif i % 3 == 0:
        print('Fizz')
    elif i % 5 == 0:
        print('Buzz')
    else:
        print(i)

В таком решении дублируется проверка кратности трем и пяти - мы проверяем на кратность 15-ти, то есть трем и пяти одновременно. Также мы используем оператор (или функцию) вывода четыре раза. Этого можно избежать, используя конкатенацию строк.

for i in range(1, 101):
    s = ''
    if i % 3 == 0:
        s = 'Fizz'
    if i % 5 == 0:
        s += 'Buzz'
    if not s:
        s = str(i)
    print s

В таком варианте нет лишней операции получения остатка от деления, но есть проверка на пустоту строки и конкатенация строк.

пятница, 19 мая 2017 г.

Метод Main() в C#

Метод Main служит для задания точки входа в программу.
Visual Studio по умолчанию создает метод Main следующего вида:
class Program
{
    static void Main(string[] args)
    {    
    }
}

Расположение

Метод Main может быть расположен в любом классе программы. Но он должен быть только один. Если их будет несколько, компилятор выдаст ошибку:
error CS0017: Program has more than one entry point defined. Compile with /main to specify the type that contains the entry point.
То есть в такой ситуации нужно будет явно указывать метод, который будет являться точкой входа.

Область видимости

Метод является private, хотя явно это и не указано. Делается это для того, чтобы случайно не вызвать его из другого места. Хотя можно объявить его и public, все продолжит работать.

Возвращаемое значение

По-умолчанию метод Main не возвращает значения, но он может быть объявлен с возвращаемым значением типа int.
class Program
{
  static int Main(string[] args)
  {
    return 0;
  }
}

Почему static?

Метод Main должен быть статическим для того, чтобы его вызов был возможен без создания экземпляра класса, в котором он объявлен.

Аргументы

Метод Main принимает массив строк. В нем содержатся аргументы, переданные программе при запуске. Если ваша программа не обрабатывает переданные ей аргументы, можно их опустить:
class Program
{
  static int Main()
  {
    return 0;
  }
}

Самый короткий вариант не содержит аргументов, и не возвращает значения:
class Program
{
  static void Main()
  {
  }
}

четверг, 18 мая 2017 г.

Algorithms, Part I на Coursera

О курсе

На Сoursera есть хороший курс по алгоритмам и структурам данных для начинающих и повторяющих. Он на английском языке, но это не должно быть большой проблемой, так как лекции технические и основная часть слов будет знакома любому программисту.
Авторы курса Кевин Уэйн (Kevin Wayne) и Роберт Седжвик (Robert Sedgewick).

Плюсы


  • Курс бесплатен и постоянно перезапускается (его можно проходить снова и снова);
  • Все лекции можно найти также и на Youtube;
  • Много интересных практических заданий;
  • Замечательная система проверки, требующая сдавать довольно хорошо отлаженный код;
  • Для углубленного изучения материала можно взять книгу авторов.


Минусы


  • Проблемы со звуком в лекциях. Лектор часто и сильно кашляет в микрофон. Берегите уши;
  • Довольно поверхностное покрытие материала в лекциях (можно компенсировать книгой авторов);
  • Несоответствие лекций и заданий. В лекциях описываются алгоритмы и структуры данных;
  • Обещается, что мы будем реализовывать их сами. Вместо этого же приходится использовать структуры данных, написанные авторами курса для решения прикладных задач.


Вывод

Хороший курс. Рекомендую всем интересующимся программированием, алгоритмами и структурами данных.

вторник, 21 февраля 2017 г.

Python import this или дзен питона

Если в питоне написать строку import this, то в консоль будет выведен дзен питона.
По-моему, это можно считать дзеном разработки на любом языке программирования.
В оригинале оно выводится на английском, здесь я публикую его со своим переводом.

The Zen of Python, by Tim Peters
Дзен питона от Тима Питерса

Beautiful is better than ugly.
Красивое лучше уродливого.

Explicit is better than implicit.
Явное лучше неявного.

Simple is better than complex.
Простое лучше составного.

Complex is better than complicated.
Составное лучше сложного.

Flat is better than nested.
Плоское лучше вложенного.

Sparse is better than dense.
Разреженный лучше плотного.

Readability counts.
Читаемость важна.

Special cases aren't special enough to break the rules.
Особые случае недостаточно особенные для того, чтобы нарушать правила.

Although practicality beats purity.
Хотя практичность важнее чистоты.

Errors should never pass silently.
Ошибки никогда не должны происходить незаметно.

Unless explicitly silenced.
За исключением случаев намеренного подавления.

In the face of ambiguity, refuse the temptation to guess.
Перед лицом неоднозначности сопротивляйтесь искушению угадать.

There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Должен быть один, желательно только один, очевидный путь сделать это.
Хотя это может быть сначала неочевидно, если вы не голландец.

Now is better than never.
Although never is often better than *right* now.
Сейчас лучше чем никогда.
Хотя никогда часто лучше, чем прямо сейчас.

If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Если реализацию сложно объяснить, это плохая идея.
Если реализацию просто объяснить, это может быть хорошей идеей.

Namespaces are one honking great idea -- let's do more of those!
Пространства имен это просто великолепная идея - давайте делать больше пространств имен.

четверг, 26 января 2017 г.

Идеальное тестовое задание для программиста

This is not fine

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

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

Но кто же пишет такие программы, и, следовательно, хорошо справится с таким заданием?

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

Таким образом, компании набирают не тех, кто лучше будет справляться с работой, а тех, кто лучше делает тестовые задания.
Итак, каким же, по моему мнению, должно быть идеальное тестовое задание?
В идеале тестовое задание должно быть максимально похоже на реальную работу. И задание должно быть добавить фичу/исправить баг/провести рефакторинг/написать юнит-тест.
То есть это должна быть та самая программа с которой предстоит в будущем работать. И в этой системе, разумеется будет обычный букет всех реальных программ: куча багов, недоделанных и полувырезанных фич, дублирование кода и логики и т.д.
К сожалению, это, как правило, возможно лишь для open-source разработки, а также в случае наличия open-source альтернативы вашего продукта. Тогда задания можно давать на ней.
Разумным компромиссом мне кажется специальная программа (возможно, разработанная для выполнения предыдущих вариантов тестового задания), содержащая баги, недофичи, не полностью покрытая тестами. Она должна содержать хотя бы 10 тысяч строк кода.
Таким образом можно будет посмотреть на работу программиста в условиях гораздо ближе к его реальной будущей работе.