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

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

1. Подробные имена переменных

Часто программисты используют сокращенные имена переменных, чтобы сэкономить время на наборе кода. Однако это может привести к трудностям в понимании кода в будущем. Вместо этого старайтесь использовать более подробные имена переменных, которые описывают их назначение. Например:

# Плохо
x = 10
y = 20

# Хорошо
width = 10
height = 20

2. Применение оператора условия в одну строку

Вы можете использовать оператор условия (тернарный оператор) для более компактной записи условных выражений. Например:

// Обычное условие
if (isLogged) {
    message = "Пользователь авторизован";
} else {
    message = "Пользователь не авторизован";
}

// Использование тернарного оператора
message = isLogged ? "Пользователь авторизован" : "Пользователь не авторизован";

3. Сокрытие сложных выражений в функциях

Если у вас есть сложные выражения, которые используются несколько раз, оберните их в функции. Это сделает ваш код более читаемым и уменьшит дублирование кода. Например:

# Без функции
result = (x * y) + (x * z) - (y * z)

# С функцией
def calculate_result(x, y, z):
    return (x * y) + (x * z) - (y * z)

result = calculate_result(x, y, z)

4. Использование генераторов

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

# Без генератора
squared_numbers = []
for number in range(1, 11):
    squared_numbers.append(number ** 2)

# С генератором
squared_numbers = [number ** 2 for number in range(1, 11)]

5. Индексация списков с отрицательными значениями

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

my_list = [1, 2, 3, 4, 5]

# Обычная индексация
first_element = my_list[0]
last_element = my_list[len(my_list) - 1]

# Индексация с отрицательными значениями
first_element = my_list[-len(my_list)]
last_element = my_list[-1]

6. Работа с контекстными менеджерами

Контекстные менеджеры в Python позволяют управлять ресурсами, такими как файлы или соединения с базой данных, с помощью ключевого слова with. Это делает код более чистым и обеспечивает автоматическое закрытие ресурсов. Например:

# Без контекстного менеджера
file = open("example.txt", "r")
content = file.read()
file.close()

# С контекстным менеджером
with open("example.txt", "r") as file:
    content = file.read()
# Файл автоматически закроется после выхода из блока with

7. Использование декомпозиции и расширенной распаковки

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

# Обычное присваивание
x = [1, 2, 3]
a = x[0]
b = x[1]
c = x[2]

# Множественное присваивание с расширенной распаковкой
x = [1, 2, 3]
a, b, c = x

8. Оператор nullish (null-коалесценции)

Оператор nullish (в некоторых языках программирования, таких как JavaScript) позволяет удобно проверять, является ли значение null или undefined и, если да, присваивать значение по умолчанию. Это полезно, чтобы избежать ошибок из-за отсутствующих значений. Например:

// Без использования nullish оператора
let user = getUser();
let username = user ? user.name : "Гость";

// С использованием nullish оператора
let user = getUser();
let username = user?.name ?? "Гость";

9. Мемоизация функций

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

// Без мемоизации
function factorial(n) {
    if (n === 0) return 1;
    return n * factorial(n - 1);
}

// С мемоизацией
const memo = {};
function factorial(n) {
    if (n === 0) return 1;
    if (memo[n]) return memo[n];
    memo[n] = n * factorial(n - 1);
    return memo[n];
}

10. Использование регулярных выражений

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

// Пример валидации email с использованием регулярного выражения
const emailPattern = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/;
const isValidEmail = emailPattern.test("example@email.com");

Заключение

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

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


Большое спасибо за внимание!

Комментарии (17)


  1. Aquahawk
    06.10.2023 08:53
    +6

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

    Это точно не нормально. А пример с регуляркой просто некорректен от слова совсем


    1. Aceki
      06.10.2023 08:53

      Почему он некорректен?


      1. Aquahawk
        06.10.2023 08:53

        1. vinari Автор
          06.10.2023 08:53
          -2

          Прочтите внимательно заголовок статьи, и описание.
          Код предоставлен не в качестве использования, а в качестве примера. Прошу читайте внимательнее!


          1. BugM
            06.10.2023 08:53
            +2

            Любой код в статье должен быть корректным. Если есть цель специально написать некорректный код, то об этом должно быть прямо сказано около него.


          1. Aquahawk
            06.10.2023 08:53

            Тут отлично подвернулась статья про недра STL: https://habr.com/ru/articles/765760/ почитайте код, прогоните через свои критерии. И потом поймите что этот код работает в огромном количестве софта и выполнен весьма качественно.


  1. Sau
    06.10.2023 08:53
    +1

    Ещё советы от бывалого разработчика:

    1) Ставьте отступы в коде. Отступы помогают проще понимать вложенность блоков.

    2) Не пишите весь код в одном файле. Группируйте в файл функции (классы) одного вида.

    3) Не стоит отключать предупреждения (Warning) на сервере и в редакторе. Там могут быть полезные сообщения.

    4) В комментариях описывайте что делает блок кода.

    5) В комментарии в начале файла описывайте что находится в этом файле.

    6) В коммит лучше писать информацию о коммите, а не qwerty.


    1. vinari Автор
      06.10.2023 08:53

      Большое спасибо!

      Вы очень помогли мне )


    1. ClayRing
      06.10.2023 08:53

      Пожалуй добавлю советов от сеньора:

      1) Используйте циклы. Не нужно прописывать все итерации вручную прямо в коде.

      2) Старайтесь давать названия переменным используя только символы латинского алфавита.

      3) Перед тем как заливать код в прод желательно хотя-бы один раз его запустить и убедиться что он вообще запускается.

      4) Не пишите код в блокноте, установите какую-нибудь IDE или хотя-бы Notepad++/Sublime text.

      5) Дышать нужно через нос.

      6) Спать лучше ночью.


      1. ValeryIvanov
        06.10.2023 08:53

        Спасибо! Ваши советы помогли мне наконец отрефакторить мой код должным образом.

        Чистый код, как он есть
        # в этом файле мы считываем пользовательский ввод и складываем числа
        
        
        chislo = 0
        # складываем числа введённые пользователем используя встроенный оператор сложения +
        # цикл помогает нам сэкономить количество строк
        for vyrazhenie in ['input("Введите число 1")', 'input("Введите число 2")', 'input("Введите число 3")', 'input("Введите число 4")', 'input("Введите число 5")', 'input("Введите число 6")', 'input("Введите число 7")', 'input("Введите число 8")']:
            import matematika
            chislo = matematika.plus(chislo, eval(vyrazhenie))
        
        # заменяем числа на буквы если возможно для крутости
        # если вдруг понадобится вывести число в одну строку, то тот кто вызывывает код может перехватить вывод и сделать всё как надо!
        for zyfra in str(chislo):
            if zyfra == '0':
                print('O')
            elif zyfra == '1':
                print('l')
            elif zyfra == '3':
                print('')
            elif zyfra == '4':
                print('Ч')
            elif zyfra == '6':
                print('Б')
            elif zyfra == '8':
                print('B')
            elif zyfra == '9':
                print('Я')
            else:
                print(zyfra+'(NOT COOL)')
        
        


  1. MihaTeam
    06.10.2023 08:53
    +5

    Что за странный микс языков в статье?
    Почему в хабах только программирование, когда половина статьи, если не больше касается отдельных языков?
    По пунктам статьи:

    # Плохо

    x = 10
    y = 20

    # Хорошо
    width = 10
    height = 20


    1. Касается всех языков - ок (к слову, x,y - корректны, когда это касается координат, также как i,j,k относительно определенных случаев)

    // Обычное условие

    if (isLogged) {
    message = "Пользователь авторизован";
    } else {
    message = "Пользователь не авторизован";
    }

    // Использование тернарного оператора
    message = isLogged ? "Пользователь авторизован" : "Пользователь не авторизован";


    2. Касается JS и Python(если знать в нем аналогичный синтаксис), но не применимо в Go к примеру

    # Без функции

    result = (x * y) + (x * z) - (y * z)

    # С функцией
    def calculate_result(x, y, z):
    return (x * y) + (x * z) - (y * z)

    result = calculate_result(x, y, z)


    3.Касается всех языков, но статья называется программирование за гранью. Когда вынос кода в функцию вышел за грань?

    # Без генератора

    squared_numbers = []
    for number in range(1, 11):
    squared_numbers.append(number ** 2)

    # С генератором
    squared_numbers = [number ** 2 for number in range(1, 11)]


    4. Касается только Python. Это не генератор, это list comprehension, он при своем вызове создаст сразу список. Генератор объявляется или через yield или как list comprehension, НО с круглыми скобками.

    my_list = [1, 2, 3, 4, 5]

    # Обычная индексация
    first_element = my_list[0]
    last_element = my_list[len(my_list) - 1]

    # Индексация с отрицательными значениями
    first_element = my_list[-len(my_list)]
    last_element = my_list[-1]


    5. Касается далеко не всех языков, в JS синтаксиса к примеру этого нет, аналогичное [-1] надо выполнять через array.length-1

    # Без контекстного менеджера

    file = open("example.txt", "r")
    content = file.read()
    file.close()

    # С контекстным менеджером
    with open("example.txt", "r") as file:
    content = file.read()
    # Файл автоматически закроется после выхода из блока with

    1. Контекстные менеджеры есть далеко не везде, честно признаюсь такую реализацию знаю только в python. В Go есть что-то похожее - defer, но суть у него все же другая

    // Без использования nullish оператора

    let user = getUser();
    let username = user ? user.name : "Гость";

    // С использованием nullish оператора
    let user = getUser();
    let username = user?.name ?? "Гость";

    1. Снова JS - опять же аналога для Go или Python я не помню

    Так для кого эта статья? Для начинающего разработчика, который знает синтаксис Python и JS? Так если она для начинающих, то тут каждый пункт на отдельную статью можно растянуть, тк начинающему надо все рассказывать и уж точно не миксовать 2 языка в одной статье. Контекстные менеджеры на питоне и генераторы тоже отдельная глубокая тема, которая требует знания магических методов, включая асинхронные. Регулярные выражения тоже крайне глубокая тема, как минимум нужно уметь прикидывать пограничные случаи. И если она для начинающих, то что за программирование за гранью? Я к примеру, пришел как разработчик на Go прочитать статью, которая должны дать мне какие-то новые подходы, как разработчику в целом.

    И последний вопрос, что за тег "пиши код блядь"?


  1. ponikrf
    06.10.2023 08:53
    +2

    # Плохо x = 10 y = 20

    # Хорошо width = 10 height = 20

    Причем тут координаты и размер?

    Тогда уж плохо должно быть:

    w=10; h=20;

    Как по вашему с такими примерами люди для которых вы это пишите должны выстраивать ассоциативный ряд?

    message = isLogged ? "Пользователь авторизован" : "Пользователь не авторизован";

    Тут тоже все не так очевидно, если говорить про присваивание то это в целом норм тема, хотя некоторые тоже через чур подобным увлекаются. Да так удобнее присваивать через условие. Но если говорить про условаия в целом - то это отвратительное решение. Почему не расписали когда конкретно оно должно использоваться?

    Знаете, не особо хочется расписывать. Но тут все какое то недоделанное.

    Например, мог бы я рекомендовать использовать регекспы для парсинга текста? Ну все зависит от задачи, например если структурно я могу сплитами разбить строку как мне надо, я лучше это сделаю сплитами чем регулярными выражениями. Ньюансов много, например попробуйте регулярокой вытащить отрицательное число с плавающей точкой из строки типа "value = -1.232". Я бы даже не стал смотреть в сторону регулярных выражений с таким паттерном строки.

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

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


    1. aamonster
      06.10.2023 08:53

      Я бы вообще сказал, что w и h – это не плохо, а, возможно, хорошо. Это вполне устоявшиеся имена переменных (ещё можно cx, cy), не хуже, чем width/height, но короче и (что порой полезно) одинаковой длины. В общем, важна не длина имени, а его осмысленность.

      Ну и есть же правило: можно (и нужно) использовать короткие имена, когда их область видимости – несколько строк. Типа индексов i, j, координат x, y, размеров cx, cy.


  1. softaria
    06.10.2023 08:53
    +2

    Не надо снимать плохие фильмы. Надо снимать хорошие фильмы. ©


    1. dprotopopov
      06.10.2023 08:53
      +1

      Надо правильно, а не надо не правильно


  1. sergio_nsk
    06.10.2023 08:53

    Ещё забыт такой пример за гранью

    if (cond)
      return true;
    else
      return false;


  1. kekoz
    06.10.2023 08:53

    Уважаемый автор, помогите, у меня начались конвульсии прямо с самого начала. Прям загадка какая-то — вы, простите, как изучали язык, например, C?

    Вы понимаете семантику слов “оператор” (statement), “операция” (operator) и “выражение” (expression)? Судя по вашему примеру:

    // Обычное условие
    if (isLogged) {
        message = "Пользователь авторизован";
    } else {
        message = "Пользователь не авторизован";
    }
    
    // Использование тернарного оператора
    message = isLogged ? "Пользователь авторизован" : "Пользователь не авторизован";

    нет, не понимаете. В языках C/C++ нет “тернарного оператора”. И никогда не было. В них есть “условная операция” (conditional operator), и она — тернарная, да. А есть “условный оператор” (conditional statement), который не может быть ни унарным, ни бинарным, ни тернарным, поскольку арность — свойство операций, а не операторов.

    Признайтесь, хочется возмутиться “Да какая нафиг разница!”? Для результата переменной messageв вашем частном случае разницы нет. Но с позиций понимания языка эти конструкции совершенно разные как синтаксически, так и семантически. Операция в языках C/C++ может быть частью выражения (т.е. evaluated, имеет некоторое значение), а оператор вы ни в какое выражение не впихнёте, и никакого значения (value) у него нет. В C.

    За Python продолжать?