12 Oct 2008

Скажи мне, какой у тебя стиль кода, и я скажу, кто ты

Стиль кода (Code style) - настолько важная вещь, что многие IDE имеют встроенную поддержку создания, редактирования, использования, проверки и обмена различными стилями. Особенно важным придерживание определенного стиля становится при совместной работе над кодом. Поэтому многие организации стандартизировали свой стиль, придерживаться которого обязаны все участники кодирования, а на всякий случай существуют еще и специальные плагины, позволяющие приводить стиль к стандартному перед коммитом.

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

Например, вот как выглядит типичный метод, написанный в соответствии со стилем кода, принятым в Apache:

 private Map getNavigationCases(FacesContext facesContext)
    {
        ExternalContext externalContext = facesContext.getExternalContext();
        RuntimeConfig runtimeConfig = RuntimeConfig.getCurrentInstance(externalContext);

        if (_navigationCases == null || runtimeConfig.isNavigationRulesChanged())
        {
            synchronized(this)
            {
                if (_navigationCases == null || runtimeConfig.isNavigationRulesChanged())
                {
                    Collection rules = runtimeConfig.getNavigationRules();
                    int rulesSize = rules.size();
                    Map cases = new HashMap(HashMapUtils.calcCapacity(rulesSize));
                    List wildcardKeys = new ArrayList();

                    for (Iterator iterator = rules.iterator(); iterator.hasNext();)
                    {
                        NavigationRule rule = (NavigationRule) iterator.next();
                        String fromViewId = rule.getFromViewId();

                        //specification 7.4.2 footnote 4 - missing fromViewId is allowed:
                        if (fromViewId == null)
                        {
                            fromViewId = ASTERISK;
                        }
                        else
                        {
                            fromViewId = fromViewId.trim();
                        }

                        List list = (List) cases.get(fromViewId);
                        if (list == null)
                        {
                            list = new ArrayList(rule.getNavigationCases());
                            cases.put(fromViewId, list);
                            if (fromViewId.endsWith(ASTERISK))
                            {
                                wildcardKeys.add(fromViewId);
                            }
                        } else {
                            list.addAll(rule.getNavigationCases());
                        }

                    }
                    Collections.sort(wildcardKeys, new KeyComparator());

                    synchronized (cases)
                    {
                        // We do not really need this sychronization at all, but this
                        // gives us the peace of mind that some good optimizing compiler
                        // will not rearrange the execution of the assignment to an
                        // earlier time, before all init code completes
                        _navigationCases = cases;
                        _wildcardKeys = wildcardKeys;

                        runtimeConfig.setNavigationRulesChanged(false);
                    }
                }
            }
        }
        return _navigationCases;
    }


Кто-то, возможно, удивится наличию уродливых подчеркиваний перед названиями некоторых переменных. Однако все здесь имеет свой смысл! Подчеркивания становятся очень важны при выполнении следующих условий:
  1. Вы идиот, потому что не пользуетесь вообще никакой IDE (которые красиво выделяют переменные - члены класса, статические переменные и т. д). Вместо этого вы пишете код в блокноте.
  2. Вы дважды идиот, потому что пишете методы, постоянно уходящие за пределы экрана, так что при написании второй половины метода его сигнатура уже не видна.
  3. И, наконец, вы трижды идиот, потому что используете стиль кода, в котором открывающая фигурная скобка выносится на следующую строку, таким образом еще более удлинняя тело метода.
Так вот в этом случае, глядя на код, можно спутать переменную - член класса с какой-нибудь локальной переменной или параметром метода. Чтобы этой путаницы не происходило, названия всех полей класса начинаются с символа подчеркивания.

Как бы назвать организацию, стиль кода которой ориентирован на кубических идиотов?

3 comments:

Alexander Berezhnoy said...

Злой ты. :)
Во-первых, какое отношение подчёркивания имеют к длине метода и к их сигнатурам?
Во-вторых, открытый код публика больше читает, чем пишет, например, вот так:
https://svn.kobrix.com/webstuff/ticl/src/faces/com/kobrix/faces/application/NavigationHandlerImpl.java
Ну, и вообще, стремление сократить количество задействованных синапсов в мозгу при чтении кода - не есть безусловный признак идиотизма =)

Я лично подчёркивания ставлю, но не по этой причине, а потому что пишу в основном на Питоне =)

Fatal said...

Гм, по твоей классификации я являюсь идиотом всего единожды, неплохой результат, могло быть и хуже. Запоролся на последнем пункте - да я выношу открывающие фигурные скобки на новую строку. Ну и что, мне так удобнее. И при этом мои методы редко вылазят за пределы экрана - у меня экран большой :)
А вообще, чем ругать все подряд, привел бы рядом с примером чужого трижды идиотски написанного кода пример своего идеального. Все бы сравнили, а то может у тебя там, как в известном приколе:
"Мы остановились, добившись успешной компиляции следующего:
for(;P("\\n"),R-;P("|"))for(e=C;e-;P("_"+(*u++/8)%2))P("| "+(*u/4)%2);"
:)

Meddle said...

Меня не слишком сильно волнует, каким образом издеваются над своим кодом любители майкрософтовских созданий и прочих удивительных языков. Хотя нет, вру: меня это вообще не волнует. Ходят слухи, что в этом фантастическом мире бывает нормой использование названий типа mStrObj или m_p_fieldname. Я же говорю о мире Java, где использование подобных конструкций может привести разве что к взрыву мозга (регулярное лицезрение уродства вряд ли способно положительно влиять на психику), чем к уменьшению его загрузки.
В конце-концов, принцип DRY (Don't Repeat Yourself) еще никто не отменял (возможно, последователи какого-нибудь C++ и не в курсе об этом принципе или о том, что его можно эффективно применять используя средства, встроенные в сам язык, а не изобретая очередную гротескную конструкцию; но это же не повод тащить все это барахло в Java. Забавно, что статические члены класса ни знаками подчеркивания, ни любыми другими знаками при этом не выделяют, но это уже свидетельство внутренней противоречивости выбранного метода).

Простейший пример:

public void setId(int id) {
    this.id = id;
}

во всех отношениях лучше, чем

public void setId(int identifier)
{
    _id = identifier;
}

Во всех.